From 098e61dcc81d7a6d666bc62a2166c9b8f32c61bc Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Mon, 21 Nov 2022 09:26:24 -0500 Subject: [PATCH] fix: sort relationships in SPDX output (#1350) --- .../common/spdxhelpers/to_format_model.go | 2 +- syft/formats/common/testutils/utils.go | 25 ++++++ syft/formats/spdxjson/encoder_test.go | 22 +---- .../TestSPDXJSONDirectoryEncoder.golden | 4 +- .../snapshot/TestSPDXJSONImageEncoder.golden | 4 +- .../snapshot/TestSPDXRelationshipOrder.golden | 12 +-- syft/formats/spdxtagvalue/encoder_test.go | 13 +++ .../snapshot/TestSPDXJSONSPDXIDs.golden | 4 +- .../snapshot/TestSPDXRelationshipOrder.golden | 79 ++++++++++++++++++ .../TestSPDXTagValueDirectoryEncoder.golden | 4 +- .../TestSPDXTagValueImageEncoder.golden | 4 +- .../stereoscope-fixture-image-simple.golden | Bin 15360 -> 15360 bytes 12 files changed, 135 insertions(+), 38 deletions(-) create mode 100644 syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden diff --git a/syft/formats/common/spdxhelpers/to_format_model.go b/syft/formats/common/spdxhelpers/to_format_model.go index b62c1be0d..be2c1018d 100644 --- a/syft/formats/common/spdxhelpers/to_format_model.go +++ b/syft/formats/common/spdxhelpers/to_format_model.go @@ -105,7 +105,7 @@ func ToFormatModel(s sbom.SBOM) *spdx.Document { }, Packages: toPackages(s.Artifacts.PackageCatalog), Files: toFiles(s), - Relationships: toRelationships(s.Relationships), + Relationships: toRelationships(s.RelationshipsSorted()), } } diff --git a/syft/formats/common/testutils/utils.go b/syft/formats/common/testutils/utils.go index 5276c46e5..f672a139e 100644 --- a/syft/formats/common/testutils/utils.go +++ b/syft/formats/common/testutils/utils.go @@ -2,8 +2,10 @@ package testutils import ( "bytes" + "math/rand" "strings" "testing" + "time" "github.com/sergi/go-diff/diffmatchpatch" "github.com/stretchr/testify/assert" @@ -12,6 +14,7 @@ import ( "github.com/anchore/stereoscope/pkg/filetree" "github.com/anchore/stereoscope/pkg/image" "github.com/anchore/stereoscope/pkg/imagetest" + "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/linux" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/sbom" @@ -276,3 +279,25 @@ func newDirectoryCatalog() *pkg.Catalog { return catalog } + +//nolint:gosec +func AddSampleFileRelationships(s *sbom.SBOM) { + catalog := s.Artifacts.PackageCatalog.Sorted() + s.Artifacts.FileMetadata = map[source.Coordinates]source.FileMetadata{} + + files := []string{"/f1", "/f2", "/d1/f3", "/d2/f4", "/z1/f5", "/a1/f6"} + rnd := rand.New(rand.NewSource(time.Now().UnixNano())) + rnd.Shuffle(len(files), func(i, j int) { files[i], files[j] = files[j], files[i] }) + + for _, f := range files { + meta := source.FileMetadata{} + coords := source.Coordinates{RealPath: f} + s.Artifacts.FileMetadata[coords] = meta + + s.Relationships = append(s.Relationships, artifact.Relationship{ + From: catalog[0], + To: coords, + Type: artifact.ContainsRelationship, + }) + } +} diff --git a/syft/formats/spdxjson/encoder_test.go b/syft/formats/spdxjson/encoder_test.go index 545013613..39fa6e3f9 100644 --- a/syft/formats/spdxjson/encoder_test.go +++ b/syft/formats/spdxjson/encoder_test.go @@ -5,10 +5,7 @@ import ( "regexp" "testing" - "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/formats/common/testutils" - "github.com/anchore/syft/syft/sbom" - "github.com/anchore/syft/syft/source" ) var updateSpdxJson = flag.Bool("update-spdx-json", false, "update the *.golden files for spdx-json encoders") @@ -36,7 +33,7 @@ func TestSPDXJSONImageEncoder(t *testing.T) { func TestSPDXRelationshipOrder(t *testing.T) { testImage := "image-simple" s := testutils.ImageInput(t, testImage, testutils.FromSnapshot()) - addRelationships(&s) + testutils.AddSampleFileRelationships(&s) testutils.AssertEncoderAgainstGoldenImageSnapshot(t, Format(), s, @@ -46,23 +43,6 @@ func TestSPDXRelationshipOrder(t *testing.T) { ) } -func addRelationships(s *sbom.SBOM) { - catalog := s.Artifacts.PackageCatalog.Sorted() - s.Artifacts.FileMetadata = map[source.Coordinates]source.FileMetadata{} - - for _, f := range []string{"/f1", "/f2", "/d1/f3", "/d2/f4", "/z1/f5", "/a1/f6"} { - meta := source.FileMetadata{} - coords := source.Coordinates{RealPath: f} - s.Artifacts.FileMetadata[coords] = meta - - s.Relationships = append(s.Relationships, artifact.Relationship{ - From: catalog[0], - To: coords, - Type: artifact.ContainsRelationship, - }) - } -} - func spdxJsonRedactor(s []byte) []byte { // each SBOM reports the time it was generated, which is not useful during snapshot testing s = regexp.MustCompile(`"created": .*`).ReplaceAll(s, []byte("redacted")) diff --git a/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden b/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden index c444dee2a..bbe863815 100644 --- a/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden +++ b/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONDirectoryEncoder.golden @@ -3,14 +3,14 @@ "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", "name": "/some/path", - "documentNamespace": "https://anchore.com/syft/dir/some/path-0f9b165e-1819-43cb-bd58-f61c1c23d6cf", + "documentNamespace": "https://anchore.com/syft/dir/some/path-4bf54cdd-0a0f-4560-bf4f-39cac2ef7a5b", "creationInfo": { "licenseListVersion": "3.18", "creators": [ "Organization: Anchore, Inc", "Tool: syft-v0.42.0-bogus" ], - "created": "2022-11-11T19:24:55Z", + "created": "2022-11-19T13:46:57Z", "comment": "" }, "packages": [ diff --git a/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden b/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden index 9d052f8ec..5462bcdf1 100644 --- a/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden +++ b/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXJSONImageEncoder.golden @@ -3,14 +3,14 @@ "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", "name": "user-image-input", - "documentNamespace": "https://anchore.com/syft/image/user-image-input-5841d063-c3ef-406b-91b4-8a702ef45ce9", + "documentNamespace": "https://anchore.com/syft/image/user-image-input-102ca7dc-3d1e-46d2-b130-28968831ebcc", "creationInfo": { "licenseListVersion": "3.18", "creators": [ "Organization: Anchore, Inc", "Tool: syft-v0.42.0-bogus" ], - "created": "2022-11-11T19:24:55Z", + "created": "2022-11-19T13:46:57Z", "comment": "" }, "packages": [ diff --git a/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden b/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden index 93c474cad..c66e4989e 100644 --- a/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden +++ b/syft/formats/spdxjson/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden @@ -3,14 +3,14 @@ "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", "name": "user-image-input", - "documentNamespace": "https://anchore.com/syft/image/user-image-input-8755f340-f205-4bf2-a909-94c623670734", + "documentNamespace": "https://anchore.com/syft/image/user-image-input-55ad4afc-ecdc-46a4-8bc3-36b3e72da5d1", "creationInfo": { "licenseListVersion": "3.18", "creators": [ "Organization: Anchore, Inc", "Tool: syft-v0.42.0-bogus" ], - "created": "2022-11-11T19:24:55Z", + "created": "2022-11-19T13:46:57Z", "comment": "" }, "packages": [ @@ -133,12 +133,12 @@ }, { "spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6", - "relatedSpdxElement": "SPDXRef-f9e49132a4b96ccd", + "relatedSpdxElement": "SPDXRef-839d99ee67d9d174", "relationshipType": "CONTAINS" }, { "spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6", - "relatedSpdxElement": "SPDXRef-c6f5b29dca12661f", + "relatedSpdxElement": "SPDXRef-9c2f7510199b17f6", "relationshipType": "CONTAINS" }, { @@ -148,12 +148,12 @@ }, { "spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6", - "relatedSpdxElement": "SPDXRef-839d99ee67d9d174", + "relatedSpdxElement": "SPDXRef-c6f5b29dca12661f", "relationshipType": "CONTAINS" }, { "spdxElementId": "SPDXRef-Package-python-package-1-66ba429119b8bec6", - "relatedSpdxElement": "SPDXRef-9c2f7510199b17f6", + "relatedSpdxElement": "SPDXRef-f9e49132a4b96ccd", "relationshipType": "CONTAINS" } ] diff --git a/syft/formats/spdxtagvalue/encoder_test.go b/syft/formats/spdxtagvalue/encoder_test.go index 55f001207..b5ca75f12 100644 --- a/syft/formats/spdxtagvalue/encoder_test.go +++ b/syft/formats/spdxtagvalue/encoder_test.go @@ -67,6 +67,19 @@ func TestSPDXJSONSPDXIDs(t *testing.T) { ) } +func TestSPDXRelationshipOrder(t *testing.T) { + testImage := "image-simple" + s := testutils.ImageInput(t, testImage, testutils.FromSnapshot()) + testutils.AddSampleFileRelationships(&s) + testutils.AssertEncoderAgainstGoldenImageSnapshot(t, + Format(), + s, + testImage, + *updateSpdxTagValue, + spdxTagValueRedactor, + ) +} + func spdxTagValueRedactor(s []byte) []byte { // each SBOM reports the time it was generated, which is not useful during snapshot testing s = regexp.MustCompile(`Created: .*`).ReplaceAll(s, []byte("redacted")) diff --git a/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden index 8acb135b9..988de2374 100644 --- a/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden +++ b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXJSONSPDXIDs.golden @@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: foobar/baz -DocumentNamespace: https://anchore.com/syft/dir/foobar/baz-3d730196-4510-4ee4-9743-9322dd27cee7 +DocumentNamespace: https://anchore.com/syft/dir/foobar/baz-62bc0aae-2b37-4c86-ab79-63c6fc4198ed LicenseListVersion: 3.18 Creator: Organization: Anchore, Inc Creator: Tool: syft-v0.42.0-bogus -Created: 2022-11-18T14:21:45Z +Created: 2022-11-19T13:48:30Z ##### Package: @at-sign diff --git a/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden new file mode 100644 index 000000000..d87fee378 --- /dev/null +++ b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXRelationshipOrder.golden @@ -0,0 +1,79 @@ +SPDXVersion: SPDX-2.3 +DataLicense: CC0-1.0 +SPDXID: SPDXRef-DOCUMENT +DocumentName: user-image-input +DocumentNamespace: https://anchore.com/syft/image/user-image-input-cc20e416-9c74-401c-b4aa-245556bada5e +LicenseListVersion: 3.18 +Creator: Organization: Anchore, Inc +Creator: Tool: syft-v0.42.0-bogus +Created: 2022-11-19T13:48:30Z + +##### Unpackaged files + +FileName: /f1 +SPDXID: SPDXRef-5265a4dde3edbf7c +FileType: OTHER +LicenseConcluded: NOASSERTION + +FileName: /z1/f5 +SPDXID: SPDXRef-839d99ee67d9d174 +FileType: OTHER +LicenseConcluded: NOASSERTION + +FileName: /a1/f6 +SPDXID: SPDXRef-9c2f7510199b17f6 +FileType: OTHER +LicenseConcluded: NOASSERTION + +FileName: /d2/f4 +SPDXID: SPDXRef-c641caa71518099f +FileType: OTHER +LicenseConcluded: NOASSERTION + +FileName: /d1/f3 +SPDXID: SPDXRef-c6f5b29dca12661f +FileType: OTHER +LicenseConcluded: NOASSERTION + +FileName: /f2 +SPDXID: SPDXRef-f9e49132a4b96ccd +FileType: OTHER +LicenseConcluded: NOASSERTION + +##### Package: package-2 + +PackageName: package-2 +SPDXID: SPDXRef-Package-deb-package-2-958443e2d9304af4 +PackageVersion: 2.0.1 +PackageDownloadLocation: NOASSERTION +FilesAnalyzed: false +PackageSourceInfo: acquired package info from DPKG DB: /somefile-2.txt +PackageLicenseConcluded: NONE +PackageLicenseDeclared: NONE +PackageCopyrightText: NOASSERTION +ExternalRef: SECURITY cpe23Type cpe:2.3:*:some:package:2:*:*:*:*:*:*:* +ExternalRef: PACKAGE-MANAGER purl pkg:deb/debian/package-2@2.0.1 + +##### Package: package-1 + +PackageName: package-1 +SPDXID: SPDXRef-Package-python-package-1-66ba429119b8bec6 +PackageVersion: 1.0.1 +PackageDownloadLocation: NOASSERTION +FilesAnalyzed: false +PackageSourceInfo: acquired package info from installed python package manifest file: /somefile-1.txt +PackageLicenseConcluded: MIT +PackageLicenseDeclared: MIT +PackageCopyrightText: NOASSERTION +ExternalRef: SECURITY cpe23Type cpe:2.3:*:some:package:1:*:*:*:*:*:*:* +ExternalRef: PACKAGE-MANAGER purl a-purl-1 + +##### Relationships + +Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-5265a4dde3edbf7c +Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-839d99ee67d9d174 +Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-9c2f7510199b17f6 +Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-c641caa71518099f +Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-c6f5b29dca12661f +Relationship: SPDXRef-Package-python-package-1-66ba429119b8bec6 CONTAINS SPDXRef-f9e49132a4b96ccd + diff --git a/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden index a450e0191..119e225ef 100644 --- a/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden +++ b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueDirectoryEncoder.golden @@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: /some/path -DocumentNamespace: https://anchore.com/syft/dir/some/path-b6078c95-5b97-462d-acb3-9e74bc9ddb43 +DocumentNamespace: https://anchore.com/syft/dir/some/path-7a4b2140-6669-4a28-80dd-5c8e795c5da0 LicenseListVersion: 3.18 Creator: Organization: Anchore, Inc Creator: Tool: syft-v0.42.0-bogus -Created: 2022-11-18T14:21:44Z +Created: 2022-11-19T13:48:30Z ##### Package: package-2 diff --git a/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden index 4d6a523d5..3d62f6ccc 100644 --- a/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden +++ b/syft/formats/spdxtagvalue/test-fixtures/snapshot/TestSPDXTagValueImageEncoder.golden @@ -2,11 +2,11 @@ SPDXVersion: SPDX-2.3 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: user-image-input -DocumentNamespace: https://anchore.com/syft/image/user-image-input-aa272d1e-8bb4-411f-a554-4c9a16ea66fb +DocumentNamespace: https://anchore.com/syft/image/user-image-input-baff7ada-85cb-403e-90d7-05b0c6d79490 LicenseListVersion: 3.18 Creator: Organization: Anchore, Inc Creator: Tool: syft-v0.42.0-bogus -Created: 2022-11-18T14:21:45Z +Created: 2022-11-19T13:48:30Z ##### Package: package-2 diff --git a/syft/formats/spdxtagvalue/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/syft/formats/spdxtagvalue/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden index f902fc6aa28a96adb912012fc34d15c22edd31f8..0a4b4d25667754eaccaf5fe1dabb4e5a5b16005e 100644 GIT binary patch literal 15360 zcmeHOZExE)5YFfQ3QzkQ+kB^JU>~xkKnoO0(Pka6peQK5BwB3AkmRC4kpI4u?Krl( zL`@_c$wtGl`FcD)r<3k@Cy5P`Tr=aC@SgZ2HYUbI3u`Q6PFw4}v;qpyELBXolU90< zluLN5(D0!7gAju?_yJmcw*Twa1I#GGk{}__0U}5udC=p{q}z{}m6a}lrM8r|H`kWl zp61K8^8fVu!^gKLzdyt-!Uze*w&i|X2ju9M{IO*Gpx0U^4>5Jy_dl0E9_$6>TeQRf zGee-Y{{LO(S;L+h^dEDwegDT?ilF}uuy)dY9i=uJMQtyG=rEe@DZywiePNf;F(A;#H+Vaqhpv4-b9^N2V{jR#t$aJq6eV+0Y>M{%F0SQ3 zvxNfTfIvVXAP^9ERtO~Apv3DqFd;S+`S>*-z z;Ahtj)1;u3B1-7|z+kb$mjq@;N5{v#xe0`8^S3u#nZt|vFTJF8urJdJST*@%vN++m zZ5-I#T)LtrF!+k1o5LnXHcu}8m65p}zQ)L+{zyi^BVKb#52GT_D-T}kbyQtVYu9z| zwUw|bn|l8xwa|AKl^2?DF#^T6*d&}Qs%$J12o4bip&n_G<`i+2BvdkDh!vb-CKz=D zei68m9%*8M>MbQMm6FDLrDG~ERX7%es>FIHCE*Cla5jW2a#l&prNaorTHL|yg;A`c z&o?j5q27zucDG2|!@3>C|9Bn$3Gu(~y}&pMdl(bh!!xZ4C<5fIvVX zAP^Av&ml0;S?XO`{YV_=she+l{&P;(a={`0AM!tN$p3jN+>e?Ev6ENJyveAOSRiH?>0~-~qnJbPr{NgIabhiz%u5|Br<8-& zMihb=q%cf5NxV0Tb9gbt!0RYD_Q(-pcv5Hoy{mK3=F4^G&cHsp%Z-CT#^;|NC6|2- zE^OH zTtXA!MVhMdVEYF~z>@O;UVb)zo4W(Tl7u9TgE9k5G3Ci%$hV8`-eOVJx&)QFO4@w5 zuJU^7PrCa5{foEnULF2EEwDL`(+s{mu&c-B!moxoqckbQkQiYpmY5HTNU}1XWAD3f|AYnhu1-j|1DRit}r~oYviWxMxD*sjaa#{1NuC+aVSGz1n zlc1-S-$Uzr#iIWDrZ1uEs^w9Aw!S```~0Sywse?VP-4~oMgAF0^2Kzzhn~;iiI$hI zX8L5M==);2nEC3m=I^5Xl;tM}*-G0Nd0n2(i!2AdmVFQNKNi_^E$X#4e!A*@v4;w{ zMAIx^d_fmG@#_7BbaniAs?U5mYW7gKezwFv`+EOJu@Eu-Z#C!+E2?7VLpJsMWK@5t zcPRLps4f1-n2Kior;H0oLXrU{q)8Xz{_mO%AM3I{&8lHD0fwi#8a7L`&+F>3MvHQz z1)>F_1)>F>iUo|co?GoGQ<^GmwN=Ji<`d!^2~J_-(x55fHc;j~b6TX%xP)VsV1@M~ z;eS%#i2wC5M>_leQSd*CN!bPqx5sm`sJ^?I|A7MJ7a>Dp1Nf@Dw$~2;iccF?u1j_mWy?J)@^7rwg zD#z2p>gl*LSw6W|UKg(_+FQ#aT%zM|foaDuWgm*u>e8NOwYT-6Y=B@rbAo}G?+D*^ zULv{%{v+YPT*mXC&c3~mfHnS0zbF3NzW;CHzmWg+ax(pspZ~YmKV1XAzusrg#5U0a z(E`x|(E>ld1&p^q&Xm?LE^Sa&DTh;GXqsBhoG_Lu$~~c00zZ=qn|L9t492IalTy0T z4)T8roX?y5PePKI|MxPv&e1JN%~kf;vSD_Vr`=%6G%45(Vhm7Wu2@7{Gk-X_u8R_w zJs-~R?8ZitQkLQ*Q7vGwc)cBN=@7%;hNhwIe9CH2)fTha z65+VKIdX;lHs98b5x(r zo7A;s?NsnkE(_sf=AiBas!lcKVnVp2!lb~(h9c0tnNA$=w-Zbq91^9lA}C1}oCFzy zmBmyBN3^k6V`Bt&5~Qvq38NiX+;YjWkvIscSSp;cu#TiURn(`RHI#EAiK7V)n0gr8 zD;x;sQlsOGzWGqS1l