Skip to content

Commit

Permalink
fix(sbom): update logic for work with files in spdx format (aquasecur…
Browse files Browse the repository at this point in the history
…ity#4513)

Co-authored-by: Teppei Fukuda <knqyf263@gmail.com>
  • Loading branch information
2 people authored and AnaisUrlichs committed Aug 10, 2023
1 parent c5a05cb commit 01f1d98
Show file tree
Hide file tree
Showing 8 changed files with 384 additions and 72 deletions.
4 changes: 4 additions & 0 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ func readSpdxJson(t *testing.T, filePath string) *spdx.Document {
return bom.Relationships[i].RefB.ElementRefID < bom.Relationships[j].RefB.ElementRefID
})

sort.Slice(bom.Files, func(i, j int) bool {
return bom.Files[i].FileSPDXIdentifier < bom.Files[j].FileSPDXIdentifier
})

// We don't compare values which change each time an SBOM is generated
bom.CreationInfo.Created = ""
bom.DocumentNamespace = ""
Expand Down
68 changes: 38 additions & 30 deletions integration/testdata/conda-spdx.json.golden
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "testdata/fixtures/fs/conda",
"documentNamespace": "http://aquasecurity.github.io/trivy/filesystem/testdata/fixtures/fs/conda-e854267f-30a6-497d-9183-2f45dee37b09",
"documentNamespace": "http://aquasecurity.github.io/trivy/filesystem/testdata/fixtures/fs/conda-8864fdf2-1c56-4e86-bc35-c89a0a4c22b9",
"creationInfo": {
"licenseListVersion": "",
"creators": [
"Organization: aquasecurity",
"Tool: trivy-dev"
],
"created": "2023-05-19T10:38:39Z"
"created": "2023-05-31T07:16:47Z"
},
"packages": [
{
Expand All @@ -37,20 +37,7 @@
"referenceLocator": "pkg:conda/openssl@1.1.1q"
}
],
"primaryPackagePurpose": "LIBRARY",
"files": [
{
"fileName": "miniconda3/envs/testenv/conda-meta/openssl-1.1.1q-h7f8727e_0.json",
"SPDXID": "SPDXRef-File-600e5e0110a84891",
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "237db0da53131e4548cb1181337fa0f420299e1f"
}
],
"copyrightText": ""
}
]
"primaryPackagePurpose": "LIBRARY"
},
{
"name": "pip",
Expand All @@ -68,20 +55,7 @@
"referenceLocator": "pkg:conda/pip@22.2.2"
}
],
"primaryPackagePurpose": "LIBRARY",
"files": [
{
"fileName": "miniconda3/envs/testenv/conda-meta/pip-22.2.2-py38h06a4308_0.json",
"SPDXID": "SPDXRef-File-7eb62e2a3edddc0a",
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "a6a2db7668f1ad541d704369fc66c96a4415aa24"
}
],
"copyrightText": ""
}
]
"primaryPackagePurpose": "LIBRARY"
},
{
"name": "testdata/fixtures/fs/conda",
Expand All @@ -94,6 +68,30 @@
"primaryPackagePurpose": "SOURCE"
}
],
"files": [
{
"fileName": "miniconda3/envs/testenv/conda-meta/openssl-1.1.1q-h7f8727e_0.json",
"SPDXID": "SPDXRef-File-600e5e0110a84891",
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "237db0da53131e4548cb1181337fa0f420299e1f"
}
],
"copyrightText": ""
},
{
"fileName": "miniconda3/envs/testenv/conda-meta/pip-22.2.2-py38h06a4308_0.json",
"SPDXID": "SPDXRef-File-7eb62e2a3edddc0a",
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "a6a2db7668f1ad541d704369fc66c96a4415aa24"
}
],
"copyrightText": ""
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-DOCUMENT",
Expand All @@ -110,10 +108,20 @@
"relatedSpdxElement": "SPDXRef-Package-b1088cb4090e3a55",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-b1088cb4090e3a55",
"relatedSpdxElement": "SPDXRef-File-600e5e0110a84891",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Application-ee5ef1aa4ac89125",
"relatedSpdxElement": "SPDXRef-Package-6b677e82217fb5bd",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-6b677e82217fb5bd",
"relatedSpdxElement": "SPDXRef-File-7eb62e2a3edddc0a",
"relationshipType": "CONTAINS"
}
]
}
19 changes: 13 additions & 6 deletions pkg/sbom/spdx/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ func (m *Marshaler) Marshal(r types.Report) (*spdx.Document, error) {
relationShip(DocumentSPDXIdentifier, rootPkg.PackageSPDXIdentifier, RelationShipDescribe),
)

