mirror of
https://github.com/anchore/syft.git
synced 2026-10-30 14:02:26 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3bd5145d2 | ||
|
|
6a33b80048 |
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/anchore/syft/syft/pkg/cataloger/alpine"
|
"github.com/anchore/syft/syft/pkg/cataloger/alpine"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/arch"
|
"github.com/anchore/syft/syft/pkg/cataloger/arch"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||||
|
bitnamiSbomCataloger "github.com/anchore/syft/syft/pkg/cataloger/bitnami"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/cpp"
|
"github.com/anchore/syft/syft/pkg/cataloger/cpp"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/dart"
|
"github.com/anchore/syft/syft/pkg/cataloger/dart"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/debian"
|
"github.com/anchore/syft/syft/pkg/cataloger/debian"
|
||||||
@@ -150,6 +151,7 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
|
|||||||
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "linux", "kernel",
|
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "linux", "kernel",
|
||||||
),
|
),
|
||||||
newSimplePackageTaskFactory(sbomCataloger.NewCataloger, "sbom"), // note: not evidence of installed packages
|
newSimplePackageTaskFactory(sbomCataloger.NewCataloger, "sbom"), // note: not evidence of installed packages
|
||||||
|
newSimplePackageTaskFactory(bitnamiSbomCataloger.NewCataloger, "bitnami", pkgcataloging.InstalledTag, pkgcataloging.ImageTag),
|
||||||
newSimplePackageTaskFactory(wordpress.NewWordpressPluginCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "wordpress"),
|
newSimplePackageTaskFactory(wordpress.NewWordpressPluginCataloger, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "wordpress"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
Package bitnami provides a concrete Cataloger implementation for capturing packages embedded within Bitnami SBOM files.
|
||||||
|
*/
|
||||||
|
package bitnami
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
"github.com/anchore/syft/syft/format"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
const catalogerName = "bitnami-cataloger"
|
||||||
|
|
||||||
|
// NewCataloger returns a new SBOM cataloger object loaded from saved SBOM JSON.
|
||||||
|
func NewCataloger() pkg.Cataloger {
|
||||||
|
return generic.NewCataloger(catalogerName).
|
||||||
|
WithParserByGlobs(parseSBOM,
|
||||||
|
"/opt/bitnami/**/.spdx-*.spdx",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this is copied from the sbom-cataloger
|
||||||
|
// it should probably be slimmed down so as not to duplicate
|
||||||
|
// parts of the SBOM cataloger that it doesn't need.
|
||||||
|
func parseSBOM(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
readSeeker, err := adaptToReadSeeker(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to read SBOM file %q: %w", reader.Location.RealPath, err)
|
||||||
|
}
|
||||||
|
s, _, _, err := format.Decode(readSeeker)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s == nil {
|
||||||
|
log.WithFields("path", reader.Location.RealPath).Trace("file is not an SBOM")
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var pkgs []pkg.Package
|
||||||
|
relationships := s.Relationships
|
||||||
|
for _, p := range s.Artifacts.Packages.Sorted() {
|
||||||
|
// replace all locations on the package with the location of the SBOM file.
|
||||||
|
// Why not keep the original list of locations? Since the "locations" field is meant to capture
|
||||||
|
// where there is evidence of this file, and the catalogers have not run against any file other than,
|
||||||
|
// the SBOM, this is the only location that is relevant for this cataloger.
|
||||||
|
p.Locations = file.NewLocationSet(
|
||||||
|
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||||
|
)
|
||||||
|
p.FoundBy = catalogerName
|
||||||
|
|
||||||
|
pkgs = append(pkgs, p)
|
||||||
|
relationships = append(relationships, artifact.Relationship{
|
||||||
|
From: p,
|
||||||
|
To: reader.Location.Coordinates,
|
||||||
|
Type: artifact.DescribedByRelationship,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkgs, relationships, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func adaptToReadSeeker(reader io.Reader) (io.ReadSeeker, error) {
|
||||||
|
// with the stereoscope API and default file.Resolver implementation here in syft, odds are very high that
|
||||||
|
// the underlying reader is already a ReadSeeker, so we can just return it as-is. We still want to
|
||||||
|
if rs, ok := reader.(io.ReadSeeker); ok {
|
||||||
|
return rs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("SBOM cataloger reader is not a ReadSeeker, reading entire SBOM into memory")
|
||||||
|
|
||||||
|
var buff bytes.Buffer
|
||||||
|
_, err := io.Copy(&buff, reader)
|
||||||
|
return bytes.NewReader(buff.Bytes()), err
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package bitnami
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBitnamiCataloger(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fixture string
|
||||||
|
wantPkgs []pkg.Package
|
||||||
|
wantError require.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "simple-redis-sbom",
|
||||||
|
fixture: "test-fixtures",
|
||||||
|
// TODO: add package assertions
|
||||||
|
},
|
||||||
|
// TODO: add another test case or too, maybe an error case
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
pkgtest.NewCatalogTester().
|
||||||
|
FromDirectory(t, tt.fixture).
|
||||||
|
ExpectsAssertion(func(t *testing.T, pkgs []pkg.Package, relationships []artifact.Relationship) {
|
||||||
|
for i, p := range pkgs {
|
||||||
|
assert.Equal(t, p.Name, tt.wantPkgs[i].Name)
|
||||||
|
assert.Equal(t, p.Version, tt.wantPkgs[i].Version)
|
||||||
|
}
|
||||||
|
}).
|
||||||
|
TestCataloger(t, NewCataloger())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"SPDXID": "SPDXRef-redis",
|
||||||
|
"spdxVersion": "SPDX-2.3",
|
||||||
|
"creationInfo": {
|
||||||
|
"created": "2024-08-08T11:12:35.680Z",
|
||||||
|
"creators": [
|
||||||
|
"Organization: VMware, Inc."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "SPDX document for Redis(R) 7.4.0",
|
||||||
|
"dataLicense": "CC0-1.0",
|
||||||
|
"documentDescribes": [
|
||||||
|
"SPDXRef-redis"
|
||||||
|
],
|
||||||
|
"documentNamespace": "redis-7.4.0",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"SPDXID": "SPDXRef-redis",
|
||||||
|
"name": "redis",
|
||||||
|
"versionInfo": "7.4.0-0",
|
||||||
|
"downloadLocation": "http://download.redis.io/releases/redis-7.4.0.tar.gz",
|
||||||
|
"licenseConcluded": "RSALv2",
|
||||||
|
"licenseDeclared": "RSALv2",
|
||||||
|
"filesAnalyzed": false,
|
||||||
|
"externalRefs": [
|
||||||
|
{
|
||||||
|
"referenceCategory": "SECURITY",
|
||||||
|
"referenceType": "cpe23Type",
|
||||||
|
"referenceLocator": "cpe:2.3:*:redis:redis:7.4.0:*:*:*:*:*:*:*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"referenceCategory": "PACKAGE-MANAGER",
|
||||||
|
"referenceType": "purl",
|
||||||
|
"referenceLocator": "pkg:bitnami/redis@7.4.0-0?arch=arm64&distro=debian-12"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"copyrightText": "NOASSERTION"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"files": [],
|
||||||
|
"relationships": []
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user