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

Add SPDX 2.3 support #13

Merged
merged 9 commits into from
Jan 12, 2023
Merged
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
48 changes: 48 additions & 0 deletions examples/spdx-example.tv
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
SPDXVersion: SPDX-2.2
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: hello-src
DocumentNamespace: https://swinslow.net/spdx-examples/example2/hello-src-v3
Creator: Person: Steve Winslow ([email protected])
Creator: Tool: github.com/spdx/tools-golang/builder
Creator: Tool: github.com/spdx/tools-golang/idsearcher
Created: 2021-08-26T01:47:00Z

##### Package: hello-src

PackageName: hello-src
SPDXID: SPDXRef-Package-hello-src
PackageDownloadLocation: git+https://github.com/swinslow/spdx-examples.git#example2/content/src
FilesAnalyzed: true
PackageVerificationCode: c6cb0949d7cd7439fce8690262a0946374824639
PackageLicenseConcluded: NOASSERTION
PackageLicenseInfoFromFiles: GPL-3.0-or-later
PackageLicenseDeclared: GPL-3.0-or-later
PackageCopyrightText: NOASSERTION

Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-hello-src

FileName: /Makefile
SPDXID: SPDXRef-Makefile
FileType: SOURCE
FileChecksum: SHA1: 69a2e85696fff1865c3f0686d6c3824b59915c80
FileChecksum: SHA256: 5da19033ba058e322e21c90e6d6d859c90b1b544e7840859c12cae5da005e79c
FileChecksum: MD5: 559424589a4f3f75fd542810473d8bc1
LicenseConcluded: GPL-3.0-or-later
LicenseInfoInFile: GPL-3.0-or-later
FileCopyrightText: NOASSERTION

FileName: /hello.c
SPDXID: SPDXRef-hello-src
FileType: SOURCE
FileChecksum: SHA1: 20862a6d08391d07d09344029533ec644fac6b21
FileChecksum: SHA256: b4e5ca56d1f9110ca94ed0bf4e6d9ac11c2186eb7cd95159c6fdb50e8db5a823
FileChecksum: MD5: 935054fe899ca782e11003bbae5e166c
LicenseConcluded: GPL-3.0-or-later
LicenseInfoInFile: GPL-3.0-or-later
FileCopyrightText: Copyright Contributors to the spdx-examples project.

##### Relationships

Relationship: SPDXRef-Makefile BUILD_TOOL_OF SPDXRef-Package-hello-src

8 changes: 6 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ module opensource.ebay.com/sbom-scorecard

go 1.19

require github.com/spdx/tools-golang v0.3.1-0.20221003161519-fb7fe8874d01
require github.com/spdx/tools-golang v0.3.1-0.20221108182156-8a01147e6342

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

require (
github.com/CycloneDX/cyclonedx-go v0.7.0 // indirect
github.com/CycloneDX/cyclonedx-go v0.7.0
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.1
)
22 changes: 18 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
github.com/CycloneDX/cyclonedx-go v0.7.0 h1:jNxp8hL7UpcvPDFXjY+Y1ibFtsW+e5zyF9QoSmhK/zg=
github.com/CycloneDX/cyclonedx-go v0.7.0/go.mod h1:W5Z9w8pTTL+t+yG3PCiFRGlr8PUlE0pGWzKSJbsyXkg=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
github.com/spdx/tools-golang v0.3.0 h1:rtm+DHk3aAt74Fh0Wgucb4pCxjXV8SqHCPEb2iBd30k=
github.com/spdx/tools-golang v0.3.0/go.mod h1:RO4Y3IFROJnz+43JKm1YOrbtgQNljW4gAPpA/sY2eqo=
github.com/spdx/tools-golang v0.3.1-0.20221003161519-fb7fe8874d01 h1:HSwhIjCVoxeYkVPkUNH1l0ej8WBLgl7pNYz17vFOp/g=
github.com/spdx/tools-golang v0.3.1-0.20221003161519-fb7fe8874d01/go.mod h1:VHzvNsKAfAGqs4ZvwRL+7a0dNsL20s7lGui4K9C0xQM=
github.com/spdx/tools-golang v0.3.1-0.20221108182156-8a01147e6342 h1:6uvaOTv4GeRqQV6O1/znbpziqhctMRLTy3OGeZrNMic=
github.com/spdx/tools-golang v0.3.1-0.20221108182156-8a01147e6342/go.mod h1:VHzvNsKAfAGqs4ZvwRL+7a0dNsL20s7lGui4K9C0xQM=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
262 changes: 262 additions & 0 deletions pkg/spdx/document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
// SPDX-License-Identifier: Apache-2.0

package spdx

import (
"bytes"
"errors"
"fmt"
"io/ioutil"

spdx_json "github.com/spdx/tools-golang/json"
spdx_rdf "github.com/spdx/tools-golang/rdfloader"
spdx_tv "github.com/spdx/tools-golang/tvloader"

"github.com/spdx/tools-golang/spdx/common"
"github.com/spdx/tools-golang/spdx/v2_2"
"github.com/spdx/tools-golang/spdx/v2_3"
)

const errOpenDoc = "opening SPDX %s document: %w"

var ErrUnknownFormat = fmt.Errorf("unrecognized document format")

type Document_22 v2_2.Document
type Document_23 v2_3.Document

type Package struct {
PackageLicenseConcluded string
PackageExternalReferences []*PackageExternalReference
PackageChecksums []common.Checksum
PackageVersion string
}

type File struct {
Checksums []common.Checksum
}

func LoadDocument(path string) (Document, error) {
f, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("opening SPDX document: %w", err)
}

