Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make SPDX version configurable #14

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion config/example_config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"spdxVersion": "SPDX-2.2",
"documentName": "composed-1.0",
"packageName": "top-level-artifact",
"spdxID": "SPDXRef-composed-sbom-product",
Expand All @@ -12,5 +13,8 @@
"packageLicenseDeclared": "license, licenseRef or NOASSERTION",
"packageCopyrightText": "text or NOASSERTION",
"packageSupplier": "Organization or recognized author of product. Optional",
"packageComment": "<text>Any relevant comment</text>. Optional"
"packageComment": "<text>Any relevant comment</text>. Optional",
"namespacePrefix": "https://spdx.org/spdxdocs/",
"creator": "sbom-composer-v0.1",
"creatorType": "Tool"
}
10 changes: 10 additions & 0 deletions config/example_config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2022 VMware, Inc. All Rights Reserved.
# SPDX-License-Identifier: BSD-2-Clause

# SPDX version the composed doc is output to
spdxVersion: "SPDX-2.2"
# SBOM-Composer report for <top level product name>
documentName: "composed-1.0"
# Top Level Composed SBOM product
Expand All @@ -24,3 +26,11 @@ packageCopyrightText: ""
packageSupplier: "Example supplier"
# <text>Any relevant comment</text>. Optional
packageComment: "<text>Example comment</text>"

# The following fields belong to SPDX config reference
# Prefix used for DocumentNamespace
NamespacePrefix: "https://spdx.org/spdxdocs/"
# Composed SPDX SBOM creator
Creator: "sbom-composer-v0.1"
# Should be always set to "Tool"
CreatorType: "Tool"
22 changes: 14 additions & 8 deletions parser/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,26 @@ import (
"github.com/spdx/tools-golang/builder"
)

