Skip to content

Commit

Permalink
feat: add artifact option to collect package files
Browse files Browse the repository at this point in the history
  • Loading branch information
lebauce committed Nov 6, 2023
1 parent 3e70f59 commit 7334338
Show file tree
Hide file tree
Showing 9 changed files with 37 additions and 21 deletions.
5 changes: 3 additions & 2 deletions pkg/fanal/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,9 @@ type PostAnalysisInput struct {
}

type AnalysisOptions struct {
Offline bool
FileChecksum bool
Offline bool
FileChecksum bool
CollectsFiles bool
}

type AnalysisResult struct {
Expand Down
8 changes: 5 additions & 3 deletions pkg/fanal/analyzer/pkg/apk/apk.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type alpinePkgAnalyzer struct{}

func (a alpinePkgAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) {
scanner := bufio.NewScanner(input.Content)
parsedPkgs, installedFiles := a.parseApkInfo(scanner)
parsedPkgs, installedFiles := a.parseApkInfo(scanner, input)

return &analyzer.AnalysisResult{
PackageInfos: []types.PackageInfo{
Expand All @@ -47,7 +47,7 @@ func (a alpinePkgAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInp
}, nil
}

func (a alpinePkgAnalyzer) parseApkInfo(scanner *bufio.Scanner) ([]types.Package, []string) {
func (a alpinePkgAnalyzer) parseApkInfo(scanner *bufio.Scanner, input analyzer.AnalysisInput) ([]types.Package, []string) {
var (
pkgs []types.Package
pkg types.Package
Expand Down Expand Up @@ -90,7 +90,9 @@ func (a alpinePkgAnalyzer) parseApkInfo(scanner *bufio.Scanner) ([]types.Package
dir = line[2:]
case "R:":
absPath := path.Join(dir, line[2:])
pkg.InstalledFiles = append(pkg.InstalledFiles, absPath)
if input.Options.CollectsFiles {
pkg.InstalledFiles = append(pkg.InstalledFiles, absPath)
}
installedFiles = append(installedFiles, absPath)
case "p:": // provides (corresponds to provides in PKGINFO, concatenated by spaces into a single line)
a.parseProvides(line, pkg.ID, provides)
Expand Down
3 changes: 2 additions & 1 deletion pkg/fanal/analyzer/pkg/apk/apk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

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

Expand Down Expand Up @@ -411,7 +412,7 @@ func TestParseApkInfo(t *testing.T) {
defer f.Close()
require.NoError(t, err)
scanner := bufio.NewScanner(f)
gotPkgs, gotFiles := a.parseApkInfo(scanner)
gotPkgs, gotFiles := a.parseApkInfo(scanner, analyzer.AnalysisInput{})

assert.Equal(t, tt.wantPkgs, gotPkgs)
assert.Equal(t, tt.wantFiles, gotFiles)
Expand Down
20 changes: 12 additions & 8 deletions pkg/fanal/analyzer/pkg/dpkg/dpkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ func (a dpkgAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysis
if err != nil {
return err
}
packageFiles[strings.TrimSuffix(filepath.Base(path), ".list")] = systemFiles
if input.Options.CollectsFiles {
packageFiles[strings.TrimSuffix(filepath.Base(path), ".list")] = systemFiles
}
systemInstalledFiles = append(systemInstalledFiles, systemFiles...)
return nil
}
Expand All @@ -92,14 +94,16 @@ func (a dpkgAnalyzer) PostAnalyze(_ context.Context, input analyzer.PostAnalysis
return nil, xerrors.Errorf("dpkg walk error: %w", err)
}

// map the packages to their respective files
for i, pkgInfo := range packageInfos {
for j, pkg := range pkgInfo.Packages {
installedFiles, found := packageFiles[pkg.Name]
if !found {
installedFiles = packageFiles[pkg.Name+":"+pkg.Arch]
if input.Options.CollectsFiles {
// map the packages to their respective files
for i, pkgInfo := range packageInfos {
for j, pkg := range pkgInfo.Packages {
installedFiles, found := packageFiles[pkg.Name]
if !found {
installedFiles = packageFiles[pkg.Name+":"+pkg.Arch]
}
packageInfos[i].Packages[j].InstalledFiles = installedFiles
}
packageInfos[i].Packages[j].InstalledFiles = installedFiles
}
}

Expand Down
9 changes: 6 additions & 3 deletions pkg/fanal/analyzer/pkg/rpm/rpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ var osVendors = []string{
type rpmPkgAnalyzer struct{}

func (a rpmPkgAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) {
parsedPkgs, installedFiles, err := a.parsePkgInfo(input.Content)
parsedPkgs, installedFiles, err := a.parsePkgInfo(input.Content, input)
if err != nil {
return nil, xerrors.Errorf("failed to parse rpmdb: %w", err)
}
Expand All @@ -80,7 +80,7 @@ func (a rpmPkgAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput)
}, nil
}

func (a rpmPkgAnalyzer) parsePkgInfo(rc io.Reader) (types.Packages, []string, error) {
func (a rpmPkgAnalyzer) parsePkgInfo(rc io.Reader, input analyzer.AnalysisInput) (types.Packages, []string, error) {
filePath, err := writeToTempFile(rc)
if err != nil {
return nil, nil, xerrors.Errorf("temp file error: %w", err)
Expand Down Expand Up @@ -154,7 +154,10 @@ func (a rpmPkgAnalyzer) parsePkgInfo(rc io.Reader) (types.Packages, []string, er
DependsOn: pkg.Requires, // Will be replaced with package IDs
Maintainer: pkg.Vendor,
Digest: d,
InstalledFiles: files,
}

if input.Options.CollectsFiles {
p.InstalledFiles = files
}
pkgs = append(pkgs, p)
installedFiles = append(installedFiles, files...)
Expand Down
3 changes: 2 additions & 1 deletion pkg/fanal/analyzer/pkg/rpm/rpm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

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

Expand Down Expand Up @@ -547,7 +548,7 @@ func TestParseRpmInfo(t *testing.T) {
require.NoError(t, err)
defer f.Close()

got, _, err := a.parsePkgInfo(f)
got, _, err := a.parsePkgInfo(f, analyzer.AnalysisInput{})
require.NoError(t, err)

sort.Sort(tc.pkgs)
Expand Down
1 change: 1 addition & 0 deletions pkg/fanal/artifact/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Option struct {
NoProgress bool
Insecure bool
Offline bool
CollectFiles bool
AppDirs []string
SBOMSources []string
RekorURL string
Expand Down
5 changes: 3 additions & 2 deletions pkg/fanal/artifact/local/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ func (a Artifact) Inspect(ctx context.Context) (types.ArtifactReference, error)
result := analyzer.NewAnalysisResult()
limit := semaphore.New(a.artifactOption.Slow)
opts := analyzer.AnalysisOptions{
Offline: a.artifactOption.Offline,
FileChecksum: a.artifactOption.FileChecksum,
Offline: a.artifactOption.Offline,
FileChecksum: a.artifactOption.FileChecksum,
CollectsFiles: a.artifactOption.CollectFiles,
}

// Prepare filesystem for post analysis
Expand Down
4 changes: 3 additions & 1 deletion pkg/fanal/test/integration/containerd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func TestContainerd_SearchLocalStoreByNameOrDigest(t *testing.T) {
}
require.NoError(t, err)

ar, err := aimage.NewArtifact(img, c, artifact.Option{})
ar, err := aimage.NewArtifact(img, c, artifact.Option{CollectFiles: true})
require.NoError(t, err)

ref, err := ar.Inspect(ctx)
Expand Down Expand Up @@ -694,6 +694,7 @@ func localImageTestWithNamespace(t *testing.T, namespace string) {
analyzer.TypeExecutable,
analyzer.TypeLicenseFile,
},
CollectFiles: true,
})
require.NoError(t, err)

Expand Down Expand Up @@ -830,6 +831,7 @@ func TestContainerd_PullImage(t *testing.T) {
analyzer.TypeExecutable,
analyzer.TypeLicenseFile,
},
CollectFiles: true,
})
require.NoError(t, err)
require.NotNil(t, art)
Expand Down

0 comments on commit 7334338

Please sign in to comment.