Revert "Updated SBOM generator module to generate JSON spdx utility bill of"
This reverts commit e97adc5db9
.
Reason for revert: Roll back until the kernel manifests are updated with the spdx-tools library.
Change-Id: Ib2327862acd928ebcea0f328daecc162b46d2c78
This commit is contained in:
committed by
Gerrit Code Review
parent
e97adc5db9
commit
928ee9d9f7
@@ -138,10 +138,6 @@ blueprint_go_binary {
|
|||||||
"compliance-module",
|
"compliance-module",
|
||||||
"blueprint-deptools",
|
"blueprint-deptools",
|
||||||
"soong-response",
|
"soong-response",
|
||||||
"spdx-tools-spdxv2_2",
|
|
||||||
"spdx-tools-builder2v2",
|
|
||||||
"spdx-tools-spdxcommon",
|
|
||||||
"spdx-tools-spdx-json",
|
|
||||||
],
|
],
|
||||||
testSrcs: ["cmd/sbom/sbom_test.go"],
|
testSrcs: ["cmd/sbom/sbom_test.go"],
|
||||||
}
|
}
|
||||||
|
@@ -31,21 +31,13 @@ import (
|
|||||||
"android/soong/tools/compliance/projectmetadata"
|
"android/soong/tools/compliance/projectmetadata"
|
||||||
|
|
||||||
"github.com/google/blueprint/deptools"
|
"github.com/google/blueprint/deptools"
|
||||||
|
|
||||||
"github.com/spdx/tools-golang/builder/builder2v2"
|
|
||||||
"github.com/spdx/tools-golang/json"
|
|
||||||
"github.com/spdx/tools-golang/spdx/common"
|
|
||||||
spdx "github.com/spdx/tools-golang/spdx/v2_2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
|
failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
|
||||||
failNoLicenses = fmt.Errorf("No licenses found")
|
failNoLicenses = fmt.Errorf("No licenses found")
|
||||||
mainPkgName = flag.String("main_package_name", "", "The name of the first target node in the licensegraph")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const NOASSERTION = "NOASSERTION"
|
|
||||||
|
|
||||||
type context struct {
|
type context struct {
|
||||||
stdout io.Writer
|
stdout io.Writer
|
||||||
stderr io.Writer
|
stderr io.Writer
|
||||||
@@ -162,8 +154,7 @@ Options:
|
|||||||
|
|
||||||
ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, actualTime}
|
ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, actualTime}
|
||||||
|
|
||||||
spdxDoc, deps, err := sbomGenerator(ctx, flags.Args()...)
|
deps, err := sbomGenerator(ctx, flags.Args()...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == failNoneRequested {
|
if err == failNoneRequested {
|
||||||
flags.Usage()
|
flags.Usage()
|
||||||
@@ -172,11 +163,6 @@ Options:
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := spdx_json.Save2_2(spdxDoc, ofile); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "failed to write document to %v: %v", *outputFile, err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *outputFile != "-" {
|
if *outputFile != "-" {
|
||||||
err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
|
err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -232,17 +218,17 @@ func getDocumentName(ctx *context, tn *compliance.TargetNode, pm *projectmetadat
|
|||||||
// or NOASSERTION if not available, none determined or ambiguous
|
// or NOASSERTION if not available, none determined or ambiguous
|
||||||
func getDownloadUrl(_ *context, pm *projectmetadata.ProjectMetadata) string {
|
func getDownloadUrl(_ *context, pm *projectmetadata.ProjectMetadata) string {
|
||||||
if pm == nil {
|
if pm == nil {
|
||||||
return NOASSERTION
|
return "NOASSERTION"
|
||||||
}
|
}
|
||||||
|
|
||||||
urlsByTypeName := pm.UrlsByTypeName()
|
urlsByTypeName := pm.UrlsByTypeName()
|
||||||
if urlsByTypeName == nil {
|
if urlsByTypeName == nil {
|
||||||
return NOASSERTION
|
return "NOASSERTION"
|
||||||
}
|
}
|
||||||
|
|
||||||
url := urlsByTypeName.DownloadUrl()
|
url := urlsByTypeName.DownloadUrl()
|
||||||
if url == "" {
|
if url == "" {
|
||||||
return NOASSERTION
|
return "NOASSERTION"
|
||||||
}
|
}
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
@@ -303,10 +289,10 @@ func inputFiles(lg *compliance.LicenseGraph, pmix *projectmetadata.Index, licens
|
|||||||
|
|
||||||
// sbomGenerator uses the SPDX standard, see the SPDX specification (https://spdx.github.io/spdx-spec/)
|
// sbomGenerator uses the SPDX standard, see the SPDX specification (https://spdx.github.io/spdx-spec/)
|
||||||
// sbomGenerator is also following the internal google SBOM styleguide (http://goto.google.com/spdx-style-guide)
|
// sbomGenerator is also following the internal google SBOM styleguide (http://goto.google.com/spdx-style-guide)
|
||||||
func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, error) {
|
func sbomGenerator(ctx *context, files ...string) ([]string, error) {
|
||||||
// Must be at least one root file.
|
// Must be at least one root file.
|
||||||
if len(files) < 1 {
|
if len(files) < 1 {
|
||||||
return nil, nil, failNoneRequested
|
return nil, failNoneRequested
|
||||||
}
|
}
|
||||||
|
|
||||||
pmix := projectmetadata.NewIndex(ctx.rootFS)
|
pmix := projectmetadata.NewIndex(ctx.rootFS)
|
||||||
@@ -314,18 +300,9 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
|
|||||||
lg, err := compliance.ReadLicenseGraph(ctx.rootFS, ctx.stderr, files)
|
lg, err := compliance.ReadLicenseGraph(ctx.rootFS, ctx.stderr, files)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("Unable to read license text file(s) for %q: %v\n", files, err)
|
return nil, fmt.Errorf("Unable to read license text file(s) for %q: %v\n", files, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// creating the packages section
|
|
||||||
pkgs := []*spdx.Package{}
|
|
||||||
|
|
||||||
// creating the relationship section
|
|
||||||
relationships := []*spdx.Relationship{}
|
|
||||||
|
|
||||||
// creating the license section
|
|
||||||
otherLicenses := []*spdx.OtherLicense{}
|
|
||||||
|
|
||||||
// implementing the licenses references for the packages
|
// implementing the licenses references for the packages
|
||||||
licenses := make(map[string]string)
|
licenses := make(map[string]string)
|
||||||
concludedLicenses := func(licenseTexts []string) string {
|
concludedLicenses := func(licenseTexts []string) string {
|
||||||
@@ -348,6 +325,7 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
isMainPackage := true
|
isMainPackage := true
|
||||||
|
var mainPackage string
|
||||||
visitedNodes := make(map[*compliance.TargetNode]struct{})
|
visitedNodes := make(map[*compliance.TargetNode]struct{})
|
||||||
|
|
||||||
// performing a Breadth-first top down walk of licensegraph and building package information
|
// performing a Breadth-first top down walk of licensegraph and building package information
|
||||||
@@ -363,50 +341,45 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isMainPackage {
|
if isMainPackage {
|
||||||
*mainPkgName = replaceSlashes(getPackageName(ctx, tn))
|
mainPackage = getDocumentName(ctx, tn, pm)
|
||||||
|
fmt.Fprintf(ctx.stdout, "SPDXVersion: SPDX-2.2\n")
|
||||||
|
fmt.Fprintf(ctx.stdout, "DataLicense: CC0-1.0\n")
|
||||||
|
fmt.Fprintf(ctx.stdout, "DocumentName: %s\n", mainPackage)
|
||||||
|
fmt.Fprintf(ctx.stdout, "SPDXID: SPDXRef-DOCUMENT\n")
|
||||||
|
fmt.Fprintf(ctx.stdout, "DocumentNamespace: Android\n")
|
||||||
|
fmt.Fprintf(ctx.stdout, "Creator: Organization: Google LLC\n")
|
||||||
|
fmt.Fprintf(ctx.stdout, "Created: %s\n", ctx.creationTime().Format("2006-01-02T15:04:05Z"))
|
||||||
isMainPackage = false
|
isMainPackage = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(path) == 0 {
|
relationships := make([]string, 0, 1)
|
||||||
// Add the describe relationship for the main package
|
defer func() {
|
||||||
rln := &spdx.Relationship{
|
if r := recover(); r != nil {
|
||||||
RefA: common.MakeDocElementID("" /* this document */, "DOCUMENT"),
|
panic(r)
|
||||||
RefB: common.MakeDocElementID("", *mainPkgName),
|
|
||||||
Relationship: "DESCRIBES",
|
|
||||||
}
|
}
|
||||||
relationships = append(relationships, rln)
|
for _, relationship := range relationships {
|
||||||
|
fmt.Fprintln(ctx.stdout, relationship)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if len(path) == 0 {
|
||||||
|
relationships = append(relationships,
|
||||||
|
fmt.Sprintf("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-%s",
|
||||||
|
getPackageName(ctx, tn)))
|
||||||
} else {
|
} else {
|
||||||
// Check parent and identify annotation
|
// Check parent and identify annotation
|
||||||
parent := path[len(path)-1]
|
parent := path[len(path)-1]
|
||||||
targetEdge := parent.Edge()
|
targetEdge := parent.Edge()
|
||||||
if targetEdge.IsRuntimeDependency() {
|
if targetEdge.IsRuntimeDependency() {
|
||||||
// Adding the dynamic link annotation RUNTIME_DEPENDENCY_OF relationship
|
// Adding the dynamic link annotation RUNTIME_DEPENDENCY_OF relationship
|
||||||
rln := &spdx.Relationship{
|
relationships = append(relationships, fmt.Sprintf("Relationship: SPDXRef-Package-%s RUNTIME_DEPENDENCY_OF SPDXRef-Package-%s", getPackageName(ctx, tn), getPackageName(ctx, targetEdge.Target())))
|
||||||
RefA: common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, tn))),
|
|
||||||
RefB: common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, targetEdge.Target()))),
|
|
||||||
Relationship: "RUNTIME_DEPENDENCY_OF",
|
|
||||||
}
|
|
||||||
relationships = append(relationships, rln)
|
|
||||||
|
|
||||||
} else if targetEdge.IsDerivation() {
|
} else if targetEdge.IsDerivation() {
|
||||||
// Adding the derivation annotation as a CONTAINS relationship
|
// Adding the derivation annotation as a CONTAINS relationship
|
||||||
rln := &spdx.Relationship{
|
relationships = append(relationships, fmt.Sprintf("Relationship: SPDXRef-Package-%s CONTAINS SPDXRef-Package-%s", getPackageName(ctx, targetEdge.Target()), getPackageName(ctx, tn)))
|
||||||
RefA: common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, targetEdge.Target()))),
|
|
||||||
RefB: common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, tn))),
|
|
||||||
Relationship: "CONTAINS",
|
|
||||||
}
|
|
||||||
relationships = append(relationships, rln)
|
|
||||||
|
|
||||||
} else if targetEdge.IsBuildTool() {
|
} else if targetEdge.IsBuildTool() {
|
||||||
// Adding the toolchain annotation as a BUILD_TOOL_OF relationship
|
// Adding the toolchain annotation as a BUILD_TOOL_OF relationship
|
||||||
rln := &spdx.Relationship{
|
relationships = append(relationships, fmt.Sprintf("Relationship: SPDXRef-Package-%s BUILD_TOOL_OF SPDXRef-Package-%s", getPackageName(ctx, tn), getPackageName(ctx, targetEdge.Target())))
|
||||||
RefA: common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, tn))),
|
|
||||||
RefB: common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, targetEdge.Target()))),
|
|
||||||
Relationship: "BUILD_TOOL_OF",
|
|
||||||
}
|
|
||||||
relationships = append(relationships, rln)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
panic(fmt.Errorf("Unknown dependency type: %v", targetEdge.Annotations()))
|
panic(fmt.Errorf("Unknown dependency type: %v", targetEdge.Annotations()))
|
||||||
}
|
}
|
||||||
@@ -417,27 +390,18 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
|
|||||||
}
|
}
|
||||||
visitedNodes[tn] = struct{}{}
|
visitedNodes[tn] = struct{}{}
|
||||||
pkgName := getPackageName(ctx, tn)
|
pkgName := getPackageName(ctx, tn)
|
||||||
|
fmt.Fprintf(ctx.stdout, "##### Package: %s\n", strings.Replace(pkgName, "-", "/", -2))
|
||||||
// Making an spdx package and adding it to pkgs
|
fmt.Fprintf(ctx.stdout, "PackageName: %s\n", pkgName)
|
||||||
pkg := &spdx.Package{
|
|
||||||
PackageName: replaceSlashes(pkgName),
|
|
||||||
PackageDownloadLocation: getDownloadUrl(ctx, pm),
|
|
||||||
PackageSPDXIdentifier: common.ElementID(replaceSlashes(pkgName)),
|
|
||||||
PackageLicenseConcluded: concludedLicenses(tn.LicenseTexts()),
|
|
||||||
}
|
|
||||||
|
|
||||||
if pm != nil && pm.Version() != "" {
|
if pm != nil && pm.Version() != "" {
|
||||||
pkg.PackageVersion = pm.Version()
|
fmt.Fprintf(ctx.stdout, "PackageVersion: %s\n", pm.Version())
|
||||||
} else {
|
|
||||||
pkg.PackageVersion = NOASSERTION
|
|
||||||
}
|
}
|
||||||
|
fmt.Fprintf(ctx.stdout, "SPDXID: SPDXRef-Package-%s\n", pkgName)
|
||||||
pkgs = append(pkgs, pkg)
|
fmt.Fprintf(ctx.stdout, "PackageDownloadLocation: %s\n", getDownloadUrl(ctx, pm))
|
||||||
|
fmt.Fprintf(ctx.stdout, "PackageLicenseConcluded: %s\n", concludedLicenses(tn.LicenseTexts()))
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
// Adding Non-standard licenses
|
fmt.Fprintf(ctx.stdout, "##### Non-standard license:\n")
|
||||||
|
|
||||||
licenseTexts := make([]string, 0, len(licenses))
|
licenseTexts := make([]string, 0, len(licenses))
|
||||||
|
|
||||||
@@ -448,39 +412,23 @@ func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, err
|
|||||||
sort.Strings(licenseTexts)
|
sort.Strings(licenseTexts)
|
||||||
|
|
||||||
for _, licenseText := range licenseTexts {
|
for _, licenseText := range licenseTexts {
|
||||||
|
fmt.Fprintf(ctx.stdout, "LicenseID: %s\n", licenses[licenseText])
|
||||||
// open the file
|
// open the file
|
||||||
f, err := ctx.rootFS.Open(filepath.Clean(licenseText))
|
f, err := ctx.rootFS.Open(filepath.Clean(licenseText))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("error opening license text file %q: %w", licenseText, err)
|
return nil, fmt.Errorf("error opening license text file %q: %w", licenseText, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the file
|
// read the file
|
||||||
text, err := io.ReadAll(f)
|
text, err := io.ReadAll(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("error reading license text file %q: %w", licenseText, err)
|
return nil, fmt.Errorf("error reading license text file %q: %w", licenseText, err)
|
||||||
}
|
}
|
||||||
// Making an spdx License and adding it to otherLicenses
|
// adding the extracted license text
|
||||||
otherLicenses = append(otherLicenses, &spdx.OtherLicense{
|
fmt.Fprintf(ctx.stdout, "ExtractedText: <text>%v</text>\n", string(text))
|
||||||
LicenseName: strings.Replace(licenses[licenseText], "LicenseRef-", "", -1),
|
|
||||||
LicenseIdentifier: string(licenses[licenseText]),
|
|
||||||
ExtractedText: string(text),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deps := inputFiles(lg, pmix, licenseTexts)
|
deps := inputFiles(lg, pmix, licenseTexts)
|
||||||
sort.Strings(deps)
|
sort.Strings(deps)
|
||||||
|
return deps, nil
|
||||||
// Making the SPDX doc
|
|
||||||
ci, err := builder2v2.BuildCreationInfoSection2_2("Organization", "Google LLC", nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, fmt.Errorf("Unable to build creation info section for SPDX doc: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &spdx.Document{
|
|
||||||
SPDXIdentifier: "DOCUMENT",
|
|
||||||
CreationInfo: ci,
|
|
||||||
Packages: pkgs,
|
|
||||||
Relationships: relationships,
|
|
||||||
OtherLicenses: otherLicenses,
|
|
||||||
}, deps, nil
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user