doc23, err := spdx_json.Load2_3(bytes.NewReader(f))
if err == nil && doc23 != nil {
return documentFromSPDX(doc23)
}
doc23, err = spdx_rdf.Load2_3(bytes.NewReader(f))
if err == nil && doc23 != nil {
return documentFromSPDX(doc23)
}
doc23, err = spdx_tv.Load2_3(bytes.NewReader(f))
if err == nil && doc23 != nil {
return documentFromSPDX(doc23)
}

doc22, err := spdx_json.Load2_2(bytes.NewReader(f))
if err == nil && doc22 != nil {
return documentFromSPDX(doc22)
}
doc22, err = spdx_rdf.Load2_2(bytes.NewReader(f))
if err == nil && doc22 != nil {
return documentFromSPDX(doc22)
}
doc22, err = spdx_tv.Load2_2(bytes.NewReader(f))
if err == nil && doc22 != nil {
return documentFromSPDX(doc22)
}

return nil, ErrUnknownFormat
}

func getFiles(doc interface{}) []File {
files := []File{}
switch castDoc := doc.(type) {
case *Document_22:
for _, of := range castDoc.Files {
f := File{Checksums: of.Checksums}
files = append(files, f)
}
case *Document_23:
for _, of := range castDoc.Files {
f := File{}
f.Checksums = of.Checksums
files = append(files, f)
}
}
return files
}

func documentFromSPDX(doc interface{}) (Document, error) {
switch castDoc := doc.(type) {
case *v2_2.Document:
d := Document_22(*castDoc)
return &d, nil
case *v2_3.Document:
d := Document_23(*castDoc)
return &d, nil
}
return nil, errors.New("unrecognized document format")
}

func (d *Document_22) Version() string {
return version(d)
}

func (d *Document_22) GetCreationInfo() *CreationInfo {
return creationInfo(d)
}

func (d *Document_23) Version() string {
return version(d)
}

func (d *Document_23) GetCreationInfo() *CreationInfo {
return creationInfo(d)
}

func NewPackage() *Package {
return &Package{}
}

func (p *Package) read22(sp *v2_2.Package) {
p.PackageExternalReferences = externalReferences(sp)
p.PackageLicenseConcluded = sp.PackageLicenseConcluded
p.PackageChecksums = sp.PackageChecksums
p.PackageVersion = sp.PackageVersion
}

func (p *Package) read23(sp *v2_3.Package) {
p.PackageExternalReferences = externalReferences(sp)
p.PackageLicenseConcluded = sp.PackageLicenseConcluded
p.PackageChecksums = sp.PackageChecksums
p.PackageVersion = sp.PackageVersion
}

func (d *Document_22) GetFiles() []File {
return getFiles(d)
}

func (d *Document_23) GetFiles() []File {
return getFiles(d)
}

func (d *Document_23) GetPackages() []Package {
packages := []Package{}
for _, p := range d.Packages {
np := Package{}
np.read23(p)
packages = append(packages, np)
}
return packages
}

func (d *Document_22) GetPackages() []Package {
packages := []Package{}
for _, p := range d.Packages {
np := Package{}
np.read22(p)
packages = append(packages, np)
}
return packages
}

type CreationInfo struct {
LicenseListVersion string
Creators []common.Creator
Created string
CreatorComment string
}

type PackageExternalReference struct {
Category string
RefType string
Locator string
ExternalRefComment string
}

type Document interface {
Version() string
GetCreationInfo() *CreationInfo
GetPackages() []Package
GetFiles() []File
}

func externalReferences(pkg interface{}) []*PackageExternalReference {
refs := []*PackageExternalReference{}
switch castPkg := pkg.(type) {
case *v2_2.Package:
if castPkg.PackageExternalReferences == nil {
return nil
}

for _, p := range castPkg.PackageExternalReferences {
refs = append(refs, &PackageExternalReference{
Category: p.Category,
RefType: p.RefType,
Locator: p.Locator,
ExternalRefComment: p.ExternalRefComment,
})
}
case *v2_3.Package:
if castPkg.PackageExternalReferences == nil {
return nil
}

for _, p := range castPkg.PackageExternalReferences {
refs = append(refs, &PackageExternalReference{
Category: p.Category,
RefType: p.RefType,
Locator: p.Locator,
ExternalRefComment: p.ExternalRefComment,
})
}
}

return refs
}

func creationInfo(doc Document) *CreationInfo {
var ci *CreationInfo
creators := []common.Creator{}

switch castDoc := doc.(type) {
case *Document_22:
if castDoc.CreationInfo == nil {
return nil
}
ci = &CreationInfo{
LicenseListVersion: castDoc.CreationInfo.LicenseListVersion,
Created: castDoc.CreationInfo.Created,
CreatorComment: castDoc.CreationInfo.CreatorComment,
}
if castDoc.CreationInfo.Creators != nil {
creators = castDoc.CreationInfo.Creators
}
case *Document_23:
if castDoc.CreationInfo == nil {
return nil
}
ci = &CreationInfo{
LicenseListVersion: castDoc.CreationInfo.LicenseListVersion,
Created: castDoc.CreationInfo.Created,
CreatorComment: castDoc.CreationInfo.CreatorComment,
}
if castDoc.CreationInfo.Creators != nil {
creators = castDoc.CreationInfo.Creators
}
}
ci.Creators = creators
return ci
}

func version(doc Document) string {
switch doc.(type) {
case *Document_22:
return "2.2"
case *Document_23:
return "2.3"
}
return ""
}
Loading