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
This commit is contained in:
Ibrahim Kanouche
2023-04-03 20:15:14 +00:00
parent 960a4700e0
commit f89fc4aa9b
2 changed files with 217 additions and 61 deletions

View File

@@ -16,6 +16,8 @@ package main
import (
"bytes"
"crypto/sha1"
"encoding/hex"
"flag"
"fmt"
"io"
@@ -194,11 +196,12 @@ Options:
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 @@ func replaceSlashes(x string) string {
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 @@ func getDocumentName(ctx *context, tn *compliance.TargetNode, pm *projectmetadat
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 @@ func inputFiles(lg *compliance.LicenseGraph, pmix *projectmetadata.Index, licens
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,6 +357,9 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
// creating the license section
otherLicenses := []*spdx.OtherLicense{}
// spdx document name
var docName string
// main package name
var mainPkgName string
@@ -365,6 +400,7 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
}
if isMainPackage {
docName = getDocumentName(ctx, tn, pm)
mainPkgName = replaceSlashes(getPackageName(ctx, tn))
isMainPackage = false
}
@@ -478,8 +514,14 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
return nil, nil, fmt.Errorf("Unable to build creation info section for SPDX doc: %v\n", err)
}
ci.Created = ctx.creationTime()
return &spdx.Document{
SPDXVersion: "SPDX-2.2",
DataLicense: "CC0-1.0",
SPDXIdentifier: "DOCUMENT",
DocumentName: docName,
DocumentNamespace: generateSPDXNamespace(ci.Created),
CreationInfo: ci,
Packages: pkgs,
Relationships: relationships,

View File

@@ -55,7 +55,11 @@ func Test(t *testing.T) {
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -179,7 +183,11 @@ func Test(t *testing.T) {
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -254,7 +262,11 @@ func Test(t *testing.T) {
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -378,7 +390,11 @@ func Test(t *testing.T) {
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -440,7 +456,11 @@ func Test(t *testing.T) {
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -476,7 +496,11 @@ func Test(t *testing.T) {
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -606,7 +630,11 @@ func Test(t *testing.T) {
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -736,7 +764,11 @@ func Test(t *testing.T) {
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -817,7 +849,11 @@ func Test(t *testing.T) {
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -885,7 +921,11 @@ func Test(t *testing.T) {
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -921,7 +961,11 @@ func Test(t *testing.T) {
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1057,7 +1101,11 @@ func Test(t *testing.T) {
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1144,7 +1192,11 @@ func Test(t *testing.T) {
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1212,7 +1264,11 @@ func Test(t *testing.T) {
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1248,7 +1304,11 @@ func Test(t *testing.T) {
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1390,7 +1450,11 @@ func Test(t *testing.T) {
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1532,7 +1596,11 @@ func Test(t *testing.T) {
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1606,7 +1674,11 @@ func Test(t *testing.T) {
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1642,7 +1714,11 @@ func Test(t *testing.T) {
name: "apex",
roots: []string{"highest.apex.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1784,7 +1860,11 @@ func Test(t *testing.T) {
name: "container",
roots: []string{"container.zip.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -1926,7 +2006,11 @@ func Test(t *testing.T) {
name: "application",
roots: []string{"application.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -2013,7 +2097,11 @@ func Test(t *testing.T) {
name: "binary",
roots: []string{"bin/bin1.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -2081,7 +2169,11 @@ func Test(t *testing.T) {
name: "library",
roots: []string{"lib/libd.so.meta_lic"},
expectedOut: &spdx.Document{
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{
{
@@ -2123,7 +2215,7 @@ func Test(t *testing.T) {
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 @@ func compareSpdxDocs(t *testing.T, actual, expected *spdx.Document) {
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 @@ func compareLicenses(t *testing.T, i int, actual, expected *spdx.OtherLicense) b
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")
}