mirror of
https://github.com/anchore/syft.git
synced 2026-10-11 21:57:22 +02:00
feat: add relationships to ELF package discovery (#2715)
This PR adds DependencyOf relationships when ELF packages have been discovered by the binary cataloger. The discovered file.Executable type has a []ImportedLibraries that's read from the file when discovered by syft. By mapping these imported libraries back to the package collection, syft is able to create relationships showing which packages are dependencies of other packages by just reading metadata from the ELF executable. --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Signed-off-by: Brian Ebarb <ebarb.brian@sers.noreply.github.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
co-authored by
Alex Goodman
parent
74b01a1c38
commit
4194a2cd34
@@ -20,6 +20,8 @@ type Builder interface {
|
||||
|
||||
AddPackages(...pkg.Package)
|
||||
|
||||
DeletePackages(...artifact.ID)
|
||||
|
||||
// edges
|
||||
|
||||
AddRelationships(...artifact.Relationship)
|
||||
@@ -78,6 +80,34 @@ func (b sbomBuilder) AddPackages(p ...pkg.Package) {
|
||||
b.onWriteEvent()
|
||||
}
|
||||
|
||||
func (b sbomBuilder) DeletePackages(ids ...artifact.ID) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
deleted := make(map[artifact.ID]struct{})
|
||||
for _, id := range ids {
|
||||
b.sbom.Artifacts.Packages.Delete(id)
|
||||
deleted[id] = struct{}{}
|
||||
}
|
||||
|
||||
// remove any relationships that reference the deleted packages
|
||||
var relationships []artifact.Relationship
|
||||
for _, rel := range b.sbom.Relationships {
|
||||
if _, ok := deleted[rel.From.ID()]; ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := deleted[rel.To.ID()]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// only keep relationships that don't reference the deleted packages
|
||||
relationships = append(relationships, rel)
|
||||
}
|
||||
|
||||
b.sbom.Relationships = relationships
|
||||
b.onWriteEvent()
|
||||
}
|
||||
|
||||
func (b sbomBuilder) AddRelationships(relationship ...artifact.Relationship) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package sbomsync
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/magiconair/properties/assert"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
func TestNewBuilder(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
sbom sbom.SBOM
|
||||
}{
|
||||
{
|
||||
"TestNewBuilder with empty sbom",
|
||||
sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
Packages: pkg.NewCollection(),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
builder := NewBuilder(&tt.sbom)
|
||||
builder.AddPackages(pkg.Package{})
|
||||
accessor := builder.(Accessor)
|
||||
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
|
||||
packageCount := s.Artifacts.Packages.PackageCount()
|
||||
assert.Equal(t, packageCount, 1, "expected 1 package in sbom")
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_sbomBuilder_DeletePackages(t *testing.T) {
|
||||
testPackage := pkg.Package{
|
||||
Name: "test",
|
||||
Version: "1.0.0",
|
||||
Type: pkg.DebPkg,
|
||||
}
|
||||
testPackage.SetID()
|
||||
|
||||
keepMe := pkg.Package{
|
||||
Name: "keepMe",
|
||||
Version: "1.0.0",
|
||||
Type: pkg.DebPkg,
|
||||
}
|
||||
|
||||
prexistingRelationships := []artifact.Relationship{
|
||||
{
|
||||
From: testPackage,
|
||||
To: testPackage,
|
||||
Type: artifact.DependencyOfRelationship,
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
sbom sbom.SBOM
|
||||
}{
|
||||
{
|
||||
"Test_sbomBuilder_DeletePackages deletes a given package",
|
||||
sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
Packages: pkg.NewCollection(),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
builder := NewBuilder(&tt.sbom)
|
||||
builder.AddPackages(testPackage, keepMe)
|
||||
accessor := builder.(Accessor)
|
||||
accessor.WriteToSBOM(func(s *sbom.SBOM) {
|
||||
s.Relationships = prexistingRelationships
|
||||
})
|
||||
|
||||
builder.DeletePackages(testPackage.ID())
|
||||
newAccess := builder.(Accessor)
|
||||
newAccess.ReadFromSBOM(func(s *sbom.SBOM) {
|
||||
packageCount := s.Artifacts.Packages.PackageCount()
|
||||
|
||||
// deleted target package
|
||||
assert.Equal(t, packageCount, 1, "expected 1 packages in sbom")
|
||||
relationshipCount := len(s.Relationships)
|
||||
|
||||
// deleted relationships that reference the deleted package
|
||||
assert.Equal(t, relationshipCount, 0, "expected 0 relationships in sbom")
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user