feat(filesystem): scan in client/server mode (#1829)

Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
afdesk
2022-03-21 19:51:18 +06:00
committed by GitHub
parent 12d0317a67
commit d6418cf0de
49 changed files with 763 additions and 1014 deletions

View File

@@ -13,9 +13,11 @@ import (
"github.com/aquasecurity/fanal/artifact"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy-db/pkg/db"
tcache "github.com/aquasecurity/trivy/pkg/cache"
"github.com/aquasecurity/trivy/pkg/commands/operation"
"github.com/aquasecurity/trivy/pkg/log"
pkgReport "github.com/aquasecurity/trivy/pkg/report"
"github.com/aquasecurity/trivy/pkg/rpc/client"
"github.com/aquasecurity/trivy/pkg/scanner"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/utils"
@@ -25,9 +27,26 @@ const defaultPolicyNamespace = "appshield"
var errSkipScan = errors.New("skip subsequent processes")
type scannerConfig struct {
// e.g. image name and file path
Target string
// Cache
ArtifactCache cache.ArtifactCache
LocalArtifactCache cache.LocalArtifactCache
// Client/Server options
RemoteOption client.ScannerOption
// Artifact options
ArtifactOption artifact.Option
// Misconfiguration scanning options
MisconfOption config.ScannerOption
}
// InitializeScanner defines the initialize function signature of scanner
type InitializeScanner func(context.Context, string, cache.ArtifactCache, cache.LocalArtifactCache, bool,
artifact.Option, config.ScannerOption) (scanner.Scanner, func(), error)
type InitializeScanner func(context.Context, scannerConfig) (scanner.Scanner, func(), error)
// InitCache defines cache initializer
type InitCache func(c Option) (cache.Cache, error)
@@ -37,7 +56,11 @@ func Run(ctx context.Context, opt Option, initializeScanner InitializeScanner, i
ctx, cancel := context.WithTimeout(ctx, opt.Timeout)
defer cancel()
return runWithTimeout(ctx, opt, initializeScanner, initCache)
err := runWithTimeout(ctx, opt, initializeScanner, initCache)
if xerrors.Is(err, context.DeadlineExceeded) {
log.Logger.Warn("Increase --timeout value")
}
return err
}
func runWithTimeout(ctx context.Context, opt Option, initializeScanner InitializeScanner, initCache InitCache) error {
@@ -54,8 +77,8 @@ func runWithTimeout(ctx context.Context, opt Option, initializeScanner Initializ
}
defer cacheClient.Close()
// When scanning config files, it doesn't need to download the vulnerability database.
if utils.StringInSlice(types.SecurityCheckVulnerability, opt.SecurityChecks) {
// When scanning config files or running as client mode, it doesn't need to download the vulnerability database.
if opt.RemoteAddr == "" && utils.StringInSlice(types.SecurityCheckVulnerability, opt.SecurityChecks) {
if err = initDB(opt); err != nil {
if errors.Is(err, errSkipScan) {
return nil
@@ -92,7 +115,14 @@ func runWithTimeout(ctx context.Context, opt Option, initializeScanner Initializ
return nil
}
func initFSCache(c Option) (cache.Cache, error) {
func initCache(c Option) (cache.Cache, error) {
// client/server mode
if c.RemoteAddr != "" {
remoteCache := tcache.NewRemoteCache(c.RemoteAddr, c.CustomHeaders, c.Insecure)
return tcache.NopCache(remoteCache), nil
}
// standalone mode
utils.SetCacheDir(c.CacheDir)
cache, err := operation.NewCache(c.CacheOption)
if err != nil {
@@ -181,7 +211,7 @@ func scan(ctx context.Context, opt Option, initializeScanner InitializeScanner,
}
log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType)
// ScannerOptions is filled only when config scanning is enabled.
// ScannerOption is filled only when config scanning is enabled.
var configScannerOptions config.ScannerOption
if utils.StringInSlice(types.SecurityCheckConfig, opt.SecurityChecks) {
noProgress := opt.Quiet || opt.NoProgress
@@ -199,16 +229,25 @@ func scan(ctx context.Context, opt Option, initializeScanner InitializeScanner,
}
}
artifactOpt := artifact.Option{
DisabledAnalyzers: disabledAnalyzers(opt),
SkipFiles: opt.SkipFiles,
SkipDirs: opt.SkipDirs,
InsecureSkipTLS: opt.Insecure,
Offline: opt.OfflineScan,
NoProgress: opt.NoProgress || opt.Quiet,
}
s, cleanup, err := initializeScanner(ctx, target, cacheClient, cacheClient, opt.Insecure, artifactOpt, configScannerOptions)
s, cleanup, err := initializeScanner(ctx, scannerConfig{
Target: target,
ArtifactCache: cacheClient,
LocalArtifactCache: cacheClient,
RemoteOption: client.ScannerOption{
RemoteURL: opt.RemoteAddr,
CustomHeaders: opt.CustomHeaders,
Insecure: opt.Insecure,
},
ArtifactOption: artifact.Option{
DisabledAnalyzers: disabledAnalyzers(opt),
SkipFiles: opt.SkipFiles,
SkipDirs: opt.SkipDirs,
InsecureSkipTLS: opt.Insecure,
Offline: opt.OfflineScan,
NoProgress: opt.NoProgress || opt.Quiet,
},
MisconfOption: configScannerOptions,
})
if err != nil {
return types.Report{}, xerrors.Errorf("unable to initialize a scanner: %w", err)
}
@@ -225,7 +264,10 @@ func filter(ctx context.Context, opt Option, report types.Report) (types.Report,
resultClient := initializeResultClient()
results := report.Results
for i := range results {
resultClient.FillVulnerabilityInfo(results[i].Vulnerabilities, results[i].Type)
// Fill vulnerability info only in standalone mode
if opt.RemoteAddr == "" {
resultClient.FillVulnerabilityInfo(results[i].Vulnerabilities, results[i].Type)
}
vulns, misconfSummary, misconfs, err := resultClient.Filter(ctx, results[i].Vulnerabilities, results[i].Misconfigurations,
opt.Severities, opt.IgnoreUnfixed, opt.IncludeNonFailures, opt.IgnoreFile, opt.IgnorePolicy)
if err != nil {