mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
98 lines
3.6 KiB
Go
98 lines
3.6 KiB
Go
package binary
|
|
|
|
import (
|
|
"path"
|
|
|
|
"github.com/anchore/syft/internal/sbomsync"
|
|
"github.com/anchore/syft/syft/artifact"
|
|
"github.com/anchore/syft/syft/file"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
"github.com/anchore/syft/syft/sbom"
|
|
)
|
|
|
|
func NewDependencyRelationships(resolver file.Resolver, accessor sbomsync.Accessor) []artifact.Relationship {
|
|
// TODO: consider library format (e.g. ELF, Mach-O, PE) for the meantime assume all binaries are homogeneous format
|
|
|
|
// start with building new file-to-file relationships for executables-to-executables
|
|
// you need to make certain that they are unique, store in a map[id]map[id]relationship to avoid dupes.
|
|
// before creating the new file-to-file relationship, check to see if there are packages that represent each
|
|
// file. If there are, create a package-to-package, file-to-package, or package-to-file relationship as appropriate.
|
|
|
|
// 1 & 2... build an index of all shared libraries and their owning packages to search against
|
|
index := newShareLibIndex(resolver, accessor)
|
|
|
|
// 3. craft package-to-package or package-to-file relationships that represent binary shared library dependencies
|
|
// note: prefer package-to-package relationships over package-to-file relationships
|
|
|
|
relIndex := newRelationshipIndex()
|
|
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
|
|
// read all existing dependencyOf relationships
|
|
for _, r := range s.Relationships {
|
|
if r.Type != artifact.DependencyOfRelationship {
|
|
continue
|
|
}
|
|
relIndex.track(r)
|
|
}
|
|
})
|
|
|
|
// find all new relationships to add...
|
|
accessor.ReadFromSBOM(func(s *sbom.SBOM) {
|
|
for _, parentPkg := range s.Artifacts.Packages.Sorted(pkg.BinaryPkg) {
|
|
for _, evidentLocation := range parentPkg.Locations.ToSlice() {
|
|
if evidentLocation.Annotations[pkg.EvidenceAnnotationKey] != pkg.PrimaryEvidenceAnnotation {
|
|
continue
|
|
}
|
|
|
|
// find all libraries that this package depends on
|
|
exec, ok := s.Artifacts.Executables[evidentLocation.Coordinates]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
for _, libReference := range exec.ImportedLibraries {
|
|
// TODO: is this always a basename? technically no, it could be a path...
|
|
libBasename := path.Base(libReference)
|
|
|
|
pkgsThatOwnLib := index.owningLibraryPackage(libBasename)
|
|
if pkgsThatOwnLib == nil {
|
|
// create package-to-file relationship...
|
|
// if there is more than one library for this given library name, then we will include
|
|
// all of them as dependencies since we don't know the LD_LIBRARY_PATH order
|
|
// TODO: add configuration for LD_LIBRARY_PATH order?
|
|
for _, libCoord := range index.owningLibraryLocations(libBasename).ToSlice() {
|
|
relIndex.add(
|
|
artifact.Relationship{
|
|
From: libCoord,
|
|
To: parentPkg,
|
|
Type: artifact.DependencyOfRelationship,
|
|
},
|
|
)
|
|
}
|
|
|
|
// don't create a package-to-package relationship for this library... since we can't
|
|
continue
|
|
}
|
|
|
|
// create a package-to-package relationship between the binary package and the library package
|
|
// if there is more than one library for this given library name, then we will include
|
|
// all of them as dependencies since we don't know the LD_LIBRARY_PATH order
|
|
for _, pkgThatOwnsLib := range pkgsThatOwnLib.Sorted() {
|
|
relIndex.add(
|
|
artifact.Relationship{
|
|
From: pkgThatOwnsLib,
|
|
To: parentPkg,
|
|
Type: artifact.DependencyOfRelationship,
|
|
},
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
// so far this handles the first order dependencies from the binary package. Odds are that the OS package manager
|
|
// will have already created a package-to-package relationship for the lib packages to other lib packages.
|
|
|
|
return relIndex.newRelationships()
|
|
}
|