feat(scan): support --offline-scan option (#1511)

This commit is contained in:
Teppei Fukuda
2021-12-24 12:20:21 +02:00
committed by GitHub
parent da8b72d2e7
commit 59957d4c6b
13 changed files with 53 additions and 16 deletions

View File

@@ -50,11 +50,12 @@ $ rm trivy-offline.db.tgz
In an air-gapped environment it is your responsibility to update the Trivy database on a regular basis, so that the scanner can detect recently-identified vulnerabilities. In an air-gapped environment it is your responsibility to update the Trivy database on a regular basis, so that the scanner can detect recently-identified vulnerabilities.
### Run Trivy with --skip-update option ### Run Trivy with --skip-update and --offline-scan option
In an air-gapped environment, specify `--skip-update` so that Trivy doesn't attempt to download the latest database file. In an air-gapped environment, specify `--skip-update` so that Trivy doesn't attempt to download the latest database file.
In addition, if you want to scan Java dependencies such as JAR and pom.xml, you need to specify `--offline-scan` since Trivy tries to issue API requests for scanning Java applications by default.
``` ```
$ trivy image --skip-update alpine:3.12 $ trivy image --skip-update --offline-scan alpine:3.12
``` ```
## Air-Gapped Environment for misconfigurations ## Air-Gapped Environment for misconfigurations

View File

@@ -22,6 +22,7 @@ OPTIONS:
--timeout value timeout (default: 5m0s) [$TRIVY_TIMEOUT] --timeout value timeout (default: 5m0s) [$TRIVY_TIMEOUT]
--ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY] --ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY]
--list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS] --list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS]
--offline-scan do not issue API requests to identify dependencies (default: false) [$TRIVY_OFFLINE_SCAN]
--token value for authentication [$TRIVY_TOKEN] --token value for authentication [$TRIVY_TOKEN]
--token-header value specify a header name for token (default: "Trivy-Token") [$TRIVY_TOKEN_HEADER] --token-header value specify a header name for token (default: "Trivy-Token") [$TRIVY_TOKEN_HEADER]
--remote value server address (default: "http://localhost:4954") [$TRIVY_REMOTE] --remote value server address (default: "http://localhost:4954") [$TRIVY_REMOTE]

View File

@@ -25,6 +25,7 @@ OPTIONS:
--no-progress suppress progress bar (default: false) [$TRIVY_NO_PROGRESS] --no-progress suppress progress bar (default: false) [$TRIVY_NO_PROGRESS]
--ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY] --ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY]
--list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS] --list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS]
--offline-scan do not issue API requests to identify dependencies (default: false) [$TRIVY_OFFLINE_SCAN]
--skip-files value specify the file paths to skip traversal [$TRIVY_SKIP_FILES] --skip-files value specify the file paths to skip traversal [$TRIVY_SKIP_FILES]
--skip-dirs value specify the directories where the traversal is skipped [$TRIVY_SKIP_DIRS] --skip-dirs value specify the directories where the traversal is skipped [$TRIVY_SKIP_DIRS]
--config-policy value specify paths to the Rego policy files directory, applying config files [$TRIVY_CONFIG_POLICY] --config-policy value specify paths to the Rego policy files directory, applying config files [$TRIVY_CONFIG_POLICY]

View File

@@ -27,6 +27,7 @@ OPTIONS:
--light light mode: it's faster, but vulnerability descriptions and references are not displayed (default: false) [$TRIVY_LIGHT] --light light mode: it's faster, but vulnerability descriptions and references are not displayed (default: false) [$TRIVY_LIGHT]
--ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY] --ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY]
--list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS] --list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS]
--offline-scan do not issue API requests to identify dependencies (default: false) [$TRIVY_OFFLINE_SCAN]
--skip-files value specify the file path to skip traversal [$TRIVY_SKIP_FILES] --skip-files value specify the file path to skip traversal [$TRIVY_SKIP_FILES]
--skip-dirs value specify the directory where the traversal is skipped [$TRIVY_SKIP_DIRS] --skip-dirs value specify the directory where the traversal is skipped [$TRIVY_SKIP_DIRS]
--cache-backend value cache backend (e.g. redis://localhost:6379) (default: "fs") [$TRIVY_CACHE_BACKEND] --cache-backend value cache backend (e.g. redis://localhost:6379) (default: "fs") [$TRIVY_CACHE_BACKEND]

View File

@@ -25,6 +25,7 @@ OPTIONS:
--no-progress suppress progress bar (default: false) [$TRIVY_NO_PROGRESS] --no-progress suppress progress bar (default: false) [$TRIVY_NO_PROGRESS]
--ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY] --ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY]
--list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS] --list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS]
--offline-scan do not issue API requests to identify dependencies (default: false) [$TRIVY_OFFLINE_SCAN]
--skip-files value specify the file path to skip traversal [$TRIVY_SKIP_FILES] --skip-files value specify the file path to skip traversal [$TRIVY_SKIP_FILES]
--skip-dirs value specify the directory where the traversal is skipped [$TRIVY_SKIP_DIRS] --skip-dirs value specify the directory where the traversal is skipped [$TRIVY_SKIP_DIRS]
--help, -h show help (default: false) --help, -h show help (default: false)