func Build(spdxVersion string, dirRoot string, conf *Config) (*Document, error) {
spdxDocRef := BuildVersion(spdxVersion, dirRoot, conf)
func Build(dirRoot string, conf *Config) (*Document, error) {
spdxDocRef := BuildVersion(dirRoot, conf)

UpdatePackages(SPDX_VERSION, &spdxDocRef, conf)
UpdatePackages(&spdxDocRef, conf)
doc := CreateDocument(&spdxDocRef, conf)
return doc, nil
}

func BuildVersion(spdxVersion string, dirRoot string, conf *Config) SPDXDocRef {
func BuildVersion(dirRoot string, conf *Config) SPDXDocRef {
res := SPDXDocRef{}
switch spdxVersion {
case "2.2":
switch conf.SPDXVersion {
case "SPDX-2.2":
var err error
res.Doc2_2, err = builder.Build2_2(conf.PackageName, dirRoot, conf.SPDXConfigRef)
res.Doc2_2, err = builder.Build2_2(conf.PackageName, dirRoot, conf.SPDXConfigRef.Conf2_2)
if err != nil {
fmt.Printf("error while building spdx document reference for path %v with config %v, %v: %v\n", dirRoot, conf.PackageName, conf.SPDXConfigRef, err)
}
default:
var err error
res.Doc2_2, err = builder.Build2_2(conf.PackageName, dirRoot, conf.SPDXConfigRef.Conf2_2)
if err != nil {
fmt.Printf("error while building spdx document reference for path %v with config %v, %v: %v\n", dirRoot, conf.PackageName, conf.SPDXConfigRef, err)
}
Expand All @@ -33,7 +39,7 @@ func BuildVersion(spdxVersion string, dirRoot string, conf *Config) SPDXDocRef {
func GenerateComposedDoc(dirRoot string, output string, outFormat string, confFile string) error {
conf := LoadConfig(confFile)

doc, err := Build(SPDX_VERSION, dirRoot, conf)
doc, err := Build(dirRoot, conf)
if err != nil {
return err
}
Expand Down
23 changes: 17 additions & 6 deletions parser/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import (
"fmt"
"testing"

"github.com/spdx/tools-golang/builder"
"github.com/spdx/tools-golang/spdx"
"github.com/stretchr/testify/assert"
)

func TestGenerateComposedDoc(t *testing.T) {
fmt.Println("Testing Unmarshal JSON Config")
t.Run("Unmarshal Config:", func(t *testing.T) {
input := []byte(`documentName: "composed-1.0"
input := []byte(`spdxVersion: "SPDX-2.2"
documentName: "composed-1.0"
packageName: "top-level-artifact"
spdxID: "SPDXRef-DOCUMENT"
packageVersion: "1.0"
Expand All @@ -26,19 +28,28 @@ packageLicenseConcluded: "BSD-3-Clause"
packageLicenseDeclared: "BSD-3-Clause"
packageCopyrightText: ""
packageSupplier: "somesupplier"
packageComment: "<text>somecomment</text>"`)
packageComment: "<text>somecomment</text>"
namespacePrefix: "https://spdx.org/spdxdocs/"
creator: "sbom-composer-v0.1"
creatorType: "Tool"`)

want := Document{
SPDXDocRef: &SPDXDocRef{
Doc2_2: &spdx.Document2_2{
SPDXVersion: "SPDX-2.2",
DataLicense: "CC0-1.0",
SPDXIdentifier: "DOCUMENT",
DocumentName: "top-level-artifact",
DocumentNamespace: "https://spdx.org/spdxdocs/top-level-artifact-",
}},
ConfigDataRef: &Config{
SPDXConfigRef: SPDXConfigReference,
SPDXVersion: "SPDX-2.2",
SPDXConfigRef: SPDXConfigRef{
Conf2_2: &builder.Config2_2{
NamespacePrefix: "https://spdx.org/spdxdocs/",
CreatorType: "Tool",
Creator: "sbom-composer-1.0",
},
},
PackageName: "top-level-artifact",
DocumentName: "composed-1.0",
SPDXID: "SPDXRef-DOCUMENT",
Expand All @@ -57,10 +68,10 @@ packageComment: "<text>somecomment</text>"`)
}

loadedConfig := createConfig(input)
doc, err := Build(SPDX_VERSION, "../example_data/micro_sboms/tag_value", loadedConfig)
doc, err := Build("../example_data/micro_sboms/tag_value", loadedConfig)
assert.Equal(t, nil, err)

assert.Equal(t, want.SPDXDocRef.Doc2_2.SPDXVersion, doc.SPDXDocRef.Doc2_2.SPDXVersion)
assert.Equal(t, want.ConfigDataRef.SPDXVersion, doc.SPDXDocRef.Doc2_2.SPDXVersion)
assert.Equal(t, want.SPDXDocRef.Doc2_2.DataLicense, doc.SPDXDocRef.Doc2_2.DataLicense)
assert.Equal(t, want.SPDXDocRef.Doc2_2.SPDXIdentifier, doc.SPDXDocRef.Doc2_2.SPDXIdentifier)
assert.Equal(t, want.SPDXDocRef.Doc2_2.DocumentName, doc.SPDXDocRef.Doc2_2.DocumentName)
Expand Down
54 changes: 44 additions & 10 deletions parser/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,26 @@ import (
)

// PackageChecksum is a unique identifier used to verify if all files
// in the orginal package are unchanged, exluding SPDX documents.
// in the original package are unchanged, excluding SPDX documents.
// Should be generated with SHA256.
type PackageChecksum struct {
SHA256 string
}

var NOASSERTION string = "NOASSERTION"
var SPDXConfigReference *builder.Config2_2 = &builder.Config2_2{
NamespacePrefix: "https://spdx.org/spdxdocs/", // TODO: move this to config
CreatorType: "Tool",
Creator: "sbom-composer-1.0", // TODO: automate taking the version

type SPDXConfigRef struct {
Conf2_2 *builder.Config2_2
}

// Config is a collection of configuration settings for builder
// to create a composed document with.
type Config struct {
SPDXConfigRef *builder.Config2_2
SPDXConfigRef SPDXConfigRef

// SPDXVersion is a configuration for the
// version that should be used as an output
SPDXVersion string `json:"spdxVersion"`

// DocumentName is an SBOM-Composer report
// for <top level product name>
Expand Down Expand Up @@ -73,6 +76,15 @@ type Config struct {

// PackageComment is any relevant comment in a <text></text> section
PackageComment string `json:"packageComment,omitempty"`

// NamespacePrefix is a prefix used for DocumentNamespace
NamespacePrefix string `json:"namespacePrefix"`

// Creator is the composed SPDX SBOM creator
Creator string `json:"creator"`

// CreatorType refers to SPDX CreatorType field
CreatorType string `json:"creatorType"`
}

func UnmarshalJSONConfig(jsonData []byte) (*Config, error) {
Expand Down Expand Up @@ -111,9 +123,7 @@ func readConfFile(file string) []byte {
}

func createConfig(loadedData []byte) *Config {
conf := Config{}

conf.SPDXConfigRef = SPDXConfigReference
conf := &Config{}

mapData := make(map[string]interface{})

Expand All @@ -125,6 +135,8 @@ func createConfig(loadedData []byte) *Config {
dataByte, _ := json.Marshal(mapData)
_ = json.Unmarshal(dataByte, &conf)

conf = setSPDXConfigRef(conf)

if len(conf.PackageDownloadLocation) == 0 {
conf.PackageDownloadLocation = NOASSERTION
}
Expand All @@ -139,5 +151,27 @@ func createConfig(loadedData []byte) *Config {
}
conf.PackageChecksum.SHA256 = strings.Trim(conf.PackageChecksum.SHA256, "\"{}")

return &conf
return conf
}

func setSPDXConfigRef(conf *Config) *Config {
switch conf.SPDXVersion {
case "SPDX-2.2":
conf.SPDXConfigRef = SPDXConfigRef{
Conf2_2: &builder.Config2_2{
NamespacePrefix: conf.NamespacePrefix,
CreatorType: conf.CreatorType,
Creator: conf.Creator,
},
}
default:
conf.SPDXConfigRef = SPDXConfigRef{
Conf2_2: &builder.Config2_2{
NamespacePrefix: conf.NamespacePrefix,
CreatorType: conf.CreatorType,
Creator: conf.Creator,
},
}
}
return conf
}
9 changes: 5 additions & 4 deletions parser/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import (
"github.com/stretchr/testify/assert"
)

func generateJSONTConfigExample(documentName string, packageName string, spdxID string, packageVersion string,
func generateJSONTConfigExample(spdxVersion string, documentName string, packageName string, spdxID string, packageVersion string,
packageDownloadLocation string, packageChecksum PackageChecksum, filesAnalyzed bool, packageLicenseConcluded string,
packageLicenseDeclared string, packageCopyrightText string, packageSupplier string, packageComment string) []byte {
jsonStr := fmt.Sprintf("{\"documentName\":\"%s\",\"packageName\":\"%s\",\"spdxID\":\"%s\",\"packageVersion\":\"%s\",\"packageDownloadLocation\":\"%s\",\"filesAnalyzed\":\"%t\",\"packageChecksum\":\"%s\", \"packageLicenseConcluded\":\"%s\", \"packageLicenseDeclared\":\"%s\", \"packageCopyrightText\":\"%s\", \"packageSupplier\":\"%s\", \"packageComment\":\"%s\"}",
documentName, packageName, spdxID, packageVersion, packageDownloadLocation, filesAnalyzed, packageChecksum,
jsonStr := fmt.Sprintf("{\"spdxVersion\":\"%s\",\"documentName\":\"%s\",\"packageName\":\"%s\",\"spdxID\":\"%s\",\"packageVersion\":\"%s\",\"packageDownloadLocation\":\"%s\",\"filesAnalyzed\":\"%t\",\"packageChecksum\":\"%s\", \"packageLicenseConcluded\":\"%s\", \"packageLicenseDeclared\":\"%s\", \"packageCopyrightText\":\"%s\", \"packageSupplier\":\"%s\", \"packageComment\":\"%s\"}",
spdxVersion, documentName, packageName, spdxID, packageVersion, packageDownloadLocation, filesAnalyzed, packageChecksum,
packageLicenseConcluded, packageLicenseDeclared, packageCopyrightText, packageSupplier, packageComment)

return []byte(jsonStr)
Expand All @@ -37,11 +37,12 @@ func TestUnmarshalJSONConfig(t *testing.T) {

pch := PackageChecksum{SHA256: checksum}

jsonData := generateJSONTConfigExample("composed-1.0", "top-level-artifact", "SPDXRef-DOCUMENT", "1.0", NOASSERTION, pch,
jsonData := generateJSONTConfigExample("SPDX-2.2", "composed-1.0", "top-level-artifact", "SPDXRef-DOCUMENT", "1.0", NOASSERTION, pch,
false, "BSD-3-Clause", "BSD-3-Clause", NOASSERTION,
"somesupplier", "somecomment")
conf, _ := UnmarshalJSONConfig(jsonData)

assert.Equal(t, "SPDX-2.2", conf.SPDXVersion)
assert.Equal(t, "composed-1.0", conf.DocumentName)
assert.Equal(t, "top-level-artifact", conf.PackageName)
assert.Equal(t, "SPDXRef-DOCUMENT", conf.SPDXID)
Expand Down
13 changes: 10 additions & 3 deletions parser/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,16 @@ func CreateDocumentWithSPDXRef() *Document {
return doc
}

func UpdatePackages(spdxVersion string, spdxDocRef *SPDXDocRef, conf *Config) {
switch spdxVersion {
case "2.2":
func UpdatePackages(spdxDocRef *SPDXDocRef, conf *Config) {
switch conf.SPDXVersion {
case "SPDX-2.2":
for i := range spdxDocRef.Doc2_2.Packages {
if spdxDocRef.Doc2_2.Packages[i].PackageName == conf.PackageName &&
len(spdxDocRef.Doc2_2.Packages[i].PackageVersion) == 0 {
spdxDocRef.Doc2_2.Packages[i].PackageVersion = conf.PackageVersion
}
}
default:
for i := range spdxDocRef.Doc2_2.Packages {
if spdxDocRef.Doc2_2.Packages[i].PackageName == conf.PackageName &&
len(spdxDocRef.Doc2_2.Packages[i].PackageVersion) == 0 {
Expand Down
3 changes: 2 additions & 1 deletion parser/read_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ func TestLoadConfigYAML(t *testing.T) {
t.Run("Loading YAML Config:", func(t *testing.T) {

conf := LoadConfig("../config/example_config.yaml")
fmt.Println(conf)

assert.Equal(t, "SPDX-2.2", conf.SPDXVersion)
assert.Equal(t, "composed-1.0", conf.DocumentName)
assert.Equal(t, "top-level-artifact", conf.PackageName)
assert.Equal(t, "SPDXRef-DOCUMENT", conf.SPDXID)
Expand Down
Loading