mirror of
https://github.com/anchore/syft.git
synced 2026-11-04 08:26:38 +01:00
Add support for dependency relationships for alpine (apk) (#1063)
* Fix type of pull deps and add support for provides Signed-off-by: Dan Luhring <dan+github@luhrings.com> * [wip] apk dependency lookup Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * update whitespace for linter Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com> * adjust test conditions Signed-off-by: Timothy Gerla <tim@gerla.net> * fix TODOs and improve Provides parser * run simports after main merge Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com> * add tests to cover apk relationship parsing cases Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * generate JSON schema for breaking changes to apk metadata Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * update tests to account for additional dependencies Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * [wip] fix relationship encoding for cyclonedx Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * simplify package relationships that can be expressed Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Signed-off-by: Dan Luhring <dan+github@luhrings.com> Signed-off-by: Alex Goodman <alex.goodman@anchore.com> Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com> Signed-off-by: Timothy Gerla <tim@gerla.net> Co-authored-by: Alex Goodman <alex.goodman@anchore.com> Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com> Co-authored-by: Timothy Gerla <tim@gerla.net>
This commit is contained in:
co-authored by
Alex Goodman
Christopher Phillips
Timothy Gerla
parent
e58d0aecb8
commit
949cff158d
@@ -31,20 +31,21 @@ func Test_encodeComponentProperties(t *testing.T) {
|
||||
source.Location{Coordinates: source.Coordinates{RealPath: "test"}},
|
||||
),
|
||||
Metadata: pkg.ApkMetadata{
|
||||
Package: "libc-utils",
|
||||
OriginPackage: "libc-dev",
|
||||
Maintainer: "Natanael Copa <ncopa@alpinelinux.org>",
|
||||
Version: "0.7.2-r0",
|
||||
License: "BSD",
|
||||
Architecture: "x86_64",
|
||||
URL: "http://alpinelinux.org",
|
||||
Description: "Meta package to pull in correct libc",
|
||||
Size: 0,
|
||||
InstalledSize: 4096,
|
||||
PullDependencies: "musl-utils",
|
||||
PullChecksum: "Q1p78yvTLG094tHE1+dToJGbmYzQE=",
|
||||
GitCommitOfAport: "97b1c2842faa3bfa30f5811ffbf16d5ff9f1a479",
|
||||
Files: []pkg.ApkFileRecord{},
|
||||
Package: "libc-utils",
|
||||
OriginPackage: "libc-dev",
|
||||
Maintainer: "Natanael Copa <ncopa@alpinelinux.org>",
|
||||
Version: "0.7.2-r0",
|
||||
License: "BSD",
|
||||
Architecture: "x86_64",
|
||||
URL: "http://alpinelinux.org",
|
||||
Description: "Meta package to pull in correct libc",
|
||||
Size: 0,
|
||||
InstalledSize: 4096,
|
||||
Dependencies: []string{"musl-utils"},
|
||||
Provides: []string{"so:libc.so.1"},
|
||||
Checksum: "Q1p78yvTLG094tHE1+dToJGbmYzQE=",
|
||||
GitCommit: "97b1c2842faa3bfa30f5811ffbf16d5ff9f1a479",
|
||||
Files: []pkg.ApkFileRecord{},
|
||||
},
|
||||
},
|
||||
expected: &[]cyclonedx.Property{
|
||||
@@ -53,8 +54,9 @@ func Test_encodeComponentProperties(t *testing.T) {
|
||||
{Name: "syft:metadata:gitCommitOfApkPort", Value: "97b1c2842faa3bfa30f5811ffbf16d5ff9f1a479"},
|
||||
{Name: "syft:metadata:installedSize", Value: "4096"},
|
||||
{Name: "syft:metadata:originPackage", Value: "libc-dev"},
|
||||
{Name: "syft:metadata:provides:0", Value: "so:libc.so.1"},
|
||||
{Name: "syft:metadata:pullChecksum", Value: "Q1p78yvTLG094tHE1+dToJGbmYzQE="},
|
||||
{Name: "syft:metadata:pullDependencies", Value: "musl-utils"},
|
||||
{Name: "syft:metadata:pullDependencies:0", Value: "musl-utils"},
|
||||
{Name: "syft:metadata:size", Value: "0"},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/CycloneDX/cyclonedx-go"
|
||||
|
||||
"github.com/anchore/packageurl-go"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/formats/common"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
@@ -88,6 +89,10 @@ func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[str
|
||||
case cyclonedx.ComponentTypeApplication, cyclonedx.ComponentTypeFramework, cyclonedx.ComponentTypeLibrary:
|
||||
p := decodeComponent(component)
|
||||
idMap[component.BOMRef] = p
|
||||
syftID := extractSyftPacakgeID(component.BOMRef)
|
||||
if syftID != "" {
|
||||
idMap[syftID] = p
|
||||
}
|
||||
// TODO there must be a better way than needing to call this manually:
|
||||
p.SetID()
|
||||
s.Artifacts.PackageCatalog.Add(*p)
|
||||
@@ -100,6 +105,19 @@ func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[str
|
||||
}
|
||||
}
|
||||
|
||||
func extractSyftPacakgeID(i string) string {
|
||||
instance, err := packageurl.FromString(i)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, q := range instance.Qualifiers {
|
||||
if q.Key == "package-id" {
|
||||
return q.Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func linuxReleaseFromComponents(components []cyclonedx.Component) *linux.Release {
|
||||
for i := range components {
|
||||
component := &components[i]
|
||||
@@ -188,21 +206,25 @@ func collectRelationships(bom *cyclonedx.BOM, s *sbom.SBOM, idMap map[string]int
|
||||
return
|
||||
}
|
||||
for _, d := range *bom.Dependencies {
|
||||
from, fromOk := idMap[d.Ref].(artifact.Identifiable)
|
||||
if fromOk {
|
||||
if d.Dependencies == nil {
|
||||
from, fromExists := idMap[d.Ref].(artifact.Identifiable)
|
||||
if !fromExists {
|
||||
continue
|
||||
}
|
||||
|
||||
if d.Dependencies == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, t := range *d.Dependencies {
|
||||
to, toExists := idMap[t.Ref].(artifact.Identifiable)
|
||||
if !toExists {
|
||||
continue
|
||||
}
|
||||
for _, t := range *d.Dependencies {
|
||||
to, toOk := idMap[t.Ref].(artifact.Identifiable)
|
||||
if toOk {
|
||||
s.Relationships = append(s.Relationships, artifact.Relationship{
|
||||
From: from,
|
||||
To: to,
|
||||
Type: artifact.DependencyOfRelationship, // FIXME this information is lost
|
||||
})
|
||||
}
|
||||
}
|
||||
s.Relationships = append(s.Relationships, artifact.Relationship{
|
||||
From: from,
|
||||
To: to,
|
||||
Type: artifact.DependencyOfRelationship, // FIXME this information is lost
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
@@ -120,16 +121,11 @@ func toBomDescriptor(name, version string, srcMetadata source.Metadata) *cyclone
|
||||
// An example of a relationship to not include would be: OwnershipByFileOverlapRelationship.
|
||||
func isExpressiblePackageRelationship(ty artifact.RelationshipType) bool {
|
||||
switch ty {
|
||||
case artifact.RuntimeDependencyOfRelationship:
|
||||
return true
|
||||
case artifact.DevDependencyOfRelationship:
|
||||
return true
|
||||
case artifact.BuildDependencyOfRelationship:
|
||||
return true
|
||||
case artifact.DependencyOfRelationship:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func toDependencies(relationships []artifact.Relationship) []cyclonedx.Dependency {
|
||||
@@ -141,10 +137,21 @@ func toDependencies(relationships []artifact.Relationship) []cyclonedx.Dependenc
|
||||
continue
|
||||
}
|
||||
|
||||
// we only capture package-to-package relationships for now
|
||||
fromPkg, ok := r.From.(*pkg.Package)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
toPkg, ok := r.To.(*pkg.Package)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
innerDeps := []cyclonedx.Dependency{}
|
||||
innerDeps = append(innerDeps, cyclonedx.Dependency{Ref: string(r.From.ID())})
|
||||
innerDeps = append(innerDeps, cyclonedx.Dependency{Ref: deriveBomRef(*fromPkg)})
|
||||
result = append(result, cyclonedx.Dependency{
|
||||
Ref: string(r.To.ID()),
|
||||
Ref: deriveBomRef(*toPkg),
|
||||
Dependencies: &innerDeps,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user