mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-12 15:50:15 -08:00
feat: support plugins (#878)
* fix(log): set the default logger * feat: support plugins * feat(plugin): add run command * feat(plugin): add uninstall command * test(plugin): add tests * chore(ci): pin go version * chore(ci): disable G204 * refactor: fix lint issues * feat(plugin): skip downloading installed plugins * feat: add TRIVY_RUN_AS_PLUGIN * support Ubuntu 20.10 (#876) * docs(README): update ubuntu versions (#877) * add MkDocs implementation (#870) * mkdocs: add top level nav * mkdocs: add installation nav * mkdocs: add quick-start nav * mkdocs: add examples nav * mkdocs: add CI nav * mkdocs: add vuln-detection nav * mkdocs: add comparison nav * mkdocs: add usage nav * mkdocs: add migration nav * mkdocs: add FAQ nav * mkdocs: add mkdocs.yml * mkdocs: add github workflow * docs: update documents * fix links * chore(ci): use ORG_GITHUB_TOKEN * chore(mkdocs): use mike * chore(ci): support dev * chore(ci): documentation test Co-authored-by: knqyf263 <knqyf263@gmail.com> * docs: add plugins * chore: remove stale workflow * refactor: fix lint issues Co-authored-by: Huang Huang <mozillazg101@gmail.com> Co-authored-by: aprp <doelaudi@gmail.com>
This commit is contained in:
5
.github/workflows/test.yaml
vendored
5
.github/workflows/test.yaml
vendored
@@ -9,6 +9,11 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
with:
|
||||
|
||||
@@ -56,6 +56,9 @@ issues:
|
||||
- linters:
|
||||
- gosec
|
||||
text: "Deferring unsafe method"
|
||||
- linters:
|
||||
- gosec
|
||||
text: "G204: Subprocess launched with variable"
|
||||
- linters:
|
||||
- errcheck
|
||||
text: "Close` is not checked"
|
||||
@@ -68,4 +71,4 @@ issues:
|
||||
exclude:
|
||||
- "should have a package comment, unless it's in another file for this package"
|
||||
exclude-use-default: false
|
||||
max-same-issues: 0
|
||||
max-same-issues: 0
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
l "log"
|
||||
"os"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
@@ -17,9 +15,6 @@ func main() {
|
||||
app := internal.NewApp(version)
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
if log.Logger != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
l.Fatal(err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
173
docs/plugins.md
Normal file
173
docs/plugins.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Plugins
|
||||
Trivy provides a plugin feature to allow others to extend the Trivy CLI without the need to change the Trivycode base.
|
||||
This plugin system was inspired by the plugin system used in [kubectl][kubectl], [Helm][helm], and [Conftest][conftest].
|
||||
|
||||
## Overview
|
||||
Trivy plugins are add-on tools that integrate seamlessly with Trivy.
|
||||
They provide a way to extend the core feature set of Trivy, but without requiring every new feature to be written in Go and added to the core tool.
|
||||
|
||||
- They can be added and removed from a Trivy installation without impacting the core Trivy tool.
|
||||
- They can be written in any programming language.
|
||||
- They integrate with Trivy, and will show up in Trivy help and subcommands.
|
||||
|
||||
!!! warning
|
||||
Trivy plugins available in public are not audited for security.
|
||||
You should install and run third-party plugins at your own risk, since they are arbitrary programs running on your machine.
|
||||
|
||||
|
||||
## Installing a Plugin
|
||||
A plugin can be installed using the `trivy plugin install` command.
|
||||
This command takes a url and will download the plugin and install it in the plugin cache.
|
||||
|
||||
Trivy adheres to the XDG specification, so the location depends on whether XDG_DATA_HOME is set.
|
||||
Trivy will now search XDG_DATA_HOME for the location of the Trivy plugins cache.
|
||||
The preference order is as follows:
|
||||
|
||||
- XDG_DATA_HOME if set and .trivy/plugins exists within the XDG_DATA_HOME dir
|
||||
- ~/.trivy/plugins
|
||||
|
||||
Under the hood Trivy leverages [go-getter][go-getter] to download plugins.
|
||||
This means the following protocols are supported for downloading plugins:
|
||||
|
||||
- OCI Registries
|
||||
- Local Files
|
||||
- Git
|
||||
- HTTP/HTTPS
|
||||
- Mercurial
|
||||
- Amazon S3
|
||||
- Google Cloud Storage
|
||||
|
||||
For example, to download the Kubernetes Trivy plugin you can execute the following command:
|
||||
|
||||
```bash
|
||||
$ trivy plugin install github.com/aquasecurity/trivy-plugin-kubectl
|
||||
```
|
||||
## Using Plugins
|
||||
Once the plugin is installed, Trivy will load all available plugins in the cache on the start of the next Trivy execution.
|
||||
A plugin will be made in the Trivy CLI based on the plugin name.
|
||||
To display all plugins, you can list them by `trivy --help`
|
||||
|
||||
```bash
|
||||
$ trivy --help
|
||||
NAME:
|
||||
trivy - A simple and comprehensive vulnerability scanner for containers
|
||||
|
||||
USAGE:
|
||||
trivy [global options] command [command options] target
|
||||
|
||||
VERSION:
|
||||
dev
|
||||
|
||||
COMMANDS:
|
||||
image, i scan an image
|
||||
filesystem, fs scan local filesystem
|
||||
repository, repo scan remote repository
|
||||
client, c client mode
|
||||
server, s server mode
|
||||
plugin, p manage plugins
|
||||
kubectl scan kubectl resources
|
||||
help, h Shows a list of commands or help for one command
|
||||
```
|
||||
|
||||
As shown above, `kubectl` subcommand exists in the `COMMANDS` section.
|
||||
To call the kubectl plugin and scan existing Kubernetes deployments, you can execute the following command:
|
||||
|
||||
```
|
||||
$ trivy kubectl deployment <deployment-id> -- --ignore-unfixed --severity CRITICAL
|
||||
```
|
||||
|
||||
Internally the kubectl plugin calls the kubectl binary to fetch information about that deployment and passes the using images to Trivy.
|
||||
You can see the detail [here][trivy-plugin-kubectl].
|
||||
|
||||
If you want to omit even the subcommand, you can use `TRIVY_RUN_AS_PLUGIN` environment variable.
|
||||
|
||||
```bash
|
||||
$ TRIVY_RUN_AS_PLUGIN=kubectl trivy job your-job -- --format json
|
||||
```
|
||||
|
||||
## Installing and Running Plugins on the fly
|
||||
`trivy plugin run` installs a plugin and runs it on the fly.
|
||||
If the plugin is already present in the cache, the installation is skipped.
|
||||
|
||||
```bash
|
||||
trivy plugin run github.com/aquasecurity/trivy-plugin-kubectl pod your-pod -- --exit-code 1
|
||||
```
|
||||
|
||||
## Uninstalling Plugins
|
||||
Specify a plugin name with `trivy plugin uninstall` command.
|
||||
|
||||
```bash
|
||||
$ trivy plugin uninstall kubectl
|
||||
```
|
||||
|
||||
## Building Plugins
|
||||
Each plugin has a top-level directory, and then a plugin.yaml file.
|
||||
|
||||
```bash
|
||||
your-plugin/
|
||||
|
|
||||
|- plugin.yaml
|
||||
|- your-plugin.sh
|
||||
```
|
||||
|
||||
In the example above, the plugin is contained inside of a directory named `your-plugin`.
|
||||
It has two files: plugin.yaml (required) and an executable script, your-plugin.sh (optional).
|
||||
|
||||
The core of a plugin is a simple YAML file named plugin.yaml.
|
||||
Here is an example YAML of trivy-plugin-kubectl plugin that adds support for Kubernetes scanning.
|
||||
|
||||
```yaml
|
||||
name: "kubectl"
|
||||
repository: github.com/aquasecurity/trivy-plugin-kubectl
|
||||
version: "0.1.0"
|
||||
usage: scan kubectl resources
|
||||
description: |-
|
||||
A Trivy plugin that scans the images of a kubernetes resource.
|
||||
Usage: trivy kubectl TYPE[.VERSION][.GROUP] NAME
|
||||
platforms:
|
||||
- selector: # optional
|
||||
os: darwin
|
||||
arch: amd64
|
||||
uri: ./trivy-kubectl # where the execution file is (local file, http, git, etc.)
|
||||
bin: ./trivy-kubectl # path to the execution file
|
||||
- selector: # optional
|
||||
os: linux
|
||||
arch: amd64
|
||||
uri: https://github.com/aquasecurity/trivy-plugin-kubectl/releases/download/v0.1.0/trivy-kubectl.tar.gz
|
||||
bin: ./trivy-kubectl
|
||||
```
|
||||
|
||||
The `plugin.yaml` field should contain the following information:
|
||||
|
||||
- name: The name of the plugin. This also determines how the plugin will be made available in the Trivy CLI. For example, if the plugin is named kubectl, you can call the plugin with `trivy kubectl`. (required)
|
||||
- version: The version of the plugin. (required)
|
||||
- usage: A short usage description. (required)
|
||||
- description: A long description of the plugin. This is where you could provide a helpful documentation of your plugin. (required)
|
||||
- platforms: (required)
|
||||
- selector: The OS/Architecture specific variations of a execution file. (optional)
|
||||
- os: OS information based on GOOS (linux, darwin, etc.) (optional)
|
||||
- arch: The architecture information based on GOARCH (amd64, arm64, etc.) (optional)
|
||||
- uri: Where the executable file is. Relative path from the root directory of the plugin or remote URL such as HTTP and S3. (required)
|
||||
- bin: Which file to call when the plugin is executed. Relative path from the root directory of the plugin. (required)
|
||||
|
||||
The following rules will apply in deciding which platform to select:
|
||||
|
||||
- If both `os` and `arch` under `selector` match the current platform, search will stop and the platform will be used.
|
||||
- If `selector` is not present, the platform will be used.
|
||||
- If `os` matches and there is no more specific `arch` match, the platform will be used.
|
||||
- If no `platform` match is found, Trivy will exit with an error.
|
||||
|
||||
After determining platform, Trivy will download the execution file from `uri` and store it in the plugin cache.
|
||||
When the plugin is called via Trivy CLI, `bin` command will be executed.
|
||||
|
||||
The plugin is responsible for handling flags and arguments. Any arguments are passed to the plugin from the `trivy` command.
|
||||
|
||||
## Example
|
||||
https://github.com/aquasecurity/trivy-plugin-kubectl
|
||||
|
||||
[kubectl]: https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/
|
||||
[helm]: https://helm.sh/docs/topics/plugins/
|
||||
[conftest]: https://www.conftest.dev/plugins/
|
||||
[go-getter]: https://github.com/hashicorp/go-getter
|
||||
[trivy-plugin-kubectl]: https://github.com/aquasecurity/trivy-plugin-kubectl
|
||||
|
||||
5
go.mod
5
go.mod
@@ -19,7 +19,6 @@ require (
|
||||
github.com/docker/docker v20.10.3+incompatible
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d // indirect
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20200809112317-0581fc3aee2d // indirect
|
||||
github.com/go-redis/redis/v8 v8.4.0
|
||||
github.com/goccy/go-yaml v1.8.2 // indirect
|
||||
github.com/golang/protobuf v1.4.3
|
||||
@@ -27,6 +26,7 @@ require (
|
||||
github.com/google/go-github/v28 v28.1.1
|
||||
github.com/google/wire v0.4.0
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
|
||||
github.com/hashicorp/go-getter v1.5.2
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/knqyf263/go-apk-version v0.0.0-20200609155635-041fdbb8563f
|
||||
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
|
||||
@@ -36,6 +36,7 @@ require (
|
||||
github.com/mitchellh/copystructure v1.1.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/open-policy-agent/opa v0.25.2
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||
github.com/spf13/afero v1.2.2
|
||||
github.com/stretchr/objx v0.3.0 // indirect
|
||||
@@ -49,6 +50,6 @@ require (
|
||||
google.golang.org/protobuf v1.25.0
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
|
||||
)
|
||||
|
||||
23
go.sum
23
go.sum
@@ -39,6 +39,7 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||
cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=
|
||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||
code.gitea.io/sdk/gitea v0.12.0/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
|
||||
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
|
||||
@@ -217,6 +218,7 @@ github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
@@ -326,7 +328,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -392,8 +393,6 @@ github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d h1:rtM8HsT3NG37YPj
|
||||
github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20200809112317-0581fc3aee2d h1:st1tmvy+4duoRj+RaeeJoECWCWM015fBtf/4aR+hhqk=
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20200809112317-0581fc3aee2d/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/proto v1.6.15/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
|
||||
@@ -411,7 +410,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
|
||||
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
@@ -600,7 +598,9 @@ github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSN
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE=
|
||||
github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
@@ -623,8 +623,10 @@ github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs167
|
||||
github.com/google/wire v0.4.0 h1:kXcsA/rIGzJImVqPdhfnr6q0xsS9gU0515q1EPpJ9fE=
|
||||
github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
|
||||
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
@@ -673,7 +675,9 @@ github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FK
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-getter v1.5.2 h1:XDo8LiAcDisiqZdv0TKgz+HtX3WN7zA2JD1R1tjsabE=
|
||||
github.com/hashicorp/go-getter v1.5.2/go.mod h1:orNH3BTYLu/fIxGIdLjLoAJHWMDQ/UKQr5O4m3iBuoo=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
@@ -685,6 +689,7 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+
|
||||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
|
||||
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
@@ -744,6 +749,7 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
@@ -758,6 +764,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ=
|
||||
github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
@@ -852,6 +859,7 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
@@ -1048,8 +1056,9 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryancurrah/gomodguard v1.0.4/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE=
|
||||
github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUccKSJBU0UMXJFVM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
@@ -1074,7 +1083,6 @@ github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q
|
||||
github.com/shteou/go-ignore v0.3.0/go.mod h1:+MO315cnlHh5qKX1xSa41OlWzOuAecXCNwcKUcbL+f0=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
@@ -1174,6 +1182,7 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
||||
github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA=
|
||||
@@ -1618,6 +1627,7 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
|
||||
google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||
google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w=
|
||||
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -1721,7 +1731,6 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
|
||||
gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/internal/artifact"
|
||||
"github.com/aquasecurity/trivy/internal/client"
|
||||
"github.com/aquasecurity/trivy/internal/plugin"
|
||||
"github.com/aquasecurity/trivy/internal/server"
|
||||
tdb "github.com/aquasecurity/trivy/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
@@ -282,8 +284,18 @@ func NewApp(version string) *cli.App {
|
||||
NewRepositoryCommand(),
|
||||
NewClientCommand(),
|
||||
NewServerCommand(),
|
||||
NewPluginCommand(),
|
||||
}
|
||||
app.Commands = append(app.Commands, plugin.LoadCommands()...)
|
||||
|
||||
runAsPlugin := os.Getenv("TRIVY_RUN_AS_PLUGIN")
|
||||
if runAsPlugin == "" {
|
||||
app.Action = artifact.ImageRun
|
||||
} else {
|
||||
app.Action = func(ctx *cli.Context) error {
|
||||
return plugin.RunWithArgs(ctx.Context, runAsPlugin, ctx.Args().Slice())
|
||||
}
|
||||
}
|
||||
app.Action = artifact.ImageRun
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -499,3 +511,35 @@ func NewServerCommand() *cli.Command {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewPluginCommand is the factory method to add plugin command
|
||||
func NewPluginCommand() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "plugin",
|
||||
Aliases: []string{"p"},
|
||||
Usage: "manage plugins",
|
||||
Subcommands: cli.Commands{
|
||||
{
|
||||
Name: "install",
|
||||
Aliases: []string{"i"},
|
||||
Usage: "install a plugin",
|
||||
ArgsUsage: "URL | FILE_PATH",
|
||||
Action: plugin.Install,
|
||||
},
|
||||
{
|
||||
Name: "uninstall",
|
||||
Aliases: []string{"u"},
|
||||
Usage: "uninstall a plugin",
|
||||
ArgsUsage: "PLUGIN_NAME",
|
||||
Action: plugin.Uninstall,
|
||||
},
|
||||
{
|
||||
Name: "run",
|
||||
Aliases: []string{"r"},
|
||||
Usage: "run a plugin on the fly",
|
||||
ArgsUsage: "PLUGIN_NAME [PLUGIN_OPTIONS]",
|
||||
Action: plugin.Run,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
117
internal/plugin/plugin.go
Normal file
117
internal/plugin/plugin.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/internal/config"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/plugin"
|
||||
)
|
||||
|
||||
// Install installs a plugin
|
||||
func Install(c *cli.Context) error {
|
||||
if c.NArg() != 1 {
|
||||
cli.ShowSubcommandHelpAndExit(c, 1)
|
||||
}
|
||||
|
||||
if err := initLogger(c); err != nil {
|
||||
return xerrors.Errorf("initialize error: %w", err)
|
||||
}
|
||||
|
||||
url := c.Args().First()
|
||||
if _, err := plugin.Install(c.Context, url, true); err != nil {
|
||||
return xerrors.Errorf("plugin install error: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Uninstall uninstalls the plugin
|
||||
func Uninstall(c *cli.Context) error {
|
||||
if c.NArg() != 1 {
|
||||
cli.ShowSubcommandHelpAndExit(c, 1)
|
||||
}
|
||||
|
||||
if err := initLogger(c); err != nil {
|
||||
return xerrors.Errorf("initialize error: %w", err)
|
||||
}
|
||||
|
||||
pluginName := c.Args().First()
|
||||
if err := plugin.Uninstall(pluginName); err != nil {
|
||||
return xerrors.Errorf("plugin uninstall error: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run runs the plugin
|
||||
func Run(c *cli.Context) error {
|
||||
if c.NArg() < 1 {
|
||||
cli.ShowSubcommandHelpAndExit(c, 1)
|
||||
}
|
||||
|
||||
if err := initLogger(c); err != nil {
|
||||
return xerrors.Errorf("initialize error: %w", err)
|
||||
}
|
||||
|
||||
url := c.Args().First()
|
||||
args := c.Args().Tail()
|
||||
return RunWithArgs(c.Context, url, args)
|
||||
}
|
||||
|
||||
// RunWithArgs runs the plugin with arguments
|
||||
func RunWithArgs(ctx context.Context, url string, args []string) error {
|
||||
pl, err := plugin.Install(ctx, url, false)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("plugin install error: %w", err)
|
||||
}
|
||||
|
||||
if err = pl.Run(ctx, args); err != nil {
|
||||
return xerrors.Errorf("unable to run %s plugin: %w", pl.Name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadCommands loads plugins as subcommands
|
||||
func LoadCommands() cli.Commands {
|
||||
var commands cli.Commands
|
||||
plugins, err := plugin.LoadAll()
|
||||
if err != nil {
|
||||
log.Logger.Debugf("no plugins were loaded")
|
||||
return nil
|
||||
}
|
||||
for _, p := range plugins {
|
||||
cmd := &cli.Command{
|
||||
Name: p.Name,
|
||||
Usage: p.Usage,
|
||||
Action: func(c *cli.Context) error {
|
||||
if err := initLogger(c); err != nil {
|
||||
return xerrors.Errorf("initialize error: %w", err)
|
||||
}
|
||||
|
||||
if err := p.Run(c.Context, c.Args().Slice()); err != nil {
|
||||
return xerrors.Errorf("plugin error: %w", err)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
SkipFlagParsing: true,
|
||||
}
|
||||
commands = append(commands, cmd)
|
||||
}
|
||||
return commands
|
||||
}
|
||||
|
||||
func initLogger(ctx *cli.Context) error {
|
||||
conf, err := config.NewGlobalConfig(ctx)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("config error: %w", err)
|
||||
}
|
||||
|
||||
if err = log.InitLogger(conf.Debug, conf.Quiet); err != nil {
|
||||
return xerrors.Errorf("failed to initialize a logger: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -57,6 +57,7 @@ nav:
|
||||
- Repository: usage/repo.md
|
||||
- Client: usage/client.md
|
||||
- Server: usage/server.md
|
||||
- Plugins: plugins.md
|
||||
- Air-Gapped Environment: air-gap.md
|
||||
- Comparison with Other Scanners: comparison.md
|
||||
- FAQ: faq.md
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -159,10 +158,6 @@ func TestClient_NeedsUpdate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
if err := log.InitLogger(false, true); err != nil {
|
||||
require.NoError(t, err, "failed to init logger")
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
@@ -241,9 +236,6 @@ func TestClient_Download(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
err := log.InitLogger(false, true)
|
||||
require.NoError(t, err, "failed to init logger")
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
mockConfig := new(mockDbOperation)
|
||||
@@ -351,9 +343,6 @@ func TestClient_UpdateMetadata(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
mockConfig := new(mockDbOperation)
|
||||
err := log.InitLogger(false, true)
|
||||
require.NoError(t, err, "failed to init logger")
|
||||
|
||||
mockConfig.ApplyGetMetadataExpectation(tc.getMetadataExpectation)
|
||||
mockConfig.ApplyStoreMetadataExpectation(tc.storeMetadataExpectation)
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/dbtest"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -62,7 +61,6 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_ = dbtest.InitDB(t, tt.fixtures)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/bundler"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func TestRubyGemsComparer_IsVulnerable(t *testing.T) {
|
||||
@@ -93,7 +92,6 @@ func TestRubyGemsComparer_IsVulnerable(t *testing.T) {
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
log.InitLogger(false, false)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := bundler.RubyGemsComparer{}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/dbtest"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/cargo"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -77,7 +76,6 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_ = dbtest.InitDB(t, tt.fixtures)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
"github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/comparer"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func TestGenericComparer_IsVulnerable(t *testing.T) {
|
||||
@@ -85,7 +84,6 @@ func TestGenericComparer_IsVulnerable(t *testing.T) {
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
log.InitLogger(false, false)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
v := comparer.GenericComparer{}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/dbtest"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/composer"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -61,7 +60,6 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_ = dbtest.InitDB(t, tt.fixtures)
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/dbtest"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/comparer"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/ghsa"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -100,7 +99,6 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_ = dbtest.InitDB(t, tt.fixtures)
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func TestComparer_IsVulnerable(t *testing.T) {
|
||||
@@ -76,7 +75,6 @@ func TestComparer_IsVulnerable(t *testing.T) {
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
log.InitLogger(false, false)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := maven.Comparer{}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/dbtest"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/npm"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -69,7 +68,6 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_ = dbtest.InitDB(t, tt.fixtures)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/npm"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func TestNpmComparer_IsVulnerable(t *testing.T) {
|
||||
@@ -129,7 +128,6 @@ func TestNpmComparer_IsVulnerable(t *testing.T) {
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
log.InitLogger(false, false)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := npm.Comparer{}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/dbtest"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/python"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
@@ -62,7 +61,6 @@ func TestAdvisory_DetectVulnerabilities(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_ = dbtest.InitDB(t, tt.fixtures)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/detector/library/python"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func TestPep440Comparer_IsVulnerable(t *testing.T) {
|
||||
@@ -107,7 +106,6 @@ func TestPep440Comparer_IsVulnerable(t *testing.T) {
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
log.InitLogger(false, false)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := python.Pep440Comparer{}
|
||||
|
||||
@@ -2,7 +2,6 @@ package alpine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,15 +11,8 @@ import (
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_Detect(t *testing.T) {
|
||||
type args struct {
|
||||
osVer string
|
||||
|
||||
@@ -87,7 +87,6 @@ func TestScanner_Detect(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("get vulnerabilities fails to fetch", func(t *testing.T) {
|
||||
_ = log.InitLogger(true, false)
|
||||
s := &Scanner{
|
||||
l: log.Logger,
|
||||
ac: MockAmazonConfig{
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
package debian
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
|
||||
ftypes "github.com/aquasecurity/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -51,11 +49,6 @@ func (mdc MockDebianConfig) Get(a string, b string) ([]dbTypes.Advisory, error)
|
||||
return []dbTypes.Advisory{}, nil
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_IsSupportedVersion(t *testing.T) {
|
||||
vectors := map[string]struct {
|
||||
now time.Time
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package oracle
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -14,15 +13,9 @@ import (
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
oracleoval "github.com/aquasecurity/trivy-db/pkg/vulnsrc/oracle-oval"
|
||||
"github.com/aquasecurity/trivy/pkg/dbtest"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_IsSupportedVersion(t *testing.T) {
|
||||
vectors := map[string]struct {
|
||||
clock clock.Clock
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package photon
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
ftypes "github.com/aquasecurity/fanal/types"
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -30,11 +28,6 @@ func (mpc MockPhotonConfig) Get(a string, b string) ([]dbTypes.Advisory, error)
|
||||
return []dbTypes.Advisory{}, nil
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_Detect(t *testing.T) {
|
||||
t.Run("happy path", func(t *testing.T) {
|
||||
s := &Scanner{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package redhat
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,15 +11,9 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_Detect(t *testing.T) {
|
||||
type args struct {
|
||||
osVer string
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package suse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -11,7 +10,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
susecvrf "github.com/aquasecurity/trivy-db/pkg/vulnsrc/suse-cvrf"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
|
||||
"k8s.io/utils/clock"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
@@ -36,11 +34,6 @@ func (msc MockSuseConfig) Get(a string, b string) ([]dbTypes.Advisory, error) {
|
||||
return []dbTypes.Advisory{}, nil
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_IsSupportedVersion(t *testing.T) {
|
||||
vectors := map[string]struct {
|
||||
clock clock.Clock
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ubuntu
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -10,8 +9,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
|
||||
type MockUbuntuConfig struct {
|
||||
@@ -33,11 +30,6 @@ func (muc MockUbuntuConfig) Get(a string, b string) ([]dbTypes.Advisory, error)
|
||||
return []dbTypes.Advisory{}, nil
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestScanner_IsSupportedVersion(t *testing.T) {
|
||||
vectors := map[string]struct {
|
||||
now time.Time
|
||||
|
||||
@@ -13,9 +13,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -411,9 +408,6 @@ func TestClient_DownloadDB(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
err := log.InitLogger(false, true)
|
||||
require.NoError(t, err, "Init logger failed")
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.URL.Path {
|
||||
case "/happy":
|
||||
|
||||
@@ -16,6 +16,11 @@ var (
|
||||
debugOption bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Set the default logger
|
||||
Logger, _ = NewLogger(false, false) // nolint: errcheck
|
||||
}
|
||||
|
||||
// InitLogger initialize the logger variable
|
||||
func InitLogger(debug, disable bool) (err error) {
|
||||
debugOption = debug
|
||||
|
||||
290
pkg/plugin/plugin.go
Normal file
290
pkg/plugin/plugin.go
Normal file
@@ -0,0 +1,290 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
getter "github.com/hashicorp/go-getter"
|
||||
"golang.org/x/xerrors"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
configFile = "plugin.yaml"
|
||||
xdgDataHome = "XDG_DATA_HOME"
|
||||
)
|
||||
|
||||
var (
|
||||
pluginsRelativeDir = filepath.Join(".trivy", "plugins")
|
||||
|
||||
officialPlugins = map[string]string{
|
||||
"kubectl": "github.com/aquasecurity/trivy-plugin-kubectl",
|
||||
}
|
||||
)
|
||||
|
||||
// Plugin represents a plugin.
|
||||
type Plugin struct {
|
||||
Name string `yaml:"name"`
|
||||
Repository string `yaml:"repository"`
|
||||
Version string `yaml:"version"`
|
||||
Usage string `yaml:"usage"`
|
||||
Description string `yaml:"description"`
|
||||
Platforms []Platform `yaml:"platforms"`
|
||||
|
||||
// runtime environment for testability
|
||||
GOOS string `yaml:"_goos"`
|
||||
GOARCH string `yaml:"_goarch"`
|
||||
}
|
||||
|
||||
// Platform represents where the execution file exists per platform.
|
||||
type Platform struct {
|
||||
Selector *Selector
|
||||
URI string
|
||||
Bin string
|
||||
}
|
||||
|
||||
// Selector represents the environment.
|
||||
type Selector struct {
|
||||
OS string
|
||||
Arch string
|
||||
}
|
||||
|
||||
// Run runs the plugin
|
||||
func (p Plugin) Run(ctx context.Context, args []string) error {
|
||||
platform, err := p.selectPlatform()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("platform selection error: %w", err)
|
||||
}
|
||||
|
||||
execFile := filepath.Join(dir(), p.Name, platform.Bin)
|
||||
|
||||
cmd := exec.CommandContext(ctx, execFile, args...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Env = os.Environ()
|
||||
|
||||
// If an error is found during the execution of the plugin, figure
|
||||
// out if the error was from not being able to execute the plugin or
|
||||
// an error set by the plugin itself.
|
||||
if err = cmd.Run(); err != nil {
|
||||
if _, ok := err.(*exec.ExitError); !ok {
|
||||
return xerrors.Errorf("exit: %w", err)
|
||||
}
|
||||
|
||||
return xerrors.Errorf("plugin exec: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Plugin) selectPlatform() (Platform, error) {
|
||||
// These values are only filled in during unit tests.
|
||||
if p.GOOS == "" {
|
||||
p.GOOS = runtime.GOOS
|
||||
}
|
||||
if p.GOARCH == "" {
|
||||
p.GOARCH = runtime.GOARCH
|
||||
}
|
||||
|
||||
for _, platform := range p.Platforms {
|
||||
if platform.Selector == nil {
|
||||
return platform, nil
|
||||
}
|
||||
|
||||
selector := platform.Selector
|
||||
if (selector.OS == "" || p.GOOS == selector.OS) &&
|
||||
(selector.Arch == "" || p.GOARCH == selector.Arch) {
|
||||
log.Logger.Debugf("Platform found, os: %s, arch: %s", selector.OS, selector.Arch)
|
||||
return platform, nil
|
||||
}
|
||||
}
|
||||
return Platform{}, xerrors.New("platform not found")
|
||||
}
|
||||
|
||||
func (p Plugin) install(ctx context.Context, dst, pwd string) error {
|
||||
log.Logger.Debugf("Installing the plugin to %s...", dst)
|
||||
platform, err := p.selectPlatform()
|
||||
if err != nil {
|
||||
return xerrors.Errorf("platform selection error: %w", err)
|
||||
}
|
||||
|
||||
log.Logger.Debugf("Downloading the execution file from %s...", platform.URI)
|
||||
if err = download(ctx, platform.URI, dst, pwd); err != nil {
|
||||
return xerrors.Errorf("unable to download the execution file (%s): %w", platform.URI, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Plugin) dir() (string, error) {
|
||||
if p.Name == "" {
|
||||
return "", xerrors.Errorf("'name' is empty")
|
||||
}
|
||||
|
||||
// e.g. ~/.trivy/plugins/kubectl
|
||||
return filepath.Join(dir(), p.Name), nil
|
||||
}
|
||||
|
||||
// Install installs a plugin
|
||||
func Install(ctx context.Context, url string, force bool) (Plugin, error) {
|
||||
// Replace short names with full qualified names
|
||||
// e.g. kubectl => github.com/aquasecurity/trivy-plugin-kubectl
|
||||
if v, ok := officialPlugins[url]; ok {
|
||||
url = v
|
||||
}
|
||||
|
||||
if !force {
|
||||
// If the plugin is already installed, it skips installing the plugin.
|
||||
if p, installed := isInstalled(url); installed {
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Logger.Infof("Installing the plugin from %s...", url)
|
||||
tempDir, err := downloadToTempDir(ctx, url)
|
||||
if err != nil {
|
||||
return Plugin{}, xerrors.Errorf("download failed: %w", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
log.Logger.Info("Loading the plugin metadata...")
|
||||
plugin, err := loadMetadata(tempDir)
|
||||
if err != nil {
|
||||
return Plugin{}, xerrors.Errorf("failed to load the plugin metadata: %w", err)
|
||||
}
|
||||
|
||||
pluginDir, err := plugin.dir()
|
||||
if err != nil {
|
||||
return Plugin{}, xerrors.Errorf("failed to determine the plugin dir: %w", err)
|
||||
}
|
||||
|
||||
if err = plugin.install(ctx, pluginDir, tempDir); err != nil {
|
||||
return Plugin{}, xerrors.Errorf("failed to install the plugin: %w", err)
|
||||
}
|
||||
|
||||
// Copy plugin.yaml into the plugin dir
|
||||
if _, err = utils.CopyFile(filepath.Join(tempDir, configFile), filepath.Join(pluginDir, configFile)); err != nil {
|
||||
return Plugin{}, xerrors.Errorf("failed to copy plugin.yaml: %w", err)
|
||||
}
|
||||
|
||||
return plugin, nil
|
||||
}
|
||||
|
||||
// Uninstall installs the plugin
|
||||
func Uninstall(name string) error {
|
||||
pluginDir := filepath.Join(dir(), name)
|
||||
return os.RemoveAll(pluginDir)
|
||||
}
|
||||
|
||||
func downloadToTempDir(ctx context.Context, url string) (string, error) {
|
||||
tempDir, err := os.MkdirTemp("", "trivy-plugin")
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("failed to create a temp dir: %w", err)
|
||||
}
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("unable to get the current dir: %w", err)
|
||||
}
|
||||
|
||||
if err = download(ctx, url, tempDir, pwd); err != nil {
|
||||
return "", xerrors.Errorf("download error: %w", err)
|
||||
}
|
||||
|
||||
return tempDir, nil
|
||||
}
|
||||
|
||||
func download(ctx context.Context, src, dst, pwd string) error {
|
||||
// go-getter doesn't allow the dst directory already exists if the src is directory.
|
||||
_ = os.RemoveAll(dst)
|
||||
|
||||
var opts []getter.ClientOption
|
||||
|
||||
// Overwrite the file getter so that a file will be copied
|
||||
getter.Getters["file"] = &getter.FileGetter{Copy: true}
|
||||
|
||||
// Build the client
|
||||
client := &getter.Client{
|
||||
Ctx: ctx,
|
||||
Src: src,
|
||||
Dst: dst,
|
||||
Pwd: pwd,
|
||||
Getters: getter.Getters,
|
||||
Mode: getter.ClientModeAny,
|
||||
Options: opts,
|
||||
}
|
||||
|
||||
if err := client.Get(); err != nil {
|
||||
return xerrors.Errorf("failed to download: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadAll loads all plugins
|
||||
func LoadAll() ([]Plugin, error) {
|
||||
pluginsDir := dir()
|
||||
dirs, err := os.ReadDir(pluginsDir)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to read %s: %w", pluginsDir, err)
|
||||
}
|
||||
|
||||
var plugins []Plugin
|
||||
for _, d := range dirs {
|
||||
if !d.IsDir() {
|
||||
continue
|
||||
}
|
||||
plugin, err := loadMetadata(filepath.Join(pluginsDir, d.Name()))
|
||||
if err != nil {
|
||||
log.Logger.Warnf("plugin load error: %s", err)
|
||||
continue
|
||||
}
|
||||
plugins = append(plugins, plugin)
|
||||
}
|
||||
return plugins, nil
|
||||
}
|
||||
|
||||
func loadMetadata(dir string) (Plugin, error) {
|
||||
filePath := filepath.Join(dir, configFile)
|
||||
f, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return Plugin{}, xerrors.Errorf("file open error: %w", err)
|
||||
}
|
||||
|
||||
var plugin Plugin
|
||||
if err = yaml.NewDecoder(f).Decode(&plugin); err != nil {
|
||||
return Plugin{}, xerrors.Errorf("yaml decode error: %w", err)
|
||||
}
|
||||
|
||||
return plugin, nil
|
||||
}
|
||||
|
||||
func dir() string {
|
||||
dataHome := os.Getenv(xdgDataHome)
|
||||
if dataHome != "" {
|
||||
return filepath.Join(dataHome, pluginsRelativeDir)
|
||||
}
|
||||
|
||||
homeDir, _ := os.UserHomeDir()
|
||||
return filepath.Join(homeDir, pluginsRelativeDir)
|
||||
}
|
||||
|
||||
func isInstalled(url string) (Plugin, bool) {
|
||||
installedPlugins, err := LoadAll()
|
||||
if err != nil {
|
||||
return Plugin{}, false
|
||||
}
|
||||
|
||||
for _, plugin := range installedPlugins {
|
||||
if plugin.Repository == url {
|
||||
return plugin, true
|
||||
}
|
||||
}
|
||||
return Plugin{}, false
|
||||
}
|
||||
347
pkg/plugin/plugin_test.go
Normal file
347
pkg/plugin/plugin_test.go
Normal file
@@ -0,0 +1,347 @@
|
||||
package plugin_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/plugin"
|
||||
)
|
||||
|
||||
func TestPlugin_Run(t *testing.T) {
|
||||
type fields struct {
|
||||
Name string
|
||||
Repository string
|
||||
Version string
|
||||
Usage string
|
||||
Description string
|
||||
Platforms []plugin.Platform
|
||||
GOOS string
|
||||
GOARCH string
|
||||
}
|
||||
type args struct {
|
||||
args []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
fields: fields{
|
||||
Name: "test_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Bin: "test.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no selector",
|
||||
fields: fields{
|
||||
Name: "test_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
URI: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Bin: "test.sh",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no matched platform",
|
||||
fields: fields{
|
||||
Name: "test_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "darwin",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Bin: "test.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
wantErr: "platform not found",
|
||||
},
|
||||
{
|
||||
name: "no execution file",
|
||||
fields: fields{
|
||||
Name: "test_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Bin: "nonexistence.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
wantErr: "no such file or directory",
|
||||
},
|
||||
{
|
||||
name: "plugin exec error",
|
||||
fields: fields{
|
||||
Name: "error_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-error",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Bin: "test.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
wantErr: "plugin exec: exit status 1",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
os.Setenv("XDG_DATA_HOME", "testdata")
|
||||
defer os.Unsetenv("XDG_DATA_HOME")
|
||||
|
||||
p := plugin.Plugin{
|
||||
Name: tt.fields.Name,
|
||||
Repository: tt.fields.Repository,
|
||||
Version: tt.fields.Version,
|
||||
Usage: tt.fields.Usage,
|
||||
Description: tt.fields.Description,
|
||||
Platforms: tt.fields.Platforms,
|
||||
GOOS: tt.fields.GOOS,
|
||||
GOARCH: tt.fields.GOARCH,
|
||||
}
|
||||
|
||||
err := p.Run(context.Background(), tt.args.args)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstall(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
want plugin.Plugin
|
||||
wantFile string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
url: "testdata/test_plugin",
|
||||
want: plugin.Plugin{
|
||||
Name: "test_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "./test.sh",
|
||||
Bin: "./test.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
wantFile: ".trivy/plugins/test_plugin/test.sh",
|
||||
},
|
||||
{
|
||||
name: "plugin not found",
|
||||
url: "testdata/not_found",
|
||||
want: plugin.Plugin{
|
||||
Name: "test_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "./test.sh",
|
||||
Bin: "./test.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
wantErr: "no such file or directory",
|
||||
},
|
||||
{
|
||||
name: "no plugin.yaml",
|
||||
url: "testdata/no_yaml",
|
||||
want: plugin.Plugin{
|
||||
Name: "no_yaml",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "./test.sh",
|
||||
Bin: "./test.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
wantErr: "file open error",
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// The test plugin will be installed here
|
||||
dst := t.TempDir()
|
||||
os.Setenv("XDG_DATA_HOME", dst)
|
||||
|
||||
got, err := plugin.Install(context.Background(), tt.url, false)
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
assert.FileExists(t, filepath.Join(dst, tt.wantFile))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUninstall(t *testing.T) {
|
||||
pluginName := "test_plugin"
|
||||
|
||||
tempDir := t.TempDir()
|
||||
pluginDir := filepath.Join(tempDir, ".trivy", "plugins", pluginName)
|
||||
|
||||
// Create the test plugin directory
|
||||
err := os.MkdirAll(pluginDir, os.ModePerm)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create the test file
|
||||
err = os.WriteFile(filepath.Join(pluginDir, "test.sh"), []byte(`foo`), os.ModePerm)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Uninstall the plugin
|
||||
err = plugin.Uninstall(pluginName)
|
||||
assert.NoError(t, err)
|
||||
assert.NoFileExists(t, pluginDir)
|
||||
}
|
||||
|
||||
func TestLoadAll1(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
dir string
|
||||
want []plugin.Plugin
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
dir: "testdata",
|
||||
want: []plugin.Plugin{
|
||||
{
|
||||
Name: "test_plugin",
|
||||
Repository: "github.com/aquasecurity/trivy-plugin-test",
|
||||
Version: "0.1.0",
|
||||
Usage: "test",
|
||||
Description: "test",
|
||||
Platforms: []plugin.Platform{
|
||||
{
|
||||
Selector: &plugin.Selector{
|
||||
OS: "linux",
|
||||
Arch: "amd64",
|
||||
},
|
||||
URI: "./test.sh",
|
||||
Bin: "./test.sh",
|
||||
},
|
||||
},
|
||||
GOOS: "linux",
|
||||
GOARCH: "amd64",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path",
|
||||
dir: "sad",
|
||||
wantErr: "no such file or directory",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
os.Setenv("XDG_DATA_HOME", tt.dir)
|
||||
defer os.Unsetenv("XDG_DATA_HOME")
|
||||
|
||||
got, err := plugin.LoadAll()
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
0
pkg/plugin/testdata/.trivy/plugins/dummy.txt
vendored
Normal file
0
pkg/plugin/testdata/.trivy/plugins/dummy.txt
vendored
Normal file
3
pkg/plugin/testdata/.trivy/plugins/error_plugin/test.sh
vendored
Executable file
3
pkg/plugin/testdata/.trivy/plugins/error_plugin/test.sh
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
exit 1
|
||||
14
pkg/plugin/testdata/.trivy/plugins/test_plugin/plugin.yaml
vendored
Normal file
14
pkg/plugin/testdata/.trivy/plugins/test_plugin/plugin.yaml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: "test_plugin"
|
||||
repository: github.com/aquasecurity/trivy-plugin-test
|
||||
version: "0.1.0"
|
||||
usage: test
|
||||
description: test
|
||||
platforms:
|
||||
- selector:
|
||||
os: linux
|
||||
arch: amd64
|
||||
uri: ./test.sh
|
||||
bin: ./test.sh
|
||||
# for testing
|
||||
_goos: linux
|
||||
_goarch: amd64
|
||||
3
pkg/plugin/testdata/.trivy/plugins/test_plugin/test.sh
vendored
Executable file
3
pkg/plugin/testdata/.trivy/plugins/test_plugin/test.sh
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "foo"
|
||||
0
pkg/plugin/testdata/no_yaml/.keep
vendored
Normal file
0
pkg/plugin/testdata/no_yaml/.keep
vendored
Normal file
14
pkg/plugin/testdata/test_plugin/plugin.yaml
vendored
Normal file
14
pkg/plugin/testdata/test_plugin/plugin.yaml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: "test_plugin"
|
||||
repository: github.com/aquasecurity/trivy-plugin-test
|
||||
version: "0.1.0"
|
||||
usage: test
|
||||
description: test
|
||||
platforms:
|
||||
- selector:
|
||||
os: linux
|
||||
arch: amd64
|
||||
uri: ./test.sh
|
||||
bin: ./test.sh
|
||||
# for testing
|
||||
_goos: linux
|
||||
_goarch: amd64
|
||||
3
pkg/plugin/testdata/test_plugin/test.sh
vendored
Executable file
3
pkg/plugin/testdata/test_plugin/test.sh
vendored
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "foo"
|
||||
@@ -3,21 +3,13 @@ package client
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
_ = log.InitLogger(false, true)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestWithCustomHeaders(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,19 +11,12 @@ import (
|
||||
ptypes "github.com/aquasecurity/go-dep-parser/pkg/types"
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
"github.com/aquasecurity/trivy/rpc/common"
|
||||
"github.com/aquasecurity/trivy/rpc/scanner"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
code := m.Run()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func TestConvertToRpcPkgs(t *testing.T) {
|
||||
type args struct {
|
||||
pkgs []ftypes.Package
|
||||
|
||||
@@ -20,15 +20,9 @@ import (
|
||||
"github.com/aquasecurity/fanal/cache"
|
||||
"github.com/aquasecurity/trivy-db/pkg/db"
|
||||
dbFile "github.com/aquasecurity/trivy/pkg/db"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
rpcCache "github.com/aquasecurity/trivy/rpc/cache"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
_ = log.InitLogger(false, false)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func Test_dbWorker_update(t *testing.T) {
|
||||
timeNextUpdate := time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
timeUpdateAt := time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
dtypes "github.com/aquasecurity/go-dep-parser/pkg/types"
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
|
||||
ospkgDetector "github.com/aquasecurity/trivy/pkg/detector/ospkg"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
@@ -797,7 +796,6 @@ func TestScanner_Scan(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
log.InitLogger(false, true)
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_ = dbtest.InitDB(t, tt.fixtures)
|
||||
|
||||
@@ -3,7 +3,6 @@ package scanner
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -11,17 +10,10 @@ import (
|
||||
|
||||
"github.com/aquasecurity/fanal/artifact"
|
||||
ftypes "github.com/aquasecurity/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/report"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
log.InitLogger(false, false)
|
||||
code := m.Run()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func TestScanner_ScanArtifact(t *testing.T) {
|
||||
type args struct {
|
||||
options types.ScanOptions
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -33,9 +32,6 @@ func write(t *testing.T, name string, content string) {
|
||||
}
|
||||
|
||||
func TestFileWalk(t *testing.T) {
|
||||
if err := log.InitLogger(false, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
td, err := ioutil.TempDir("", "walktest")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -2,7 +2,6 @@ package vulnerability
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -13,19 +12,9 @@ import (
|
||||
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||
"github.com/aquasecurity/trivy-db/pkg/utils"
|
||||
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if err := log.InitLogger(false, true); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
code := m.Run()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func TestClient_FillInfo(t *testing.T) {
|
||||
type args struct {
|
||||
vulns []types.DetectedVulnerability
|
||||
|
||||
Reference in New Issue
Block a user