Skip to content

Commit

Permalink
feat: disable analyzers (#846)
Browse files Browse the repository at this point in the history
* feat: pass disabled analyzers

* refactor(run): split into functions

* feat(run): pass disabled analyzers

* chore(mod): update fanal

* chore(mod): update fanal

* refactor
  • Loading branch information
knqyf263 committed Feb 24, 2021
1 parent 47ce996 commit 425eaf8
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 115 deletions.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -7,7 +7,7 @@ require (
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
github.com/aquasecurity/fanal v0.0.0-20210214122859-98d76e2b3b96
github.com/aquasecurity/fanal v0.0.0-20210222115600-a1f6695cb01b
github.com/aquasecurity/go-dep-parser v0.0.0-20210214113128-b97635cfd627
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -97,8 +97,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM=
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
github.com/aquasecurity/fanal v0.0.0-20210214122859-98d76e2b3b96 h1:5Uk/RmXp+Itbm3fLa0vg1OKBl6Z6BfxDVrJpwETYqWk=
github.com/aquasecurity/fanal v0.0.0-20210214122859-98d76e2b3b96/go.mod h1:8HoL/kipOrDodHh+jzGgO2/iXJoRf6roLP5qPv8Mi90=
github.com/aquasecurity/fanal v0.0.0-20210222115600-a1f6695cb01b h1:RB7ng/h09gnW89psnw0pgJaGffMtrxrxeAL4uyOk33c=
github.com/aquasecurity/fanal v0.0.0-20210222115600-a1f6695cb01b/go.mod h1:8HoL/kipOrDodHh+jzGgO2/iXJoRf6roLP5qPv8Mi90=
github.com/aquasecurity/go-dep-parser v0.0.0-20210214113128-b97635cfd627 h1:ccLbhkZ54xTmI6Q+CyBL8sll+OXIEzX0aDDjmy8pVWQ=
github.com/aquasecurity/go-dep-parser v0.0.0-20210214113128-b97635cfd627/go.mod h1:KHiF3uK6FOE1v27YK+5CWEJ1jd0OvA2Gmk8VFjT3utk=
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
Expand Down
7 changes: 4 additions & 3 deletions internal/artifact/fs.go
Expand Up @@ -7,14 +7,15 @@ import (
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy/internal/artifact/config"
"github.com/aquasecurity/trivy/pkg/scanner"
)

func filesystemScanner(ctx context.Context, dir string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) (
scanner.Scanner, func(), error) {
s, cleanup, err := initializeFilesystemScanner(ctx, dir, ac, lac)
func filesystemScanner(ctx context.Context, dir string, ac cache.ArtifactCache, lac cache.LocalArtifactCache,
_ time.Duration, disabled []analyzer.Type) (scanner.Scanner, func(), error) {
s, cleanup, err := initializeFilesystemScanner(ctx, dir, ac, lac, disabled)
if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err)
}
Expand Down
12 changes: 7 additions & 5 deletions internal/artifact/image.go
Expand Up @@ -7,23 +7,25 @@ import (
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy/internal/artifact/config"
"github.com/aquasecurity/trivy/pkg/scanner"
)

func archiveScanner(ctx context.Context, input string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) (
scanner.Scanner, func(), error) {
s, err := initializeArchiveScanner(ctx, input, ac, lac, timeout)
func archiveScanner(ctx context.Context, input string, ac cache.ArtifactCache, lac cache.LocalArtifactCache,
timeout time.Duration, disabled []analyzer.Type) (scanner.Scanner, func(), error) {
s, err := initializeArchiveScanner(ctx, input, ac, lac, timeout, disabled)
if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize the archive scanner: %w", err)
}
return s, func() {}, nil
}

func dockerScanner(ctx context.Context, imageName string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) (
func dockerScanner(ctx context.Context, imageName string, ac cache.ArtifactCache, lac cache.LocalArtifactCache,
timeout time.Duration, disabled []analyzer.Type) (
scanner.Scanner, func(), error) {
s, cleanup, err := initializeDockerScanner(ctx, imageName, ac, lac, timeout)
s, cleanup, err := initializeDockerScanner(ctx, imageName, ac, lac, timeout, disabled)
if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a docker scanner: %w", err)
}
Expand Down
20 changes: 13 additions & 7 deletions internal/artifact/inject.go
Expand Up @@ -6,30 +6,36 @@ import (
"context"
"time"

"github.com/google/wire"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy/pkg/scanner"
"github.com/aquasecurity/trivy/pkg/vulnerability"
"github.com/google/wire"
)

func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache,
timeout time.Duration) (scanner.Scanner, func(), error) {
func initializeDockerScanner(ctx context.Context, imageName string, artifactCache cache.ArtifactCache,
localArtifactCache cache.LocalArtifactCache, timeout time.Duration, disableAnalyzers []analyzer.Type) (
scanner.Scanner, func(), error) {
wire.Build(scanner.StandaloneDockerSet)
return scanner.Scanner{}, nil, nil
}

func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache,
timeout time.Duration) (scanner.Scanner, error) {
func initializeArchiveScanner(ctx context.Context, filePath string, artifactCache cache.ArtifactCache,
localArtifactCache cache.LocalArtifactCache, timeout time.Duration, disableAnalyzers []analyzer.Type) (
scanner.Scanner, error) {
wire.Build(scanner.StandaloneArchiveSet)
return scanner.Scanner{}, nil
}

func initializeFilesystemScanner(ctx context.Context, dir string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) {
func initializeFilesystemScanner(ctx context.Context, dir string, artifactCache cache.ArtifactCache,
localArtifactCache cache.LocalArtifactCache, disableAnalyzers []analyzer.Type) (scanner.Scanner, func(), error) {
wire.Build(scanner.StandaloneFilesystemSet)
return scanner.Scanner{}, nil, nil
}

func initializeRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache, localArtifactCache cache.LocalArtifactCache) (scanner.Scanner, func(), error) {
func initializeRepositoryScanner(ctx context.Context, url string, artifactCache cache.ArtifactCache,
localArtifactCache cache.LocalArtifactCache, disableAnalyzers []analyzer.Type) (scanner.Scanner, func(), error) {
wire.Build(scanner.StandaloneRepositorySet)
return scanner.Scanner{}, nil, nil
}
Expand Down
6 changes: 4 additions & 2 deletions internal/artifact/repository.go
Expand Up @@ -7,14 +7,16 @@ import (
"github.com/urfave/cli/v2"
"golang.org/x/xerrors"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy/internal/artifact/config"
"github.com/aquasecurity/trivy/pkg/scanner"
)

func repositoryScanner(ctx context.Context, dir string, ac cache.ArtifactCache, lac cache.LocalArtifactCache, timeout time.Duration) (
func repositoryScanner(ctx context.Context, dir string, ac cache.ArtifactCache, lac cache.LocalArtifactCache,
_ time.Duration, disabled []analyzer.Type) (
scanner.Scanner, func(), error) {
s, cleanup, err := initializeRepositoryScanner(ctx, dir, ac, lac)
s, cleanup, err := initializeRepositoryScanner(ctx, dir, ac, lac, disabled)
if err != nil {
return scanner.Scanner{}, func() {}, xerrors.Errorf("unable to initialize a filesystem scanner: %w", err)
}
Expand Down
143 changes: 103 additions & 40 deletions internal/artifact/run.go
Expand Up @@ -2,12 +2,14 @@ package artifact

import (
"context"
"errors"
l "log"
"os"
"time"

"golang.org/x/xerrors"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy/internal/artifact/config"
Expand All @@ -19,96 +21,157 @@ import (
"github.com/aquasecurity/trivy/pkg/utils"
)

var errSkipScan = errors.New("skip subsequent processes")

// InitializeScanner type to define initialize function signature
type InitializeScanner func(context.Context, string, cache.ArtifactCache, cache.LocalArtifactCache, time.Duration) (
scanner.Scanner, func(), error)
type InitializeScanner func(context.Context, string, cache.ArtifactCache, cache.LocalArtifactCache, time.Duration,
[]analyzer.Type) (scanner.Scanner, func(), error)

func run(conf config.Config, initializeScanner InitializeScanner) error {
ctx, cancel := context.WithTimeout(context.Background(), conf.Timeout)
defer cancel()

// nolint: gocyclo
// TODO: refactror and fix cyclometic complexity
func run(c config.Config, initializeScanner InitializeScanner) error {
if err := log.InitLogger(c.Debug, c.Quiet); err != nil {
return runWithContext(ctx, conf, initializeScanner)
}

func runWithContext(ctx context.Context, conf config.Config, initializeScanner InitializeScanner) error {
if err := log.InitLogger(conf.Debug, conf.Quiet); err != nil {
l.Fatal(err)
}

// configure cache dir
cacheClient, err := initCache(conf)
if err != nil {
if errors.Is(err, errSkipScan) {
return nil
}
return xerrors.Errorf("cache error: %w", err)
}
defer cacheClient.Close()

if err = initDB(conf); err != nil {
if errors.Is(err, errSkipScan) {
return nil
}
return xerrors.Errorf("DB error: %w", err)
}
defer db.Close()

results, err := scan(ctx, conf, initializeScanner, cacheClient)
if err != nil {
return xerrors.Errorf("scan error: %w", err)
}

results, err = filter(ctx, conf, results)
if err != nil {
return xerrors.Errorf("filter error: %w", err)
}

if err = report.WriteResults(conf.Format, conf.Output, conf.Severities, results, conf.Template, conf.Light); err != nil {
return xerrors.Errorf("unable to write results: %w", err)
}

exit(conf, results)

return nil
}

func initCache(c config.Config) (operation.Cache, error) {
utils.SetCacheDir(c.CacheDir)
cache, err := operation.NewCache(c.CacheBackend)
if err != nil {
return xerrors.Errorf("unable to initialize the cache: %w", err)
return operation.Cache{}, xerrors.Errorf("unable to initialize the cache: %w", err)
}
defer cache.Close()
log.Logger.Debugf("cache dir: %s", utils.CacheDir())

if c.Reset {
return cache.Reset()
defer cache.Close()
if err = cache.Reset(); err != nil {
return operation.Cache{}, xerrors.Errorf("cache reset error: %w", err)
}
return operation.Cache{}, errSkipScan
}
if c.ClearCache {
return cache.ClearImages()
defer cache.Close()
if err = cache.ClearImages(); err != nil {
return operation.Cache{}, xerrors.Errorf("cache clear error: %w", err)
}
return operation.Cache{}, errSkipScan
}
return cache, nil
}

func initDB(c config.Config) error {
// download the database file
noProgress := c.Quiet || c.NoProgress
if err = operation.DownloadDB(c.AppVersion, c.CacheDir, noProgress, c.Light, c.SkipUpdate); err != nil {
if err := operation.DownloadDB(c.AppVersion, c.CacheDir, noProgress, c.Light, c.SkipUpdate); err != nil {
return err
}

if c.DownloadDBOnly {
return nil
return errSkipScan
}

if err = db.Init(c.CacheDir); err != nil {
if err := db.Init(c.CacheDir); err != nil {
return xerrors.Errorf("error in vulnerability DB initialize: %w", err)
}
defer db.Close()

target := c.Target
if c.Input != "" {
target = c.Input
}
return nil
}

ctx, cancel := context.WithTimeout(context.Background(), c.Timeout)
defer cancel()
scanner, cleanup, err := initializeScanner(ctx, target, cache, cache, c.Timeout)
if err != nil {
return xerrors.Errorf("unable to initialize a scanner: %w", err)
func scan(ctx context.Context, conf config.Config, initializeScanner InitializeScanner, cacheClient cache.Cache) (
report.Results, error) {
target := conf.Target
if conf.Input != "" {
target = conf.Input
}
defer cleanup()

scanOptions := types.ScanOptions{
VulnType: c.VulnType,
ScanRemovedPackages: c.ScanRemovedPkgs, // this is valid only for image subcommand
ListAllPackages: c.ListAllPkgs,
SkipFiles: c.SkipFiles,
SkipDirectories: c.SkipDirectories,
VulnType: conf.VulnType,
ScanRemovedPackages: conf.ScanRemovedPkgs, // this is valid only for image subcommand
ListAllPackages: conf.ListAllPkgs,
SkipFiles: conf.SkipFiles,
SkipDirectories: conf.SkipDirectories,
}
log.Logger.Debugf("Vulnerability type: %s", scanOptions.VulnType)

results, err := scanner.ScanArtifact(ctx, scanOptions)
// It doesn't analyze apk commands by default.
disabledAnalyzers := []analyzer.Type{analyzer.TypeApkCommand}
if conf.ScanRemovedPkgs {
disabledAnalyzers = []analyzer.Type{}
}

s, cleanup, err := initializeScanner(ctx, target, cacheClient, cacheClient, conf.Timeout, disabledAnalyzers)
if err != nil {
return nil, xerrors.Errorf("unable to initialize a scanner: %w", err)
}
defer cleanup()

results, err := s.ScanArtifact(ctx, scanOptions)
if err != nil {
return xerrors.Errorf("error in image scan: %w", err)
return nil, xerrors.Errorf("image scan failed: %w", err)
}
return results, nil
}

func filter(ctx context.Context, conf config.Config, results report.Results) (report.Results, error) {
vulnClient := initializeVulnerabilityClient()
for i := range results {
vulnClient.FillInfo(results[i].Vulnerabilities, results[i].Type)
vulns, err := vulnClient.Filter(ctx, results[i].Vulnerabilities,
c.Severities, c.IgnoreUnfixed, c.IgnoreFile, c.IgnorePolicy)
conf.Severities, conf.IgnoreUnfixed, conf.IgnoreFile, conf.IgnorePolicy)
if err != nil {
return xerrors.Errorf("unable to filter vulnerabilities: %w", err)
return nil, xerrors.Errorf("unable to filter vulnerabilities: %w", err)
}
results[i].Vulnerabilities = vulns
}
return results, nil
}

if err = report.WriteResults(c.Format, c.Output, c.Severities, results, c.Template, c.Light); err != nil {
return xerrors.Errorf("unable to write results: %w", err)
}

func exit(c config.Config, results report.Results) {
if c.ExitCode != 0 {
for _, result := range results {
if len(result.Vulnerabilities) > 0 {
os.Exit(c.ExitCode)
}
}
}
return nil
}

0 comments on commit 425eaf8

Please sign in to comment.