Added Document Fields to SBOM generator
Added functions to generate unique spdx doc namespace and generate a
clean document name
Test: m compliance_sbom
Bug: 265472710
Change-Id: I86ea9ddf50d066e139b757e8a093f98b8df8c81f
diff --git a/tools/compliance/cmd/sbom/sbom.go b/tools/compliance/cmd/sbom/sbom.go
index 1477ca5..3cdfa0a 100644
--- a/tools/compliance/cmd/sbom/sbom.go
+++ b/tools/compliance/cmd/sbom/sbom.go
@@ -16,6 +16,8 @@
import (
"bytes"
+ "crypto/sha1"
+ "encoding/hex"
"flag"
"fmt"
"io"
@@ -194,11 +196,12 @@
os.Exit(0)
}
-type creationTimeGetter func() time.Time
+type creationTimeGetter func() string
// actualTime returns current time in UTC
-func actualTime() time.Time {
- return time.Now().UTC()
+func actualTime() string {
+ t := time.Now().UTC()
+ return t.UTC().Format("2006-01-02T15:04:05Z")
}
// replaceSlashes replaces "/" by "-" for the library path to be used for packages & files SPDXID
@@ -206,6 +209,23 @@
return strings.ReplaceAll(x, "/", "-")
}
+// stripDocName removes the outdir prefix and meta_lic suffix from a target Name
+func stripDocName(name string) string {
+ // remove outdir prefix
+ if strings.HasPrefix(name, "out/") {
+ name = name[4:]
+ }
+
+ // remove suffix
+ if strings.HasSuffix(name, ".meta_lic") {
+ name = name[:len(name)-9]
+ } else if strings.HasSuffix(name, "/meta_lic") {
+ name = name[:len(name)-9] + "/"
+ }
+
+ return name
+}
+
// getPackageName returns a package name of a target Node
func getPackageName(_ *context, tn *compliance.TargetNode) string {
return replaceSlashes(tn.Name())
@@ -223,8 +243,7 @@
return replaceSlashes(tn.ModuleName())
}
- // TO DO: Replace tn.Name() with pm.Name() + parts of the target name
- return replaceSlashes(tn.Name())
+ return stripDocName(replaceSlashes(tn.Name()))
}
// getDownloadUrl returns the download URL if available (GIT, SVN, etc..),
@@ -295,6 +314,19 @@
return files
}
+// generateSPDXNamespace generates a unique SPDX Document Namespace using a SHA1 checksum
+// and the CreationInfo.Created field as the date.
+func generateSPDXNamespace(created string) string {
+ // Compute a SHA1 checksum of the CreationInfo.Created field.
+ hash := sha1.Sum([]byte(created))
+ checksum := hex.EncodeToString(hash[:])
+
+ // Combine the checksum and timestamp to generate the SPDX Namespace.
+ namespace := fmt.Sprintf("SPDXRef-DOCUMENT-%s-%s", created, checksum)
+
+ return namespace
+}
+
// sbomGenerator implements the spdx bom utility
// SBOM is part of the new government regulation issued to improve national cyber security
@@ -325,8 +357,11 @@
// creating the license section
otherLicenses := []*spdx.OtherLicense{}
- // main package name
- var mainPkgName string
+ // spdx document name
+ var docName string
+
+ // main package name
+ var mainPkgName string
// implementing the licenses references for the packages
licenses := make(map[string]string)
@@ -365,6 +400,7 @@
}
if isMainPackage {
+ docName = getDocumentName(ctx, tn, pm)
mainPkgName = replaceSlashes(getPackageName(ctx, tn))
isMainPackage = false
}
@@ -478,11 +514,17 @@
return nil, nil, fmt.Errorf("Unable to build creation info section for SPDX doc: %v\n", err)
}
+ ci.Created = ctx.creationTime()
+
return &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: ci,
- Packages: pkgs,
- Relationships: relationships,
- OtherLicenses: otherLicenses,
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: docName,
+ DocumentNamespace: generateSPDXNamespace(ci.Created),
+ CreationInfo: ci,
+ Packages: pkgs,
+ Relationships: relationships,
+ OtherLicenses: otherLicenses,
}, deps, nil
}
diff --git a/tools/compliance/cmd/sbom/sbom_test.go b/tools/compliance/cmd/sbom/sbom_test.go
index cc8805f..65a2df1 100644
--- a/tools/compliance/cmd/sbom/sbom_test.go
+++ b/tools/compliance/cmd/sbom/sbom_test.go
@@ -55,8 +55,12 @@
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-firstparty-highest.apex",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-firstparty-highest.apex.meta_lic",
@@ -179,8 +183,12 @@
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-firstparty-application",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-firstparty-application.meta_lic",
@@ -254,8 +262,12 @@
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-firstparty-container.zip",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-firstparty-container.zip.meta_lic",
@@ -378,8 +390,12 @@
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-firstparty-bin-bin1",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-firstparty-bin-bin1.meta_lic",
@@ -440,8 +456,12 @@
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-firstparty-lib-libd.so",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-firstparty-lib-libd.so.meta_lic",
@@ -476,8 +496,12 @@
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-notice-highest.apex",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-notice-highest.apex.meta_lic",
@@ -606,8 +630,12 @@
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-notice-container.zip",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-notice-container.zip.meta_lic",
@@ -736,8 +764,12 @@
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-notice-application",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-notice-application.meta_lic",
@@ -817,8 +849,12 @@
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-notice-bin-bin1",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-notice-bin-bin1.meta_lic",
@@ -885,8 +921,12 @@
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-notice-lib-libd.so",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-notice-lib-libd.so.meta_lic",
@@ -921,8 +961,12 @@
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-reciprocal-highest.apex",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-reciprocal-highest.apex.meta_lic",
@@ -1057,8 +1101,12 @@
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-reciprocal-application",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-reciprocal-application.meta_lic",
@@ -1144,8 +1192,12 @@
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-reciprocal-bin-bin1",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-reciprocal-bin-bin1.meta_lic",
@@ -1212,8 +1264,12 @@
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-reciprocal-lib-libd.so",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-reciprocal-lib-libd.so.meta_lic",
@@ -1248,8 +1304,12 @@
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-restricted-highest.apex",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-restricted-highest.apex.meta_lic",
@@ -1390,8 +1450,12 @@
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-restricted-container.zip",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-restricted-container.zip.meta_lic",
@@ -1532,8 +1596,12 @@
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-restricted-bin-bin1",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-restricted-bin-bin1.meta_lic",
@@ -1606,8 +1674,12 @@
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-restricted-lib-libd.so",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-restricted-lib-libd.so.meta_lic",
@@ -1642,8 +1714,12 @@
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-proprietary-highest.apex",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-proprietary-highest.apex.meta_lic",
@@ -1784,8 +1860,12 @@
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-proprietary-container.zip",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-proprietary-container.zip.meta_lic",
@@ -1926,8 +2006,12 @@
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-proprietary-application",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-proprietary-application.meta_lic",
@@ -2013,8 +2097,12 @@
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-proprietary-bin-bin1",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-proprietary-bin-bin1.meta_lic",
@@ -2081,8 +2169,12 @@
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
- SPDXIdentifier: "DOCUMENT",
- CreationInfo: getCreationInfo(t),
+ SPDXVersion: "SPDX-2.2",
+ DataLicense: "CC0-1.0",
+ SPDXIdentifier: "DOCUMENT",
+ DocumentName: "testdata-proprietary-lib-libd.so",
+ DocumentNamespace: generateSPDXNamespace("1970-01-01T00:00:00Z"),
+ CreationInfo: getCreationInfo(t),
Packages: []*spdx.Package{
{
PackageName: "testdata-proprietary-lib-libd.so.meta_lic",
@@ -2123,7 +2215,7 @@
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
- ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), "Android", []string{tt.stripPrefix}, fakeTime}
+ ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), "", []string{tt.stripPrefix}, fakeTime}
spdxDoc, deps, err := sbomGenerator(&ctx, rootFiles...)
if err != nil {
@@ -2181,6 +2273,27 @@
if actual == nil || expected == nil {
t.Errorf("SBOM: SPDX Doc is nil! Got %v: Expected %v", actual, expected)
}
+
+ if actual.DocumentName != expected.DocumentName {
+ t.Errorf("sbom: unexpected SPDX Document Name got %q, want %q", actual.DocumentName, expected.DocumentName)
+ }
+
+ if actual.SPDXVersion != expected.SPDXVersion {
+ t.Errorf("sbom: unexpected SPDX Version got %s, want %s", actual.SPDXVersion, expected.SPDXVersion)
+ }
+
+ if actual.DataLicense != expected.DataLicense {
+ t.Errorf("sbom: unexpected SPDX DataLicense got %s, want %s", actual.DataLicense, expected.DataLicense)
+ }
+
+ if actual.SPDXIdentifier != expected.SPDXIdentifier {
+ t.Errorf("sbom: unexpected SPDX Identified got %s, want %s", actual.SPDXIdentifier, expected.SPDXIdentifier)
+ }
+
+ if actual.DocumentNamespace != expected.DocumentNamespace {
+ t.Errorf("sbom: unexpected SPDX Document Namespace got %s, want %s", actual.DocumentNamespace, expected.DocumentNamespace)
+ }
+
// compare creation info
compareSpdxCreationInfo(t, actual.CreationInfo, expected.CreationInfo)
@@ -2314,6 +2427,7 @@
return true
}
-func fakeTime() time.Time {
- return time.UnixMicro(0).UTC()
+func fakeTime() string {
+ t := time.UnixMicro(0)
+ return t.UTC().Format("2006-01-02T15:04:05Z")
}