mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 02:26:42 +01:00
Infer the package type from ELF package notes (#3008)
* fix ELF package types to be honored Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * prefer OS packages over binary packages when there are duplicates Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
c816039e91
commit
573440b7cf
@ -10,7 +10,8 @@ import (
|
|||||||
func TestMarinerDistroless(t *testing.T) {
|
func TestMarinerDistroless(t *testing.T) {
|
||||||
sbom, _ := catalogFixtureImage(t, "image-mariner-distroless", source.SquashedScope)
|
sbom, _ := catalogFixtureImage(t, "image-mariner-distroless", source.SquashedScope)
|
||||||
|
|
||||||
expectedPkgs := 12
|
// 12 RPMs + 2 binaries with ELF package notes claiming to be RPMs
|
||||||
|
expectedPkgs := 14
|
||||||
actualPkgs := 0
|
actualPkgs := 0
|
||||||
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
||||||
actualPkgs += 1
|
actualPkgs += 1
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package relationship
|
package relationship
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/sbomsync"
|
"github.com/anchore/syft/internal/sbomsync"
|
||||||
@ -21,6 +22,10 @@ var (
|
|||||||
binaryCatalogerTypes = []pkg.Type{
|
binaryCatalogerTypes = []pkg.Type{
|
||||||
pkg.BinaryPkg,
|
pkg.BinaryPkg,
|
||||||
}
|
}
|
||||||
|
binaryMetadataTypes = []string{
|
||||||
|
reflect.TypeOf(pkg.ELFBinaryPackageNoteJSONPayload{}).Name(),
|
||||||
|
reflect.TypeOf(pkg.BinarySignature{}).Name(),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExcludeBinariesByFileOwnershipOverlap(accessor sbomsync.Accessor) {
|
func ExcludeBinariesByFileOwnershipOverlap(accessor sbomsync.Accessor) {
|
||||||
@ -60,5 +65,15 @@ func excludeBinaryByFileOwnershipOverlap(r artifact.Relationship, c *pkg.Collect
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return slices.Contains(binaryCatalogerTypes, child.Type)
|
if slices.Contains(binaryCatalogerTypes, child.Type) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if child.Metadata == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
childMetadataType := reflect.TypeOf(child.Metadata)
|
||||||
|
|
||||||
|
return slices.Contains(binaryMetadataTypes, childMetadataType.Name())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,9 @@ func TestExclude(t *testing.T) {
|
|||||||
packageB := pkg.Package{Name: "package-a", Type: pkg.PythonPkg}
|
packageB := pkg.Package{Name: "package-a", Type: pkg.PythonPkg}
|
||||||
packageC := pkg.Package{Name: "package-a", Type: pkg.BinaryPkg}
|
packageC := pkg.Package{Name: "package-a", Type: pkg.BinaryPkg}
|
||||||
packageD := pkg.Package{Name: "package-d", Type: pkg.BinaryPkg}
|
packageD := pkg.Package{Name: "package-d", Type: pkg.BinaryPkg}
|
||||||
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD} {
|
packageE := pkg.Package{Name: "package-e", Type: pkg.RpmPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}}
|
||||||
|
packageF := pkg.Package{Name: "package-f", Type: pkg.RpmPkg, Metadata: pkg.BinarySignature{}}
|
||||||
|
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD, &packageE, &packageF} {
|
||||||
p := p
|
p := p
|
||||||
p.SetID()
|
p.SetID()
|
||||||
}
|
}
|
||||||
@ -43,6 +45,26 @@ func TestExclude(t *testing.T) {
|
|||||||
packages: pkg.NewCollection(packageA, packageC),
|
packages: pkg.NewCollection(packageA, packageC),
|
||||||
shouldExclude: true,
|
shouldExclude: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "exclusions from os -> elf binary (as RPM)",
|
||||||
|
relationship: artifact.Relationship{
|
||||||
|
Type: artifact.OwnershipByFileOverlapRelationship,
|
||||||
|
From: packageA,
|
||||||
|
To: packageE,
|
||||||
|
},
|
||||||
|
packages: pkg.NewCollection(packageA, packageE),
|
||||||
|
shouldExclude: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "exclusions from os -> binary (masquerading as RPM)",
|
||||||
|
relationship: artifact.Relationship{
|
||||||
|
Type: artifact.OwnershipByFileOverlapRelationship,
|
||||||
|
From: packageA,
|
||||||
|
To: packageF,
|
||||||
|
},
|
||||||
|
packages: pkg.NewCollection(packageA, packageF),
|
||||||
|
shouldExclude: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "no exclusions from python -> binary",
|
name: "no exclusions from python -> binary",
|
||||||
relationship: artifact.Relationship{
|
relationship: artifact.Relationship{
|
||||||
|
|||||||
@ -13,7 +13,7 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p
|
|||||||
Version: metadata.Version,
|
Version: metadata.Version,
|
||||||
Licenses: pkg.NewLicenseSet(pkg.NewLicense(metadata.License)),
|
Licenses: pkg.NewLicenseSet(pkg.NewLicense(metadata.License)),
|
||||||
PURL: packageURL(metadata),
|
PURL: packageURL(metadata),
|
||||||
Type: pkg.BinaryPkg,
|
Type: pkgType(metadata.Type),
|
||||||
Locations: locations,
|
Locations: locations,
|
||||||
Metadata: metadata.ELFBinaryPackageNoteJSONPayload,
|
Metadata: metadata.ELFBinaryPackageNoteJSONPayload,
|
||||||
}
|
}
|
||||||
@ -67,6 +67,8 @@ func packageURL(metadata elfBinaryPackageNotes) string {
|
|||||||
).ToString()
|
).ToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const alpmType = "alpm"
|
||||||
|
|
||||||
func purlDistroType(ty string) string {
|
func purlDistroType(ty string) string {
|
||||||
switch ty {
|
switch ty {
|
||||||
case "rpm":
|
case "rpm":
|
||||||
@ -75,8 +77,22 @@ func purlDistroType(ty string) string {
|
|||||||
return packageurl.TypeDebian
|
return packageurl.TypeDebian
|
||||||
case "apk":
|
case "apk":
|
||||||
return packageurl.TypeAlpine
|
return packageurl.TypeAlpine
|
||||||
case "alpm":
|
case alpmType:
|
||||||
return "alpm"
|
return alpmType
|
||||||
}
|
}
|
||||||
return packageurl.TypeGeneric
|
return packageurl.TypeGeneric
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pkgType(ty string) pkg.Type {
|
||||||
|
switch ty {
|
||||||
|
case "rpm":
|
||||||
|
return pkg.RpmPkg
|
||||||
|
case "deb":
|
||||||
|
return pkg.DebPkg
|
||||||
|
case "apk":
|
||||||
|
return pkg.ApkPkg
|
||||||
|
case alpmType:
|
||||||
|
return pkg.AlpmPkg
|
||||||
|
}
|
||||||
|
return pkg.BinaryPkg
|
||||||
|
}
|
||||||
|
|||||||
@ -77,7 +77,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
|
|||||||
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||||
),
|
),
|
||||||
Licenses: pkg.NewLicenseSet(),
|
Licenses: pkg.NewLicenseSet(),
|
||||||
Type: pkg.BinaryPkg,
|
Type: pkg.RpmPkg,
|
||||||
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
|
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
|
||||||
Type: "rpm",
|
Type: "rpm",
|
||||||
Architecture: "x86_64",
|
Architecture: "x86_64",
|
||||||
@ -99,7 +99,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
|
|||||||
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||||
),
|
),
|
||||||
Licenses: pkg.NewLicenseSet(),
|
Licenses: pkg.NewLicenseSet(),
|
||||||
Type: pkg.BinaryPkg,
|
Type: pkg.RpmPkg,
|
||||||
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
|
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
|
||||||
Type: "rpm",
|
Type: "rpm",
|
||||||
Architecture: "arm",
|
Architecture: "arm",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user