From 13046515a0a81d5b0c320acb41f633c4f883b026 Mon Sep 17 00:00:00 2001 From: m-brophy Date: Mon, 2 Oct 2023 12:13:47 +0100 Subject: [PATCH 1/5] process `PACKAGE_OF` relationship in SPDX files Signed-off-by: m-brophy --- .../testing/testdata/exampledata/alpine-small-spdx.json | 8 +++++++- .../testing/testdata/exampledata/ingest_predicates.json | 2 +- internal/testing/testdata/testdata.go | 4 ++-- pkg/ingestor/parser/spdx/parse_spdx.go | 9 +++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/internal/testing/testdata/exampledata/alpine-small-spdx.json b/internal/testing/testdata/exampledata/alpine-small-spdx.json index fe5bdbca9d..c669bdeebe 100644 --- a/internal/testing/testdata/exampledata/alpine-small-spdx.json +++ b/internal/testing/testdata/exampledata/alpine-small-spdx.json @@ -155,7 +155,8 @@ "SPDXRef-f542a07f45615070", "SPDXRef-f91e100c74bf27e", "SPDXRef-f96f56f789a464ad", - "SPDXRef-fb57f5df1fd169db" + "SPDXRef-fb57f5df1fd169db", + "SPDXRef-d3f01bc78ba82ed5" ], "licenseDeclared": "MIT", "originator": "Person: Natanael Copa ", @@ -628,6 +629,11 @@ "spdxElementId": "SPDXRef-ec1d619a28263eb0", "relationshipType": "CONTAINS", "relatedSpdxElement": "SPDXRef-e2c90ae8ae67431f" + }, + { + "spdxElementId": "SPDXRef-ec1d619a28263eb0", + "relationshipType": "PACKAGE_OF", + "relatedSpdxElement": "SPDXRef-d3f01bc78ba82ed5" } ] } diff --git a/internal/testing/testdata/exampledata/ingest_predicates.json b/internal/testing/testdata/exampledata/ingest_predicates.json index c0aa62b052..b909848671 100644 --- a/internal/testing/testdata/exampledata/ingest_predicates.json +++ b/internal/testing/testdata/exampledata/ingest_predicates.json @@ -646,7 +646,7 @@ "hasSbom": { "uri": "TestSource", "algorithm": "sha256", - "digest": "8b5e8212cae084f92ff91f8625a50ea1070738cfc68ecca08bf04d64f64b9feb", + "digest": "cc141f24bef6367cd21c3501864b1411c428d34b5b10cce2214d3a2107df97c3", "downloadLocation": "TestSource", "origin": "", "collector": "" diff --git a/internal/testing/testdata/testdata.go b/internal/testing/testdata/testdata.go index 5fa26fd871..abb913c65f 100644 --- a/internal/testing/testdata/testdata.go +++ b/internal/testing/testdata/testdata.go @@ -726,7 +726,7 @@ var ( HasSBOM: &model.HasSBOMInputSpec{ Uri: "TestSource", Algorithm: "sha256", - Digest: "8b5e8212cae084f92ff91f8625a50ea1070738cfc68ecca08bf04d64f64b9feb", + Digest: "cc141f24bef6367cd21c3501864b1411c428d34b5b10cce2214d3a2107df97c3", DownloadLocation: "TestSource", KnownSince: spdxTime, }, @@ -2478,7 +2478,7 @@ For the update to take effect, all services linked to the OpenSSL library must b HasSBOM: &generated.HasSBOMInputSpec{ Uri: "TestSource", Algorithm: "sha256", - Digest: "8b5e8212cae084f92ff91f8625a50ea1070738cfc68ecca08bf04d64f64b9feb", + Digest: "cc141f24bef6367cd21c3501864b1411c428d34b5b10cce2214d3a2107df97c3", DownloadLocation: "TestSource", }, }, diff --git a/pkg/ingestor/parser/spdx/parse_spdx.go b/pkg/ingestor/parser/spdx/parse_spdx.go index bbe28c8533..2fcfdd68d4 100644 --- a/pkg/ingestor/parser/spdx/parse_spdx.go +++ b/pkg/ingestor/parser/spdx/parse_spdx.go @@ -268,6 +268,9 @@ func (s *spdxParser) GetPredicates(ctx context.Context) *assembler.IngestPredica } else if isDependent(rel.Relationship) { foundId = string(rel.RefB.ElementRefID) relatedId = string(rel.RefA.ElementRefID) + } else if isPackageOf(rel.Relationship) { + foundId = string(rel.RefB.ElementRefID) + relatedId = string(rel.RefA.ElementRefID) } else { continue } @@ -426,6 +429,12 @@ func isDependent(rel string) bool { }[rel] } +func isPackageOf(rel string) bool { + return map[string]bool{ + spdx_common.TypeRelationshipPackageOf: true, + }[rel] +} + func (s *spdxParser) GetIdentities(ctx context.Context) []common.TrustInformation { return nil } From 3d704a37209385d25fde46edb695962ee56e8040 Mon Sep 17 00:00:00 2001 From: m-brophy Date: Mon, 2 Oct 2023 12:56:32 +0100 Subject: [PATCH 2/5] formatting changes Signed-off-by: m-brophy --- pkg/ingestor/parser/spdx/parse_spdx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ingestor/parser/spdx/parse_spdx.go b/pkg/ingestor/parser/spdx/parse_spdx.go index 2fcfdd68d4..c61e99ccef 100644 --- a/pkg/ingestor/parser/spdx/parse_spdx.go +++ b/pkg/ingestor/parser/spdx/parse_spdx.go @@ -431,7 +431,7 @@ func isDependent(rel string) bool { func isPackageOf(rel string) bool { return map[string]bool{ - spdx_common.TypeRelationshipPackageOf: true, + spdx_common.TypeRelationshipPackageOf: true, }[rel] } From ae0aa2815b29e4164ff872b46afeab07c5969bce Mon Sep 17 00:00:00 2001 From: m-brophy Date: Mon, 2 Oct 2023 12:13:47 +0100 Subject: [PATCH 3/5] process `PACKAGE_OF` relationship in SPDX files Signed-off-by: m-brophy --- pkg/ingestor/parser/spdx/parse_spdx.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/ingestor/parser/spdx/parse_spdx.go b/pkg/ingestor/parser/spdx/parse_spdx.go index c61e99ccef..ee7276b03f 100644 --- a/pkg/ingestor/parser/spdx/parse_spdx.go +++ b/pkg/ingestor/parser/spdx/parse_spdx.go @@ -265,10 +265,7 @@ func (s *spdxParser) GetPredicates(ctx context.Context) *assembler.IngestPredica if isDependency(rel.Relationship) { foundId = string(rel.RefA.ElementRefID) relatedId = string(rel.RefB.ElementRefID) - } else if isDependent(rel.Relationship) { - foundId = string(rel.RefB.ElementRefID) - relatedId = string(rel.RefA.ElementRefID) - } else if isPackageOf(rel.Relationship) { + } else if isDependent(rel.Relationship) || isPackageOf(rel.Relationship) { foundId = string(rel.RefB.ElementRefID) relatedId = string(rel.RefA.ElementRefID) } else { @@ -431,7 +428,7 @@ func isDependent(rel string) bool { func isPackageOf(rel string) bool { return map[string]bool{ - spdx_common.TypeRelationshipPackageOf: true, + spdx_common.TypeRelationshipPackageOf: true, }[rel] } From b20a6e3ebff5b9ff5dd15a879228ab9dfac5fd6b Mon Sep 17 00:00:00 2001 From: m-brophy Date: Mon, 2 Oct 2023 12:56:32 +0100 Subject: [PATCH 4/5] formatting changes Signed-off-by: m-brophy --- pkg/ingestor/parser/spdx/parse_spdx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ingestor/parser/spdx/parse_spdx.go b/pkg/ingestor/parser/spdx/parse_spdx.go index ee7276b03f..1011b6743b 100644 --- a/pkg/ingestor/parser/spdx/parse_spdx.go +++ b/pkg/ingestor/parser/spdx/parse_spdx.go @@ -428,7 +428,7 @@ func isDependent(rel string) bool { func isPackageOf(rel string) bool { return map[string]bool{ - spdx_common.TypeRelationshipPackageOf: true, + spdx_common.TypeRelationshipPackageOf: true, }[rel] } From 31a123d0877f445b813366bdb3975023eed96381 Mon Sep 17 00:00:00 2001 From: m-brophy Date: Fri, 6 Oct 2023 14:31:37 +0100 Subject: [PATCH 5/5] add new test for PACKAGE_OF relationship ingestion Signed-off-by: m-brophy --- .../exampledata/alpine-small-spdx.json | 8 +- .../exampledata/ingest_predicates.json | 2 +- internal/testing/testdata/testdata.go | 4 +- pkg/ingestor/parser/spdx/parse_spdx_test.go | 93 +++++++++++++++++++ 4 files changed, 97 insertions(+), 10 deletions(-) diff --git a/internal/testing/testdata/exampledata/alpine-small-spdx.json b/internal/testing/testdata/exampledata/alpine-small-spdx.json index c669bdeebe..fe5bdbca9d 100644 --- a/internal/testing/testdata/exampledata/alpine-small-spdx.json +++ b/internal/testing/testdata/exampledata/alpine-small-spdx.json @@ -155,8 +155,7 @@ "SPDXRef-f542a07f45615070", "SPDXRef-f91e100c74bf27e", "SPDXRef-f96f56f789a464ad", - "SPDXRef-fb57f5df1fd169db", - "SPDXRef-d3f01bc78ba82ed5" + "SPDXRef-fb57f5df1fd169db" ], "licenseDeclared": "MIT", "originator": "Person: Natanael Copa ", @@ -629,11 +628,6 @@ "spdxElementId": "SPDXRef-ec1d619a28263eb0", "relationshipType": "CONTAINS", "relatedSpdxElement": "SPDXRef-e2c90ae8ae67431f" - }, - { - "spdxElementId": "SPDXRef-ec1d619a28263eb0", - "relationshipType": "PACKAGE_OF", - "relatedSpdxElement": "SPDXRef-d3f01bc78ba82ed5" } ] } diff --git a/internal/testing/testdata/exampledata/ingest_predicates.json b/internal/testing/testdata/exampledata/ingest_predicates.json index b909848671..c0aa62b052 100644 --- a/internal/testing/testdata/exampledata/ingest_predicates.json +++ b/internal/testing/testdata/exampledata/ingest_predicates.json @@ -646,7 +646,7 @@ "hasSbom": { "uri": "TestSource", "algorithm": "sha256", - "digest": "cc141f24bef6367cd21c3501864b1411c428d34b5b10cce2214d3a2107df97c3", + "digest": "8b5e8212cae084f92ff91f8625a50ea1070738cfc68ecca08bf04d64f64b9feb", "downloadLocation": "TestSource", "origin": "", "collector": "" diff --git a/internal/testing/testdata/testdata.go b/internal/testing/testdata/testdata.go index abb913c65f..5fa26fd871 100644 --- a/internal/testing/testdata/testdata.go +++ b/internal/testing/testdata/testdata.go @@ -726,7 +726,7 @@ var ( HasSBOM: &model.HasSBOMInputSpec{ Uri: "TestSource", Algorithm: "sha256", - Digest: "cc141f24bef6367cd21c3501864b1411c428d34b5b10cce2214d3a2107df97c3", + Digest: "8b5e8212cae084f92ff91f8625a50ea1070738cfc68ecca08bf04d64f64b9feb", DownloadLocation: "TestSource", KnownSince: spdxTime, }, @@ -2478,7 +2478,7 @@ For the update to take effect, all services linked to the OpenSSL library must b HasSBOM: &generated.HasSBOMInputSpec{ Uri: "TestSource", Algorithm: "sha256", - Digest: "cc141f24bef6367cd21c3501864b1411c428d34b5b10cce2214d3a2107df97c3", + Digest: "8b5e8212cae084f92ff91f8625a50ea1070738cfc68ecca08bf04d64f64b9feb", DownloadLocation: "TestSource", }, }, diff --git a/pkg/ingestor/parser/spdx/parse_spdx_test.go b/pkg/ingestor/parser/spdx/parse_spdx_test.go index b726f67c22..6e4db86a72 100644 --- a/pkg/ingestor/parser/spdx/parse_spdx_test.go +++ b/pkg/ingestor/parser/spdx/parse_spdx_test.go @@ -37,6 +37,10 @@ func pUrlToPkgDiscardError(pUrl string) *generated.PkgInputSpec { } func Test_spdxParser(t *testing.T) { + packageOfns := "spdx" + //packageOfVersion := "sha256:a743268cd3c56f921f3fb706c" + depPackageOfVersion := "sha256:a743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10" + packageOfEmptyString := "" ctx := logging.WithLogger(context.Background()) tests := []struct { name string @@ -63,6 +67,95 @@ func Test_spdxParser(t *testing.T) { wantPredicates: &testdata.SpdxIngestionPredicates, wantErr: false, }, + { + name: "SPDX with PACKAGE_OF relationship populates pUrl from described element", + additionalOpts: []cmp.Option{ + cmpopts.IgnoreFields(assembler.HasSBOMIngest{}, + "HasSBOM"), + }, + doc: &processor.Document{ + Blob: []byte(` + { + "spdxVersion": "SPDX-2.3", + "SPDXID":"SPDXRef-DOCUMENT", + "name":"sbom-sha256:a743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10", + "creationInfo": { "created": "2023-01-01T01:01:01.00Z" }, + "packages":[ + { + "SPDXID":"SPDXRef-Package-sha256-a743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10", + "name":"sha256:a743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10", + "externalRefs":[ + { + "referenceCategory":"PACKAGE_MANAGER", + "referenceLocator":"pkg:oci/image@sha256:a743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10?mediaType=application%2Fvnd.oci.image.manifest.v1%2Bjson", + "referenceType":"purl" + } + ] + } + ], + "relationships":[ + { + "spdxElementId":"SPDXRef-DOCUMENT", + "relationshipType":"PACKAGE_OF", + "relatedSpdxElement":"SPDXRef-Package-sha256-a743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10" + } + ] + } + `), + Format: processor.FormatJSON, + Type: processor.DocumentSPDX, + SourceInformation: processor.SourceInformation{ + Collector: "TestCollector", + Source: "TestSource", + }, + }, + wantPredicates: &assembler.IngestPredicates{ + IsDependency: []assembler.IsDependencyIngest{ + { + Pkg: &generated.PkgInputSpec{ + Type: "guac", + Namespace: &packageOfns, + Name: "sbom-sha256%3Aa743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10", + Version: &packageOfEmptyString, + Subpath: &packageOfEmptyString, + }, + DepPkg: &generated.PkgInputSpec{ + Type: "oci", + Namespace: &packageOfEmptyString, + Name: "image", + Version: &depPackageOfVersion, + Qualifiers: []generated.PackageQualifierInputSpec{{Key: "mediatype", Value: "application/vnd.oci.image.manifest.v1+json"}}, + Subpath: &packageOfEmptyString, + }, + DepPkgMatchFlag: generated.MatchFlags{Pkg: "SPECIFIC_VERSION"}, + IsDependency: &generated.IsDependencyInputSpec{ + VersionRange: "sha256:a743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10", + DependencyType: "UNKNOWN", + Justification: "top-level package GUAC heuristic connecting to each file/package", + }, + }, + }, + + HasSBOM: []assembler.HasSBOMIngest{ + { + Pkg: &generated.PkgInputSpec{ + Type: "guac", + Namespace: &packageOfns, + Name: "sbom-sha256%3Aa743268cd3c56f921f3fb706cc0425c8ab78119fd433e38bb7c5dcd5635b0d10", + Version: &packageOfEmptyString, + Subpath: &packageOfEmptyString, + }, + HasSBOM: &generated.HasSBOMInputSpec{ + Uri: "TestSource", + Algorithm: "sha256", + Digest: "ba096464061993bbbdfc30a26b42cd8beb1bfff301726fe6c58cb45d468c7648", + DownloadLocation: "TestSource", + }, + }, + }, + }, + wantErr: false, + }, { name: "SPDX with DESCRIBES relationship populates pUrl from described element", additionalOpts: []cmp.Option{