View File

@@ -25,6 +25,7 @@ OPTIONS:
--no-progress suppress progress bar (default: false) [$TRIVY_NO_PROGRESS] --no-progress suppress progress bar (default: false) [$TRIVY_NO_PROGRESS]
--ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY] --ignore-policy value specify the Rego file to evaluate each vulnerability [$TRIVY_IGNORE_POLICY]
--list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS] --list-all-pkgs enabling the option will output all packages regardless of vulnerability (default: false) [$TRIVY_LIST_ALL_PKGS]
--offline-scan do not issue API requests to identify dependencies (default: false) [$TRIVY_OFFLINE_SCAN]
--skip-files value specify the file paths to skip traversal [$TRIVY_SKIP_FILES] --skip-files value specify the file paths to skip traversal [$TRIVY_SKIP_FILES]
--skip-dirs value specify the directories where the traversal is skipped [$TRIVY_SKIP_DIRS] --skip-dirs value specify the directories where the traversal is skipped [$TRIVY_SKIP_DIRS]
--config-policy value specify paths to the Rego policy files directory, applying config files [$TRIVY_CONFIG_POLICY] --config-policy value specify paths to the Rego policy files directory, applying config files [$TRIVY_CONFIG_POLICY]

View File

@@ -39,6 +39,22 @@ https://developer.github.com/v3/#rate-limiting
$ GITHUB_TOKEN=XXXXXXXXXX trivy alpine:3.10 $ GITHUB_TOKEN=XXXXXXXXXX trivy alpine:3.10
``` ```
### Maven rate limiting
!!! error
``` bash
$ trivy image ...
...
status 403 Forbidden from http://search.maven.org/solrsearch/select
```
Trivy calls Maven API for better detection of JAR files, but many requests may exceed rate limiting.
If it happens frequently, try the `--offline-scan` option to stop Trivy from making API requests.
This option affects only vulnerability scanning. The vulnerability database and builtin policies are downloaded as usual.
If you want to skip them as well, you can try `--skip-update` and `--skip-policy-update`.
Note that a number of vulnerabilities might be fewer than without the `--offline-scan` option.
### Running in parallel takes same time as series run ### Running in parallel takes same time as series run
When running trivy on multiple images simultaneously, it will take same time as running trivy in series. When running trivy on multiple images simultaneously, it will take same time as running trivy in series.
This is because of a limitation of boltdb. This is because of a limitation of boltdb.

4
go.mod
View File

