fix(detector): library.Scan move to detector (#1864)

This commit is contained in:
MaineK00n
2024-03-06 16:59:06 +09:00
committed by GitHub
parent dc496468b9
commit bf14b5f61f
2 changed files with 134 additions and 136 deletions

View File

@@ -5,12 +5,20 @@ package detector
import (
"context"
"errors"
"fmt"
"strings"
"github.com/aquasecurity/go-dep-parser/pkg/java/jar"
trivydb "github.com/aquasecurity/trivy-db/pkg/db"
"github.com/aquasecurity/trivy-db/pkg/metadata"
trivydbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy/pkg/db"
"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"
"github.com/samber/lo"
"golang.org/x/xerrors"
"github.com/future-architect/vuls/config"
@@ -19,6 +27,11 @@ import (
"github.com/future-architect/vuls/models"
)
type libraryDetector struct {
scanner models.LibraryScanner
javaDBClient *javadb.DBClient
}
// DetectLibsCves fills LibraryScanner information
func DetectLibsCves(r *models.ScanResult, trivyOpts config.TrivyOpts, logOpts logging.LogOpts, noProgress bool) (err error) {
totalCnt := 0
@@ -44,6 +57,7 @@ func DetectLibsCves(r *models.ScanResult, trivyOpts config.TrivyOpts, logOpts lo
var javaDBClient *javadb.DBClient
defer javaDBClient.Close()
for _, lib := range r.LibraryScanners {
d := libraryDetector{scanner: lib}
if lib.Type == ftypes.Jar {
if javaDBClient == nil {
if err := javadb.UpdateJavaDB(trivyOpts, noProgress); err != nil {
@@ -55,10 +69,10 @@ func DetectLibsCves(r *models.ScanResult, trivyOpts config.TrivyOpts, logOpts lo
return xerrors.Errorf("Failed to open Trivy Java DB. err: %w", err)
}
}
lib.JavaDBClient = javaDBClient
d.javaDBClient = javaDBClient
}
vinfos, err := lib.Scan()
vinfos, err := d.scan()
if err != nil {
return xerrors.Errorf("Failed to scan library. err: %w", err)
}
@@ -113,3 +127,121 @@ func showDBInfo(cacheDir string) error {
meta.Version, meta.UpdatedAt, meta.NextUpdate, meta.DownloadedAt)
return nil
}
// Scan : scan target library
func (d libraryDetector) scan() ([]models.VulnInfo, error) {
if d.scanner.Type == ftypes.Jar {
if err := d.improveJARInfo(); err != nil {
return nil, xerrors.Errorf("Failed to improve JAR information by trivy Java DB. err: %w", err)
}
}
scanner, ok := library.NewDriver(d.scanner.Type)
if !ok {
return nil, xerrors.Errorf("Failed to new a library driver for %s", d.scanner.Type)
}
var vulnerabilities = []models.VulnInfo{}
for _, pkg := range d.scanner.Libs {
tvulns, err := scanner.DetectVulnerabilities("", pkg.Name, pkg.Version)
if err != nil {
return nil, xerrors.Errorf("Failed to detect %s vulnerabilities. err: %w", scanner.Type(), err)
}
if len(tvulns) == 0 {
continue
}
vulns := d.convertFanalToVuln(tvulns)
vulnerabilities = append(vulnerabilities, vulns...)
}
return vulnerabilities, nil
}
func (d *libraryDetector) improveJARInfo() error {
libs := make([]models.Library, 0, len(d.scanner.Libs))
for _, l := range d.scanner.Libs {
if l.Digest == "" {
// This is the case from pom.properties, it should be respected as is.
libs = append(libs, l)
continue
}
algorithm, sha1, found := strings.Cut(l.Digest, ":")
if !found || algorithm != "sha1" {
logging.Log.Debugf("No SHA1 hash found for %s in the digest: %q", l.FilePath, l.Digest)
libs = append(libs, l)
continue
}
foundProps, err := d.javaDBClient.SearchBySHA1(sha1)
if err != nil {
if !errors.Is(err, jar.ArtifactNotFoundErr) {
return xerrors.Errorf("Failed to search trivy Java DB. err: %w", err)
}
logging.Log.Debugf("No record in Java DB for %s by SHA1: %s", l.FilePath, sha1)
libs = append(libs, l)
continue
}
foundLib := foundProps.Library()
l.Name = foundLib.Name
l.Version = foundLib.Version
libs = append(libs, l)
}
d.scanner.Libs = lo.UniqBy(libs, func(lib models.Library) string {
return fmt.Sprintf("%s::%s::%s", lib.Name, lib.Version, lib.FilePath)
})
return nil
}
func (d libraryDetector) convertFanalToVuln(tvulns []types.DetectedVulnerability) (vulns []models.VulnInfo) {
for _, tvuln := range tvulns {
vinfo, err := d.getVulnDetail(tvuln)
if err != nil {
logging.Log.Debugf("failed to getVulnDetail. err: %+v, tvuln: %#v", err, tvuln)
continue
}
vulns = append(vulns, vinfo)
}
return vulns
}
func (d libraryDetector) getVulnDetail(tvuln types.DetectedVulnerability) (vinfo models.VulnInfo, err error) {
vul, err := trivydb.Config{}.GetVulnerability(tvuln.VulnerabilityID)
if err != nil {
return vinfo, err
}
vinfo.CveID = tvuln.VulnerabilityID
vinfo.CveContents = getCveContents(tvuln.VulnerabilityID, vul)
vinfo.LibraryFixedIns = []models.LibraryFixedIn{
{
Key: d.scanner.GetLibraryKey(),
Name: tvuln.PkgName,
FixedIn: tvuln.FixedVersion,
Path: d.scanner.LockfilePath,
},
}
return vinfo, nil
}
func getCveContents(cveID string, vul trivydbTypes.Vulnerability) (contents map[models.CveContentType][]models.CveContent) {
contents = map[models.CveContentType][]models.CveContent{}
refs := []models.Reference{}
for _, refURL := range vul.References {
refs = append(refs, models.Reference{Source: "trivy", Link: refURL})
}
contents[models.Trivy] = []models.CveContent{
{
Type: models.Trivy,
CveID: cveID,
Title: vul.Title,
Summary: vul.Description,
Cvss3Severity: string(vul.Severity),
References: refs,
},
}
return contents
}