mirror of
https://github.com/anchore/syft.git
synced 2026-11-01 15:06:36 +01:00
Use package ID from decoded SBOMs when provided (#1872)
* fix: use package id from cyclonedx when provided Signed-off-by: James Neate <jamesmneate@gmail.com> * override package IDs from converted SBOMs Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix typo Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * remove extractSyftID function Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: James Neate <jamesmneate@gmail.com> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
co-authored by
Alex Goodman
parent
39396cfff9
commit
00c4a4e72a
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/CycloneDX/cyclonedx-go"
|
||||
|
||||
"github.com/anchore/packageurl-go"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
@@ -66,12 +65,16 @@ 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 component.BOMRef != "" {
|
||||
// always prefer the IDs from the SBOM over derived IDs
|
||||
p.OverrideID(artifact.ID(component.BOMRef))
|
||||
} else {
|
||||
p.SetID()
|
||||
}
|
||||
syftID := p.ID()
|
||||
if syftID != "" {
|
||||
idMap[syftID] = p
|
||||
idMap[string(syftID)] = p
|
||||
}
|
||||
// TODO there must be a better way than needing to call this manually:
|
||||
p.SetID()
|
||||
s.Artifacts.Packages.Add(*p)
|
||||
}
|
||||
|
||||
@@ -82,19 +85,6 @@ 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]
|
||||
|
||||
@@ -421,3 +421,39 @@ func Test_decodeDependencies(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_useBomRefOverDerivedSyftArtifactID(t *testing.T) {
|
||||
|
||||
packageWithId := cyclonedx.Component{
|
||||
BOMRef: "pkg:maven/org.springframework.boot/spring-boot-starter-test?package-id=646a5a71a4abeee0",
|
||||
Type: cyclonedx.ComponentTypeLibrary,
|
||||
Name: "spring-boot-starter-test",
|
||||
Version: "",
|
||||
PackageURL: "pkg:maven/org.springframework.boot/spring-boot-starter-test",
|
||||
}
|
||||
|
||||
packageWithoutId := cyclonedx.Component{
|
||||
BOMRef: "pkg:maven/org.springframework.boot/spring-boot-starter-webflux",
|
||||
Type: cyclonedx.ComponentTypeLibrary,
|
||||
Name: "spring-boot-starter-webflux",
|
||||
Version: "",
|
||||
PackageURL: "pkg:maven/org.springframework.boot/spring-boot-starter-webflux",
|
||||
}
|
||||
|
||||
bom := cyclonedx.BOM{Metadata: nil,
|
||||
Components: &[]cyclonedx.Component{
|
||||
packageWithId,
|
||||
packageWithoutId,
|
||||
}}
|
||||
|
||||
s, err := ToSyftModel(&bom)
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, s.Artifacts.Packages.Package("pkg:maven/org.springframework.boot/spring-boot-starter-test?package-id=646a5a71a4abeee0"))
|
||||
|
||||
pkgsWithoutID := s.Artifacts.Packages.PackagesByName(packageWithoutId.Name)
|
||||
|
||||
assert.Len(t, pkgsWithoutID, 1)
|
||||
assert.NotEqual(t, "", pkgsWithoutID[0].ID())
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ func (r RedactorFn) Redact(b []byte) []byte {
|
||||
|
||||
type PatternReplacement struct {
|
||||
Search *regexp.Regexp
|
||||
Groups []string
|
||||
Replace string
|
||||
}
|
||||
|
||||
@@ -39,7 +40,67 @@ func NewPatternReplacement(r *regexp.Regexp) PatternReplacement {
|
||||
}
|
||||
|
||||
func (p PatternReplacement) Redact(b []byte) []byte {
|
||||
return p.Search.ReplaceAll(b, []byte(p.Replace))
|
||||
if len(p.Groups) == 0 {
|
||||
return p.Search.ReplaceAll(b, []byte(p.Replace))
|
||||
}
|
||||
|
||||
return p.redactNamedGroups(b)
|
||||
}
|
||||
|
||||
func (p PatternReplacement) redactNamedGroups(b []byte) []byte {
|
||||
groupsToReplace := make(map[string]bool)
|
||||
for _, g := range p.Groups {
|
||||
groupsToReplace[g] = true
|
||||
}
|
||||
|
||||
subexpNames := p.Search.SubexpNames()
|
||||
|
||||
return p.Search.ReplaceAllFunc(b, func(match []byte) []byte {
|
||||
indexes := p.Search.FindSubmatchIndex(match)
|
||||
if indexes == nil {
|
||||
return match
|
||||
}
|
||||
|
||||
result := make([]byte, len(match))
|
||||
copy(result, match)
|
||||
|
||||
// keep track of the offset as we replace groups
|
||||
offset := 0
|
||||
|
||||
// process each named group
|
||||
for i, name := range subexpNames {
|
||||
// skip the full match (i==0) and groups we don't want to replace
|
||||
if i == 0 || !groupsToReplace[name] {
|
||||
continue
|
||||
}
|
||||
|
||||
// get the start and end positions of this group
|
||||
startPos := indexes[2*i]
|
||||
endPos := indexes[2*i+1]
|
||||
|
||||
// skip if the group didn't match
|
||||
if startPos < 0 || endPos < 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// adjust positions based on previous replacements
|
||||
startPos += offset
|
||||
endPos += offset
|
||||
|
||||
// replace the group with our replacement text
|
||||
beforeGroup := result[:startPos]
|
||||
afterGroup := result[endPos:]
|
||||
|
||||
// calculate the new offset
|
||||
oldLen := endPos - startPos
|
||||
newLen := len(p.Replace)
|
||||
offset += (newLen - oldLen)
|
||||
|
||||
result = append(beforeGroup, append([]byte(p.Replace), afterGroup...)...) //nolint:gocritic
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
// Replace by value //////////////////////////////
|
||||
@@ -86,6 +147,13 @@ func (r *Redactions) WithPatternRedactors(values map[string]string) *Redactions
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Redactions) WithPatternRedactorSpec(values ...PatternReplacement) *Redactions {
|
||||
for _, v := range values {
|
||||
r.redactors = append(r.redactors, v)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Redactions) WithValueRedactors(values map[string]string) *Redactions {
|
||||
for k, v := range values {
|
||||
r.redactors = append(r.redactors,
|
||||
|
||||
Reference in New Issue
Block a user