mirror of
https://github.com/anchore/syft
synced 2024-11-10 06:14:16 +00:00
4194a2cd34
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>
125 lines
2.4 KiB
Go
125 lines
2.4 KiB
Go
package sbomsync
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/anchore/syft/syft/artifact"
|
|
"github.com/anchore/syft/syft/linux"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
"github.com/anchore/syft/syft/sbom"
|
|
)
|
|
|
|
var _ interface {
|
|
Accessor
|
|
Builder
|
|
} = (*sbomBuilder)(nil) // integrity check
|
|
|
|
// Builder provides a simple facade for simple additions to the SBOM
|
|
type Builder interface {
|
|
// nodes
|
|
|
|
AddPackages(...pkg.Package)
|
|
|
|
DeletePackages(...artifact.ID)
|
|
|
|
// edges
|
|
|
|
AddRelationships(...artifact.Relationship)
|
|
|
|
// other
|
|
|
|
SetLinuxDistribution(linux.Release)
|
|
}
|
|
|
|
// Accessor allows for low-level access to the SBOM
|
|
type Accessor interface {
|
|
WriteToSBOM(func(*sbom.SBOM))
|
|
ReadFromSBOM(func(*sbom.SBOM))
|
|
}
|
|
|
|
type sbomBuilder struct {
|
|
sbom *sbom.SBOM
|
|
lock *sync.RWMutex
|
|
onWrite []func(*sbom.SBOM)
|
|
}
|
|
|
|
func NewBuilder(s *sbom.SBOM, onWrite ...func(*sbom.SBOM)) Builder {
|
|
return &sbomBuilder{
|
|
sbom: s,
|
|
lock: &sync.RWMutex{},
|
|
onWrite: onWrite,
|
|
}
|
|
}
|
|
|
|
func (b sbomBuilder) onWriteEvent() {
|
|
for _, fn := range b.onWrite {
|
|
fn(b.sbom)
|
|
}
|
|
}
|
|
|
|
func (b sbomBuilder) WriteToSBOM(fn func(*sbom.SBOM)) {
|
|
b.lock.Lock()
|
|
defer b.lock.Unlock()
|
|
|
|
fn(b.sbom)
|
|
b.onWriteEvent()
|
|
}
|
|
|
|
func (b sbomBuilder) ReadFromSBOM(fn func(*sbom.SBOM)) {
|
|
b.lock.RLock()
|
|
defer b.lock.RUnlock()
|
|
|
|
fn(b.sbom)
|
|
}
|
|
|
|
func (b sbomBuilder) AddPackages(p ...pkg.Package) {
|
|
b.lock.Lock()
|
|
defer b.lock.Unlock()
|
|
|
|
b.sbom.Artifacts.Packages.Add(p...)
|
|
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()
|
|
|
|
b.sbom.Relationships = append(b.sbom.Relationships, relationship...)
|
|
b.onWriteEvent()
|
|
}
|
|
|
|
func (b sbomBuilder) SetLinuxDistribution(release linux.Release) {
|
|
b.lock.Lock()
|
|
defer b.lock.Unlock()
|
|
|
|
b.sbom.Artifacts.LinuxDistribution = &release
|
|
b.onWriteEvent()
|
|
}
|