Skip to content

Commit

Permalink
refactor: define vulnerability scanner interfaces (#4117)
Browse files Browse the repository at this point in the history
  • Loading branch information
knqyf263 authored May 9, 2023
1 parent 090a00e commit 45d5edb
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 210 deletions.
33 changes: 20 additions & 13 deletions pkg/commands/artifact/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 1 addition & 4 deletions pkg/detector/ospkg/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,8 @@ type Driver interface {
IsSupportedVersion(string, string) bool
}

// Detector implements Operation
type Detector struct{}

// Detect detects the vulnerabilities
func (d Detector) Detect(_, osFamily, osName string, repo *ftypes.Repository, _ time.Time, pkgs []ftypes.Package) ([]types.DetectedVulnerability, bool, error) {
func Detect(_, osFamily, osName string, repo *ftypes.Repository, _ time.Time, pkgs []ftypes.Package) ([]types.DetectedVulnerability, bool, error) {
driver, err := newDriver(osFamily)
if err != nil {
return nil, false, ErrUnsupportedOS
Expand Down
19 changes: 12 additions & 7 deletions pkg/fanal/applier/applier.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,36 @@ import (

"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
"github.com/aquasecurity/trivy/pkg/fanal/cache"
"github.com/aquasecurity/trivy/pkg/fanal/types"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
)

type Applier struct {
// Applier defines operation to scan image layers
type Applier interface {
ApplyLayers(artifactID string, blobIDs []string) (detail ftypes.ArtifactDetail, err error)
}

type applier struct {
cache cache.LocalArtifactCache
}

func NewApplier(c cache.LocalArtifactCache) Applier {
return Applier{cache: c}
return &applier{cache: c}
}

func (a Applier) ApplyLayers(imageID string, layerKeys []string) (types.ArtifactDetail, error) {
var layers []types.BlobInfo
func (a *applier) ApplyLayers(imageID string, layerKeys []string) (ftypes.ArtifactDetail, error) {
var layers []ftypes.BlobInfo
for _, key := range layerKeys {
blob, _ := a.cache.GetBlob(key) // nolint
if blob.SchemaVersion == 0 {
return types.ArtifactDetail{}, xerrors.Errorf("layer cache missing: %s", key)
return ftypes.ArtifactDetail{}, xerrors.Errorf("layer cache missing: %s", key)
}
layers = append(layers, blob)
}

mergedLayer := ApplyLayers(layers)

imageInfo, _ := a.cache.GetArtifact(imageID) // nolint
mergedLayer.ImageConfig = types.ImageConfigDetail{
mergedLayer.ImageConfig = ftypes.ImageConfigDetail{
Packages: imageInfo.HistoryPackages,
Misconfiguration: imageInfo.Misconfiguration,
Secret: imageInfo.Secret,
Expand Down
10 changes: 6 additions & 4 deletions pkg/rpc/server/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

102 changes: 102 additions & 0 deletions pkg/scanner/langpkg/scan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package langpkg

import (
"sort"

"golang.org/x/xerrors"

"github.com/aquasecurity/trivy/pkg/detector/library"
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/types"
)

var (
PkgTargets = map[string]string{
ftypes.PythonPkg: "Python",
ftypes.CondaPkg: "Conda",
ftypes.GemSpec: "Ruby",
ftypes.NodePkg: "Node.js",
ftypes.Jar: "Java",
}
)

type Scanner interface {
Packages(detail ftypes.ArtifactDetail, options types.ScanOptions) types.Results
Scan(detail ftypes.ArtifactDetail, options types.ScanOptions) (types.Results, error)
}

type scanner struct{}

func NewScanner() Scanner {
return &scanner{}
}

func (s *scanner) Packages(detail ftypes.ArtifactDetail, _ types.ScanOptions) types.Results {
var results types.Results
for _, app := range detail.Applications {
if len(app.Libraries) == 0 {
continue
}
target := app.FilePath
if t, ok := PkgTargets[app.Type]; ok && target == "" {
// When the file path is empty, we will overwrite it with the pre-defined value.
target = t
}

results = append(results, types.Result{
Target: target,
Class: types.ClassLangPkg,
Type: app.Type,
Packages: app.Libraries,
})
}
return results
}

func (s *scanner) Scan(detail ftypes.ArtifactDetail, _ types.ScanOptions) (types.Results, error) {
apps := detail.Applications
log.Logger.Infof("Number of language-specific files: %d", len(apps))
if len(apps) == 0 {
return nil, nil
}

var results types.Results
printedTypes := map[string]struct{}{}
for _, app := range apps {
if len(app.Libraries) == 0 {
continue
}

// Prevent the same log messages from being displayed many times for the same type.
if _, ok := printedTypes[app.Type]; !ok {
log.Logger.Infof("Detecting %s vulnerabilities...", app.Type)
printedTypes[app.Type] = struct{}{}
}

log.Logger.Debugf("Detecting library vulnerabilities, type: %s, path: %s", app.Type, app.FilePath)
vulns, err := library.Detect(app.Type, app.Libraries)
if err != nil {
return nil, xerrors.Errorf("failed vulnerability detection of libraries: %w", err)
} else if len(vulns) == 0 {
continue
}

target := app.FilePath
if t, ok := PkgTargets[app.Type]; ok && target == "" {
// When the file path is empty, we will overwrite it with the pre-defined value.
target = t
}

results = append(results, types.Result{
Target: target,
Vulnerabilities: vulns,
Class: types.ClassLangPkg,
Type: app.Type,
})
}
sort.Slice(results, func(i, j int) bool {
return results[i].Target < results[j].Target
})
return results, nil
}
Loading

0 comments on commit 45d5edb

Please sign in to comment.