@@ -7,8 +7,8 @@ require (
github.com/Masterminds/sprig v2.22.0+incompatible github.com/Masterminds/sprig v2.22.0+incompatible
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
github.com/aquasecurity/fanal v0.0.0-20211223181536-672696605858 github.com/aquasecurity/fanal v0.0.0-20211224062610-102e2bce2240
github.com/aquasecurity/go-dep-parser v0.0.0-20211223152202-b497b40cd9d2 github.com/aquasecurity/go-dep-parser v0.0.0-20211224061556-d0e33761a8ab
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46

8
go.sum
View File

@@ -207,10 +207,10 @@ github.com/aquasecurity/cfsec v0.2.2 h1:hq6MZlg7XFZsrerCv297N4HRlnJM7K6LLd/l/xCz
github.com/aquasecurity/cfsec v0.2.2/go.mod h1:sUELRJqIPXTOZiHUx7TzyyFFzuk0W22IG6IWAoV8T6U= github.com/aquasecurity/cfsec v0.2.2/go.mod h1:sUELRJqIPXTOZiHUx7TzyyFFzuk0W22IG6IWAoV8T6U=
github.com/aquasecurity/defsec v0.0.37 h1:zdZndlKrW257b8VLK1UwfmXiyPuDrNA+wzBilHRk1LA= github.com/aquasecurity/defsec v0.0.37 h1:zdZndlKrW257b8VLK1UwfmXiyPuDrNA+wzBilHRk1LA=
github.com/aquasecurity/defsec v0.0.37/go.mod h1:csaBEcJ3AKy44expnW0dCANEZcS/c1vcJjwBCbnKWBM= github.com/aquasecurity/defsec v0.0.37/go.mod h1:csaBEcJ3AKy44expnW0dCANEZcS/c1vcJjwBCbnKWBM=
github.com/aquasecurity/fanal v0.0.0-20211223181536-672696605858 h1:K+OhavtHOe6weJpCvSDDiObrJDBk4hXtcqBBJ0mTzjE= github.com/aquasecurity/fanal v0.0.0-20211224062610-102e2bce2240 h1:wxeId0nDv3i3Ih98oFZE7Q6OeNY1R+itxOpkmpbaiek=
github.com/aquasecurity/fanal v0.0.0-20211223181536-672696605858/go.mod h1:cLmcWHV2gIXcwNEOVVVoas/5wSyhIvMHJACbenvGUCg= github.com/aquasecurity/fanal v0.0.0-20211224062610-102e2bce2240/go.mod h1:Uj+SCSOPxrU4xrxu9fFVvRWimkktPXv/VWzSfMx/dog=
github.com/aquasecurity/go-dep-parser v0.0.0-20211223152202-b497b40cd9d2 h1:B+lL7tKxen+aWygRCv5YRjwq08YokAEHMrTsrujURrc= github.com/aquasecurity/go-dep-parser v0.0.0-20211224061556-d0e33761a8ab h1:/i0NsV3rYRcW0hkcCCrHmppX5rAr3rlWVIGKdeKBThU=
github.com/aquasecurity/go-dep-parser v0.0.0-20211223152202-b497b40cd9d2/go.mod h1:mYbm6nW+oy1o7gGYngbki6y2VPUf6BPt5U7+O9C78sI= github.com/aquasecurity/go-dep-parser v0.0.0-20211224061556-d0e33761a8ab/go.mod h1:mYbm6nW+oy1o7gGYngbki6y2VPUf6BPt5U7+O9C78sI=
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s= github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s=
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 h1:eveqE9ivrt30CJ7dOajOfBavhZ4zPqHcZe/4tKp0alc= github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798 h1:eveqE9ivrt30CJ7dOajOfBavhZ4zPqHcZe/4tKp0alc=

View File

@@ -225,6 +225,12 @@ var (
EnvVars: []string{"TRIVY_SKIP_DIRS"}, EnvVars: []string{"TRIVY_SKIP_DIRS"},
} }
offlineScan = cli.BoolFlag{
Name: "offline-scan",
Usage: "do not issue API requests to identify dependencies",
EnvVars: []string{"TRIVY_OFFLINE_SCAN"},
}
// For misconfigurations // For misconfigurations
configPolicy = cli.StringSliceFlag{ configPolicy = cli.StringSliceFlag{
Name: "config-policy", Name: "config-policy",
@@ -309,6 +315,7 @@ var (
&ignorePolicy, &ignorePolicy,
&listAllPackages, &listAllPackages,
&cacheBackendFlag, &cacheBackendFlag,
&offlineScan,
stringSliceFlag(skipFiles), stringSliceFlag(skipFiles),
stringSliceFlag(skipDirs), stringSliceFlag(skipDirs),
} }
@@ -465,6 +472,7 @@ func NewFilesystemCommand() *cli.Command {
&noProgressFlag, &noProgressFlag,
&ignorePolicy, &ignorePolicy,
&listAllPackages, &listAllPackages,
&offlineScan,
stringSliceFlag(skipFiles), stringSliceFlag(skipFiles),
stringSliceFlag(skipDirs), stringSliceFlag(skipDirs),
stringSliceFlag(configPolicy), stringSliceFlag(configPolicy),
@@ -499,6 +507,7 @@ func NewRootfsCommand() *cli.Command {
&noProgressFlag, &noProgressFlag,
&ignorePolicy, &ignorePolicy,
&listAllPackages, &listAllPackages,
&offlineScan,
stringSliceFlag(skipFiles), stringSliceFlag(skipFiles),
stringSliceFlag(skipDirs), stringSliceFlag(skipDirs),
stringSliceFlag(configPolicy), stringSliceFlag(configPolicy),
@@ -536,6 +545,7 @@ func NewRepositoryCommand() *cli.Command {
&noProgressFlag, &noProgressFlag,
&ignorePolicy, &ignorePolicy,
&listAllPackages, &listAllPackages,
&offlineScan,
stringSliceFlag(skipFiles), stringSliceFlag(skipFiles),
stringSliceFlag(skipDirs), stringSliceFlag(skipDirs),
}, },
@@ -569,6 +579,7 @@ func NewClientCommand() *cli.Command {
stringSliceFlag(skipDirs), stringSliceFlag(skipDirs),
stringSliceFlag(configPolicy), stringSliceFlag(configPolicy),
&listAllPackages, &listAllPackages,
&offlineScan,
// original flags // original flags
&token, &token,

View File

@@ -203,6 +203,7 @@ func scan(ctx context.Context, opt Option, initializeScanner InitializeScanner,
DisabledAnalyzers: disabledAnalyzers(opt), DisabledAnalyzers: disabledAnalyzers(opt),
SkipFiles: opt.SkipFiles, SkipFiles: opt.SkipFiles,
SkipDirs: opt.SkipDirs, SkipDirs: opt.SkipDirs,
Offline: opt.OfflineScan,
} }
s, cleanup, err := initializeScanner(ctx, target, cacheClient, cacheClient, opt.Timeout, artifactOpt, configScannerOptions) s, cleanup, err := initializeScanner(ctx, target, cacheClient, cacheClient, opt.Timeout, artifactOpt, configScannerOptions)

View File

@@ -143,7 +143,7 @@ func initializeScanner(ctx context.Context, opt Option) (scanner.Scanner, func()
// ScannerOptions is filled only when config scanning is enabled. // ScannerOptions is filled only when config scanning is enabled.
var configScannerOptions config.ScannerOption var configScannerOptions config.ScannerOption
if utils.StringInSlice(types.SecurityCheckConfig, opt.SecurityChecks) { if utils.StringInSlice(types.SecurityCheckConfig, opt.SecurityChecks) {
builtinPolicyPaths, err := operation.InitBuiltinPolicies(ctx, false) builtinPolicyPaths, err := operation.InitBuiltinPolicies(ctx, opt.SkipPolicyUpdate)
if err != nil { if err != nil {
return scanner.Scanner{}, nil, xerrors.Errorf("failed to initialize default policies: %w", err) return scanner.Scanner{}, nil, xerrors.Errorf("failed to initialize default policies: %w", err)
} }
@@ -161,6 +161,7 @@ func initializeScanner(ctx context.Context, opt Option) (scanner.Scanner, func()
DisabledAnalyzers: disabledAnalyzers(opt), DisabledAnalyzers: disabledAnalyzers(opt),
SkipFiles: opt.SkipFiles, SkipFiles: opt.SkipFiles,
SkipDirs: opt.SkipDirs, SkipDirs: opt.SkipDirs,
Offline: opt.OfflineScan,
} }
if opt.Input != "" { if opt.Input != "" {

View File

@@ -15,8 +15,9 @@ type ArtifactOption struct {
Timeout time.Duration Timeout time.Duration
ClearCache bool ClearCache bool
SkipDirs []string SkipDirs []string
SkipFiles []string SkipFiles []string
OfflineScan bool
// this field is populated in Init() // this field is populated in Init()
Target string Target string
@@ -25,11 +26,12 @@ type ArtifactOption struct {
// NewArtifactOption is the factory method to return artifact option // NewArtifactOption is the factory method to return artifact option
func NewArtifactOption(c *cli.Context) ArtifactOption { func NewArtifactOption(c *cli.Context) ArtifactOption {
return ArtifactOption{ return ArtifactOption{
Input: c.String("input"), Input: c.String("input"),
Timeout: c.Duration("timeout"), Timeout: c.Duration("timeout"),
ClearCache: c.Bool("clear-cache"), ClearCache: c.Bool("clear-cache"),
SkipFiles: c.StringSlice("skip-files"), SkipFiles: c.StringSlice("skip-files"),
SkipDirs: c.StringSlice("skip-dirs"), SkipDirs: c.StringSlice("skip-dirs"),
OfflineScan: c.Bool("offline-scan"),
} }
} }