var spdxFiles []*spdx.File

for _, result := range r.Results {
if len(result.Packages) == 0 {
continue
Expand All @@ -160,6 +162,16 @@ func (m *Marshaler) Marshal(r types.Report) (*spdx.Document, error) {
relationShips = append(relationShips,
relationShip(parentPackage.PackageSPDXIdentifier, spdxPackage.PackageSPDXIdentifier, RelationShipContains),
)
files, err := m.pkgFiles(pkg)
if err != nil {
return nil, xerrors.Errorf("package file error: %w", err)
}
spdxFiles = append(spdxFiles, files...)
for _, file := range files {
relationShips = append(relationShips,
relationShip(spdxPackage.PackageSPDXIdentifier, file.FileSPDXIdentifier, RelationShipContains),
)
}
}
}

Expand All @@ -184,6 +196,7 @@ func (m *Marshaler) Marshal(r types.Report) (*spdx.Document, error) {
},
Packages: toPackages(packages),
Relationships: relationShips,
Files: spdxFiles,
}, nil
}

Expand Down Expand Up @@ -337,11 +350,6 @@ func (m *Marshaler) pkgToSpdxPackage(t, pkgDownloadLocation string, class types.
attrTexts = appendAttributionText(attrTexts, PropertyLayerDigest, pkg.Layer.Digest)
attrTexts = appendAttributionText(attrTexts, PropertyLayerDiffID, pkg.Layer.DiffID)

files, err := m.pkgFiles(pkg)
if err != nil {
return spdx.Package{}, xerrors.Errorf("package file error: %w", err)
}

supplier := &spdx.Supplier{Supplier: PackageSupplierNoAssertion}
if pkg.Maintainer != "" {
supplier = &spdx.Supplier{
Expand Down Expand Up @@ -373,7 +381,6 @@ func (m *Marshaler) pkgToSpdxPackage(t, pkgDownloadLocation string, class types.
PrimaryPackagePurpose: PackagePurposeLibrary,
PackageSupplier: supplier,
PackageChecksums: checksum,
Files: files,
}, nil
}

Expand Down
73 changes: 43 additions & 30 deletions pkg/sbom/spdx/marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,18 +401,6 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageAttributionTexts: []string{
"LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488",
},
Files: []*spdx.File{
{
FileSPDXIdentifier: "File-fa42187221d0d0a8",
FileName: "tools/project-doe/specifications/actionpack.gemspec",
Checksums: []spdx.Checksum{
{
Algorithm: spdx.SHA1,
Value: "413f98442c83808042b5d1d2611a346b999bdca5",
},
},
},
},
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
},
Expand All @@ -433,18 +421,6 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageAttributionTexts: []string{
"LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488",
},
Files: []*spdx.File{
{
FileSPDXIdentifier: "File-6a540784b0dc6d55",
FileName: "tools/project-john/specifications/actionpack.gemspec",
Checksums: []spdx.Checksum{
{
Algorithm: spdx.SHA1,
Value: "d2f9f9aed5161f6e4116a3f9573f41cd832f137c",
},
},
},
},
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
},
Expand Down Expand Up @@ -475,6 +451,28 @@ func TestMarshaler_Marshal(t *testing.T) {
PrimaryPackagePurpose: tspdx.PackagePurposeApplication,
},
},
Files: []*spdx.File{
{
FileSPDXIdentifier: "File-6a540784b0dc6d55",
FileName: "tools/project-john/specifications/actionpack.gemspec",
Checksums: []spdx.Checksum{
{
Algorithm: spdx.SHA1,
Value: "d2f9f9aed5161f6e4116a3f9573f41cd832f137c",
},
},
},
{
FileSPDXIdentifier: "File-fa42187221d0d0a8",
FileName: "tools/project-doe/specifications/actionpack.gemspec",
Checksums: []spdx.Checksum{
{
Algorithm: spdx.SHA1,
Value: "413f98442c83808042b5d1d2611a346b999bdca5",
},
},
},
},
Relationships: []*spdx.Relationship{
{
RefA: spdx.DocElementID{ElementRefID: "DOCUMENT"},
Expand All @@ -501,11 +499,21 @@ func TestMarshaler_Marshal(t *testing.T) {
RefB: spdx.DocElementID{ElementRefID: "Package-d5443dbcbba0dbd4"},
Relationship: "CONTAINS",
},
{
RefA: spdx.DocElementID{ElementRefID: "Package-d5443dbcbba0dbd4"},
RefB: spdx.DocElementID{ElementRefID: "File-6a540784b0dc6d55"},
Relationship: "CONTAINS",
},
{
RefA: spdx.DocElementID{ElementRefID: "Application-441a648f2aeeee72"},
RefB: spdx.DocElementID{ElementRefID: "Package-13fe667a0805e6b7"},
Relationship: "CONTAINS",
},
{
RefA: spdx.DocElementID{ElementRefID: "Package-13fe667a0805e6b7"},
RefB: spdx.DocElementID{ElementRefID: "File-fa42187221d0d0a8"},
Relationship: "CONTAINS",
},
},

OtherLicenses: nil,
Expand Down Expand Up @@ -684,16 +692,16 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageAttributionTexts: []string{
"LayerDiffID: sha256:661c3fd3cc16b34c070f3620ca6b03b6adac150f9a7e5d0e3c707a159990f88e",
},
Files: []*spdx.File{
{
FileName: "usr/local/lib/ruby/gems/3.1.0/gems/typeprof-0.21.1/vscode/package.json",
FileSPDXIdentifier: "File-a52825a3e5bc6dfe",
},
},
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
},
},
Files: []*spdx.File{
{
FileName: "usr/local/lib/ruby/gems/3.1.0/gems/typeprof-0.21.1/vscode/package.json",
FileSPDXIdentifier: "File-a52825a3e5bc6dfe",
},
},
Relationships: []*spdx.Relationship{
{
RefA: spdx.DocElementID{ElementRefID: "DOCUMENT"},
Expand All @@ -710,6 +718,11 @@ func TestMarshaler_Marshal(t *testing.T) {
RefB: spdx.DocElementID{ElementRefID: "Package-daedb173cfd43058"},
Relationship: "CONTAINS",
},
{
RefA: spdx.DocElementID{ElementRefID: "Package-daedb173cfd43058"},
RefB: spdx.DocElementID{ElementRefID: "File-a52825a3e5bc6dfe"},
Relationship: "CONTAINS",
},
},
},
},
Expand Down
91 changes: 91 additions & 0 deletions pkg/sbom/spdx/testdata/happy/with-files-in-relationships-bom.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "app",
"documentNamespace": "http://aquasecurity.github.io/trivy/filesystem/app-8e571278-2221-4dcd-bc56-0b256210fa91",
"creationInfo": {
"licenseListVersion": "",
"creators": [
"Organization: aquasecurity",
"Tool: trivy-dev"
],
"created": "2023-05-31T05:58:45Z"
},
"packages": [
{
"name": "app",
"SPDXID": "SPDXRef-Filesystem-13b142ca391a006e",
"downloadLocation": "NONE",
"copyrightText": "",
"attributionTexts": [
"SchemaVersion: 2"
],
"primaryPackagePurpose": "SOURCE"
},
{
"name": "node-pkg",
"SPDXID": "SPDXRef-Application-24f8a80152e2c0fc",
"downloadLocation": "NONE",
"sourceInfo": "Node.js",
"copyrightText": "",
"primaryPackagePurpose": "APPLICATION"
},
{
"name": "yargs-parser",
"SPDXID": "SPDXRef-Package-c3508825bf3861d8",
"versionInfo": "21.1.1",
"supplier": "NOASSERTION",
"downloadLocation": "NONE",
"licenseConcluded": "ISC",
"licenseDeclared": "ISC",
"copyrightText": "",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:npm/yargs-parser@21.1.1"
}
],
"attributionTexts": [
"PkgID: yargs-parser@21.1.1"
],
"primaryPackagePurpose": "LIBRARY"
}
],
"files": [
{
"fileName": "node_modules/yargs-parser/package.json",
"SPDXID": "SPDXRef-File-51bb5f929ef68877",
"checksums": [
{
"algorithm": "SHA1",
"checksumValue": "69e70ec702f9df4ff64024b5fdea4644f1ce6c97"
}
],
"copyrightText": ""
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relatedSpdxElement": "SPDXRef-Filesystem-13b142ca391a006e",
"relationshipType": "DESCRIBES"
},
{
"spdxElementId": "SPDXRef-Filesystem-13b142ca391a006e",
"relatedSpdxElement": "SPDXRef-Application-24f8a80152e2c0fc",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Application-24f8a80152e2c0fc",
"relatedSpdxElement": "SPDXRef-Package-c3508825bf3861d8",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-c3508825bf3861d8",
"relatedSpdxElement": "SPDXRef-File-51bb5f929ef68877",
"relationshipType": "CONTAINS"
}
]
}
Loading

0 comments on commit 01f1d98

Please sign in to comment.