From 0f75f975c82086b5b8d3933db0127ceba4ed4e46 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 19 Jan 2023 19:28:42 -0500 Subject: [PATCH] Relax error conditions for catalogers (#1492) * binary cataloger should continue on errors Signed-off-by: Alex Goodman * test: add redirect for cmd stderr stdout Signed-off-by: Christopher Phillips * test: image update for test failure Signed-off-by: Christopher Phillips Signed-off-by: Alex Goodman Signed-off-by: Christopher Phillips Co-authored-by: Christopher Phillips --- syft/pkg/cataloger/binary/cataloger.go | 68 +++++++++++-------- syft/pkg/cataloger/binary/cataloger_test.go | 48 +++++++++++++ test/cli/spdx_tooling_validation_test.go | 2 + .../image-java-spdx-tools/Dockerfile | 2 +- 4 files changed, 91 insertions(+), 29 deletions(-) diff --git a/syft/pkg/cataloger/binary/cataloger.go b/syft/pkg/cataloger/binary/cataloger.go index 18b5cdd89..a3f8b19e6 100644 --- a/syft/pkg/cataloger/binary/cataloger.go +++ b/syft/pkg/cataloger/binary/cataloger.go @@ -1,6 +1,7 @@ package binary import ( + "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" @@ -30,41 +31,52 @@ func (c Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artif var packages []pkg.Package var relationships []artifact.Relationship - for _, classifier := range defaultClassifiers { - locations, err := resolver.FilesByGlob(classifier.FileGlob) + for _, cls := range defaultClassifiers { + pkgs, err := catalog(resolver, cls) if err != nil { - return nil, nil, err - } - for _, location := range locations { - reader, err := resolver.FileContentsByLocation(location) - if err != nil { - return nil, nil, err - } - locationReader := source.NewLocationReadCloser(location, reader) - newPkgs, err := classifier.EvidenceMatcher(classifier, locationReader) - if err != nil { - return nil, nil, err - } - newPackages: - for i := range newPkgs { - newPkg := &newPkgs[i] - for j := range packages { - p := &packages[j] - // consolidate identical packages found in different locations, - // but continue to track each location - if packagesMatch(p, newPkg) { - p.Locations.Add(newPkg.Locations.ToSlice()...) - continue newPackages - } - } - packages = append(packages, *newPkg) - } + log.WithFields("error", err, "classifier", cls.Class).Warn("unable to catalog binary package: %w", err) + continue } + packages = append(packages, pkgs...) } return packages, relationships, nil } +func catalog(resolver source.FileResolver, cls classifier) ([]pkg.Package, error) { + var pkgs []pkg.Package + locations, err := resolver.FilesByGlob(cls.FileGlob) + if err != nil { + return nil, err + } + for _, location := range locations { + reader, err := resolver.FileContentsByLocation(location) + if err != nil { + return nil, err + } + locationReader := source.NewLocationReadCloser(location, reader) + newPkgs, err := cls.EvidenceMatcher(cls, locationReader) + if err != nil { + return nil, err + } + newPackages: + for i := range newPkgs { + newPkg := &newPkgs[i] + for j := range pkgs { + p := &pkgs[j] + // consolidate identical packages found in different locations, + // but continue to track each location + if packagesMatch(p, newPkg) { + p.Locations.Add(newPkg.Locations.ToSlice()...) + continue newPackages + } + } + pkgs = append(pkgs, *newPkg) + } + } + return pkgs, nil +} + // packagesMatch returns true if the binary packages "match" based on basic criteria func packagesMatch(p1 *pkg.Package, p2 *pkg.Package) bool { if p1.Name != p2.Name || diff --git a/syft/pkg/cataloger/binary/cataloger_test.go b/syft/pkg/cataloger/binary/cataloger_test.go index 412b1aefa..c3af3bfcf 100644 --- a/syft/pkg/cataloger/binary/cataloger_test.go +++ b/syft/pkg/cataloger/binary/cataloger_test.go @@ -1,6 +1,8 @@ package binary import ( + "errors" + "io" "testing" "github.com/stretchr/testify/assert" @@ -433,3 +435,49 @@ func assertPackagesAreEqual(t *testing.T, expected pkg.Package, p pkg.Package) { assert.Failf(t, "packages not equal", "%v != %v", expected, p) } } + +type panicyResolver struct { + globCalled bool +} + +func (p panicyResolver) FileContentsByLocation(location source.Location) (io.ReadCloser, error) { + return nil, errors.New("not implemented") +} + +func (p panicyResolver) HasPath(s string) bool { + return true +} + +func (p panicyResolver) FilesByPath(paths ...string) ([]source.Location, error) { + return nil, errors.New("not implemented") +} + +func (p *panicyResolver) FilesByGlob(patterns ...string) ([]source.Location, error) { + p.globCalled = true + return nil, errors.New("not implemented") +} + +func (p panicyResolver) FilesByMIMEType(types ...string) ([]source.Location, error) { + return nil, errors.New("not implemented") +} + +func (p panicyResolver) RelativeFileByPath(_ source.Location, path string) *source.Location { + return nil +} + +func (p panicyResolver) AllLocations() <-chan source.Location { + return nil +} + +func (p panicyResolver) FileMetadataByLocation(location source.Location) (source.FileMetadata, error) { + return source.FileMetadata{}, errors.New("not implemented") +} + +func Test_Cataloger_ResilientToErrors(t *testing.T) { + c := NewCataloger() + + resolver := &panicyResolver{} + _, _, err := c.Catalog(resolver) + assert.NoError(t, err) + assert.True(t, resolver.globCalled) +} diff --git a/test/cli/spdx_tooling_validation_test.go b/test/cli/spdx_tooling_validation_test.go index eef290dee..a061a3592 100644 --- a/test/cli/spdx_tooling_validation_test.go +++ b/test/cli/spdx_tooling_validation_test.go @@ -36,6 +36,8 @@ func TestSpdxValidationTooling(t *testing.T) { fixturesPath := filepath.Join(cwd, "test-fixtures", "image-java-spdx-tools") buildCmd := exec.Command("make", "build") buildCmd.Dir = fixturesPath + buildCmd.Stdout = os.Stdout + buildCmd.Stderr = os.Stderr err = buildCmd.Run() require.NoError(t, err) }, diff --git a/test/cli/test-fixtures/image-java-spdx-tools/Dockerfile b/test/cli/test-fixtures/image-java-spdx-tools/Dockerfile index a0cc883f0..b32d68b9e 100644 --- a/test/cli/test-fixtures/image-java-spdx-tools/Dockerfile +++ b/test/cli/test-fixtures/image-java-spdx-tools/Dockerfile @@ -1,4 +1,4 @@ -FROM cgr.dev/chainguard/jdk +FROM openjdk:11 RUN wget https://github.com/spdx/tools-java/releases/download/v1.1.3/tools-java-1.1.3.zip && \ unzip tools-java-1.1.3.zip && \