mirror of
https://github.com/anchore/syft.git
synced 2026-02-13 19:16:43 +01:00
Correct ID handling during Syft JSON decoding (#900)
This commit is contained in:
parent
4231f38fa2
commit
9240860f44
@ -129,6 +129,7 @@ func (p *Package) UnmarshalJSON(b []byte) error {
|
|||||||
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
p.Metadata = payload
|
||||||
default:
|
default:
|
||||||
log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID)
|
log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
func TestUnmarshalPackage(t *testing.T) {
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUnmarshalPackageGolang(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
p *Package
|
p *Package
|
||||||
packageData []byte
|
packageData []byte
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
name: "Package.UnmarshalJSON will unmarshal blank json",
|
|
||||||
p: &Package{},
|
|
||||||
packageData: []byte(`{}`),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "Package.UnmarshalJSON unmarshals PackageBasicData",
|
name: "Package.UnmarshalJSON unmarshals PackageBasicData",
|
||||||
p: &Package{},
|
p: &Package{},
|
||||||
@ -47,6 +47,11 @@ func TestUnmarshalPackage(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not unmarshal packageData: %v", err)
|
t.Fatalf("could not unmarshal packageData: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert.NotNil(t, test.p.Metadata)
|
||||||
|
golangMetadata := test.p.Metadata.(pkg.GolangBinMetadata)
|
||||||
|
assert.NotEmpty(t, golangMetadata)
|
||||||
|
assert.Equal(t, "go1.18", golangMetadata.GoCompiledVersion)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func toSyftModel(doc model.Document) (*sbom.SBOM, error) {
|
func toSyftModel(doc model.Document) (*sbom.SBOM, error) {
|
||||||
catalog := toSyftCatalog(doc.Artifacts)
|
idAliases := make(map[string]string)
|
||||||
|
|
||||||
|
catalog := toSyftCatalog(doc.Artifacts, idAliases)
|
||||||
|
|
||||||
return &sbom.SBOM{
|
return &sbom.SBOM{
|
||||||
Artifacts: sbom.Artifacts{
|
Artifacts: sbom.Artifacts{
|
||||||
@ -21,7 +23,7 @@ func toSyftModel(doc model.Document) (*sbom.SBOM, error) {
|
|||||||
},
|
},
|
||||||
Source: *toSyftSourceData(doc.Source),
|
Source: *toSyftSourceData(doc.Source),
|
||||||
Descriptor: toSyftDescriptor(doc.Descriptor),
|
Descriptor: toSyftDescriptor(doc.Descriptor),
|
||||||
Relationships: toSyftRelationships(&doc, catalog, doc.ArtifactRelationships),
|
Relationships: toSyftRelationships(&doc, catalog, doc.ArtifactRelationships, idAliases),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ func toSyftLinuxRelease(d model.LinuxRelease) *linux.Release {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSyftRelationships(doc *model.Document, catalog *pkg.Catalog, relationships []model.Relationship) []artifact.Relationship {
|
func toSyftRelationships(doc *model.Document, catalog *pkg.Catalog, relationships []model.Relationship, idAliases map[string]string) []artifact.Relationship {
|
||||||
idMap := make(map[string]interface{})
|
idMap := make(map[string]interface{})
|
||||||
|
|
||||||
for _, p := range catalog.Sorted() {
|
for _, p := range catalog.Sorted() {
|
||||||
@ -62,7 +64,7 @@ func toSyftRelationships(doc *model.Document, catalog *pkg.Catalog, relationship
|
|||||||
|
|
||||||
var out []artifact.Relationship
|
var out []artifact.Relationship
|
||||||
for _, r := range relationships {
|
for _, r := range relationships {
|
||||||
syftRelationship := toSyftRelationship(idMap, r)
|
syftRelationship := toSyftRelationship(idMap, r, idAliases)
|
||||||
if syftRelationship != nil {
|
if syftRelationship != nil {
|
||||||
out = append(out, *syftRelationship)
|
out = append(out, *syftRelationship)
|
||||||
}
|
}
|
||||||
@ -70,13 +72,20 @@ func toSyftRelationships(doc *model.Document, catalog *pkg.Catalog, relationship
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSyftRelationship(idMap map[string]interface{}, relationship model.Relationship) *artifact.Relationship {
|
func toSyftRelationship(idMap map[string]interface{}, relationship model.Relationship, idAliases map[string]string) *artifact.Relationship {
|
||||||
from, ok := idMap[relationship.Parent].(artifact.Identifiable)
|
id := func(id string) string {
|
||||||
|
aliased, ok := idAliases[id]
|
||||||
|
if ok {
|
||||||
|
return aliased
|
||||||
|
}
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
from, ok := idMap[id(relationship.Parent)].(artifact.Identifiable)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Warnf("relationship mapping from key %s is not a valid artifact.Identifiable type: %+v", relationship.Parent, idMap[relationship.Parent])
|
log.Warnf("relationship mapping from key %s is not a valid artifact.Identifiable type: %+v", relationship.Parent, idMap[relationship.Parent])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
to, ok := idMap[relationship.Child].(artifact.Identifiable)
|
to, ok := idMap[id(relationship.Child)].(artifact.Identifiable)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Warnf("relationship mapping to key %s is not a valid artifact.Identifiable type: %+v", relationship.Child, idMap[relationship.Child])
|
log.Warnf("relationship mapping to key %s is not a valid artifact.Identifiable type: %+v", relationship.Child, idMap[relationship.Child])
|
||||||
return nil
|
return nil
|
||||||
@ -128,15 +137,15 @@ func toSyftSourceData(s model.Source) *source.Metadata {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSyftCatalog(pkgs []model.Package) *pkg.Catalog {
|
func toSyftCatalog(pkgs []model.Package, idAliases map[string]string) *pkg.Catalog {
|
||||||
catalog := pkg.NewCatalog()
|
catalog := pkg.NewCatalog()
|
||||||
for _, p := range pkgs {
|
for _, p := range pkgs {
|
||||||
catalog.Add(toSyftPackage(p))
|
catalog.Add(toSyftPackage(p, idAliases))
|
||||||
}
|
}
|
||||||
return catalog
|
return catalog
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSyftPackage(p model.Package) pkg.Package {
|
func toSyftPackage(p model.Package, idAliases map[string]string) pkg.Package {
|
||||||
var cpes []pkg.CPE
|
var cpes []pkg.CPE
|
||||||
for _, c := range p.CPEs {
|
for _, c := range p.CPEs {
|
||||||
value, err := pkg.NewCPE(c)
|
value, err := pkg.NewCPE(c)
|
||||||
@ -153,7 +162,7 @@ func toSyftPackage(p model.Package) pkg.Package {
|
|||||||
locations[i] = source.NewLocationFromCoordinates(c)
|
locations[i] = source.NewLocationFromCoordinates(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkg.Package{
|
out := pkg.Package{
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
Version: p.Version,
|
Version: p.Version,
|
||||||
FoundBy: p.FoundBy,
|
FoundBy: p.FoundBy,
|
||||||
@ -166,4 +175,13 @@ func toSyftPackage(p model.Package) pkg.Package {
|
|||||||
MetadataType: p.MetadataType,
|
MetadataType: p.MetadataType,
|
||||||
Metadata: p.Metadata,
|
Metadata: p.Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.SetID()
|
||||||
|
|
||||||
|
id := string(out.ID())
|
||||||
|
if id != p.ID {
|
||||||
|
idAliases[p.ID] = id
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/anchore/syft/internal/formats/syftjson/model"
|
"github.com/anchore/syft/internal/formats/syftjson/model"
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -79,3 +80,46 @@ func Test_toSyftSourceData(t *testing.T) {
|
|||||||
// assert all possible schemes were under test
|
// assert all possible schemes were under test
|
||||||
assert.ElementsMatch(t, allSchemes.List(), testedSchemes.List(), "not all source.Schemes are under test")
|
assert.ElementsMatch(t, allSchemes.List(), testedSchemes.List(), "not all source.Schemes are under test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_idsHaveChanged(t *testing.T) {
|
||||||
|
s, err := toSyftModel(model.Document{
|
||||||
|
Source: model.Source{
|
||||||
|
Type: "file",
|
||||||
|
Target: "some/path",
|
||||||
|
},
|
||||||
|
Artifacts: []model.Package{
|
||||||
|
{
|
||||||
|
PackageBasicData: model.PackageBasicData{
|
||||||
|
ID: "1",
|
||||||
|
Name: "pkg-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PackageBasicData: model.PackageBasicData{
|
||||||
|
ID: "2",
|
||||||
|
Name: "pkg-2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ArtifactRelationships: []model.Relationship{
|
||||||
|
{
|
||||||
|
Parent: "1",
|
||||||
|
Child: "2",
|
||||||
|
Type: string(artifact.ContainsRelationship),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, s.Relationships, 1)
|
||||||
|
|
||||||
|
r := s.Relationships[0]
|
||||||
|
|
||||||
|
from := s.Artifacts.PackageCatalog.Package(r.From.ID())
|
||||||
|
assert.NotNil(t, from)
|
||||||
|
assert.Equal(t, "pkg-1", from.Name)
|
||||||
|
|
||||||
|
to := s.Artifacts.PackageCatalog.Package(r.To.ID())
|
||||||
|
assert.NotNil(t, to)
|
||||||
|
assert.Equal(t, "pkg-2", to.Name)
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user