Skip to content

Commit

Permalink
Suport SPDX SBOM decoding (anchore#738)
Browse files Browse the repository at this point in the history
  • Loading branch information
kzantow committed Feb 9, 2022
1 parent 46baf11 commit fae760f
Show file tree
Hide file tree
Showing 46 changed files with 1,679 additions and 297 deletions.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -35,7 +35,7 @@ require (
github.com/scylladb/go-set v1.0.2
github.com/sergi/go-diff v1.1.0
github.com/sirupsen/logrus v1.8.1
github.com/spdx/tools-golang v0.1.0
github.com/spdx/tools-golang v0.2.0
github.com/spf13/afero v1.6.0
github.com/spf13/cobra v1.2.1
github.com/spf13/pflag v1.0.5
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -759,8 +759,8 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
github.com/spdx/tools-golang v0.1.0 h1:iDMNEPqQk6CdiDj6eWDIDw85j0wQ3IR3pH9p0X05TSQ=
github.com/spdx/tools-golang v0.1.0/go.mod h1:RO4Y3IFROJnz+43JKm1YOrbtgQNljW4gAPpA/sY2eqo=
github.com/spdx/tools-golang v0.2.0 h1:KBNcw7xvVycRWeCWZK/5xQJA+plymW1+rTCs8ekJDro=
github.com/spdx/tools-golang v0.2.0/go.mod h1:RO4Y3IFROJnz+43JKm1YOrbtgQNljW4gAPpA/sY2eqo=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
Expand Down
5 changes: 4 additions & 1 deletion internal/formats/common/spdxhelpers/download_location.go
Expand Up @@ -2,6 +2,9 @@ package spdxhelpers

import "github.com/anchore/syft/syft/pkg"

const NONE = "NONE"
const NOASSERTION = "NOASSERTION"

func DownloadLocation(p pkg.Package) string {
// 3.7: Package Download Location
// Cardinality: mandatory, one
Expand All @@ -19,5 +22,5 @@ func DownloadLocation(p pkg.Package) string {
return NoneIfEmpty(metadata.URL)
}
}
return "NOASSERTION"
return NOASSERTION
}
4 changes: 2 additions & 2 deletions internal/formats/common/spdxhelpers/download_location_test.go
Expand Up @@ -16,7 +16,7 @@ func Test_DownloadLocation(t *testing.T) {
{
name: "no metadata",
input: pkg.Package{},
expected: "NOASSERTION",
expected: NOASSERTION,
},
{
name: "from apk",
Expand All @@ -43,7 +43,7 @@ func Test_DownloadLocation(t *testing.T) {
URL: "",
},
},
expected: "NONE",
expected: NONE,
},
}
for _, test := range tests {
Expand Down
@@ -1,4 +1,4 @@
package model
package spdxhelpers

type ReferenceCategory string

Expand Down
41 changes: 8 additions & 33 deletions internal/formats/common/spdxhelpers/external_refs.go
@@ -1,51 +1,26 @@
package spdxhelpers

import (
"github.com/anchore/syft/internal/formats/spdx22json/model"
"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/pkg"
)

func ExternalRefs(p pkg.Package) (externalRefs []model.ExternalRef) {
externalRefs = make([]model.ExternalRef, 0)
func ExternalRefs(p pkg.Package) (externalRefs []ExternalRef) {
externalRefs = make([]ExternalRef, 0)

for _, c := range p.CPEs {
externalRefs = append(externalRefs, model.ExternalRef{
ReferenceCategory: model.SecurityReferenceCategory,
externalRefs = append(externalRefs, ExternalRef{
ReferenceCategory: SecurityReferenceCategory,
ReferenceLocator: pkg.CPEString(c),
ReferenceType: model.Cpe23ExternalRefType,
ReferenceType: Cpe23ExternalRefType,
})
}

if p.PURL != "" {
externalRefs = append(externalRefs, model.ExternalRef{
ReferenceCategory: model.PackageManagerReferenceCategory,
externalRefs = append(externalRefs, ExternalRef{
ReferenceCategory: PackageManagerReferenceCategory,
ReferenceLocator: p.PURL,
ReferenceType: model.PurlExternalRefType,
ReferenceType: PurlExternalRefType,
})
}
return externalRefs
}

func ExtractPURL(refs []model.ExternalRef) string {
for _, r := range refs {
if r.ReferenceType == model.PurlExternalRefType {
return r.ReferenceLocator
}
}
return ""
}

func ExtractCPEs(refs []model.ExternalRef) (cpes []pkg.CPE) {
for _, r := range refs {
if r.ReferenceType == model.Cpe23ExternalRefType {
cpe, err := pkg.NewCPE(r.ReferenceLocator)
if err != nil {
log.Warnf("unable to extract SPDX CPE=%q: %+v", r.ReferenceLocator, err)
continue
}
cpes = append(cpes, cpe)
}
}
return cpes
}
13 changes: 6 additions & 7 deletions internal/formats/common/spdxhelpers/external_refs_test.go
Expand Up @@ -3,7 +3,6 @@ package spdxhelpers
import (
"testing"

"github.com/anchore/syft/internal/formats/spdx22json/model"
"github.com/anchore/syft/syft/pkg"
"github.com/stretchr/testify/assert"
)
Expand All @@ -13,7 +12,7 @@ func Test_ExternalRefs(t *testing.T) {
tests := []struct {
name string
input pkg.Package
expected []model.ExternalRef
expected []ExternalRef
}{
{
name: "cpe + purl",
Expand All @@ -23,16 +22,16 @@ func Test_ExternalRefs(t *testing.T) {
},
PURL: "a-purl",
},
expected: []model.ExternalRef{
expected: []ExternalRef{
{
ReferenceCategory: model.SecurityReferenceCategory,
ReferenceCategory: SecurityReferenceCategory,
ReferenceLocator: pkg.CPEString(testCPE),
ReferenceType: model.Cpe23ExternalRefType,
ReferenceType: Cpe23ExternalRefType,
},
{
ReferenceCategory: model.PackageManagerReferenceCategory,
ReferenceCategory: PackageManagerReferenceCategory,
ReferenceLocator: "a-purl",
ReferenceType: model.PurlExternalRefType,
ReferenceType: PurlExternalRefType,
},
},
},
Expand Down
17 changes: 17 additions & 0 deletions internal/formats/common/spdxhelpers/file_type.go
@@ -0,0 +1,17 @@
package spdxhelpers

type FileType string

const (
DocumentationFileType FileType = "DOCUMENTATION" // if the file serves as documentation
ImageFileType FileType = "IMAGE" // if the file is associated with a picture image file (MIME type of image/*, e.g., .jpg, .gif)
VideoFileType FileType = "VIDEO" // if the file is associated with a video file type (MIME type of video/*)
ArchiveFileType FileType = "ARCHIVE" // if the file represents an archive (.tar, .jar, etc.)
SpdxFileType FileType = "SPDX" // if the file is an SPDX document
ApplicationFileType FileType = "APPLICATION" // if the file is associated with a specific application type (MIME type of application/*)
SourceFileType FileType = "SOURCE" // if the file is human readable source code (.c, .html, etc.)
BinaryFileType FileType = "BINARY" // if the file is a compiled object, target image or binary executable (.o, .a, etc.)
TextFileType FileType = "TEXT" // if the file is human readable text file (MIME type of text/*)
AudioFileType FileType = "AUDIO" // if the file is associated with an audio file (MIME type of audio/* , e.g. .mp3)
OtherFileType FileType = "OTHER" // if the file doesn't fit into the above categories (generated artifacts, data files, etc.)
)
4 changes: 2 additions & 2 deletions internal/formats/common/spdxhelpers/license.go
Expand Up @@ -18,7 +18,7 @@ func License(p pkg.Package) string {
// (iii) the SPDX file creator has intentionally provided no information (no meaning should be implied by doing so).

if len(p.Licenses) == 0 {
return "NONE"
return NONE
}

// take all licenses and assume an AND expression; for information about license expressions see https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/
Expand All @@ -30,7 +30,7 @@ func License(p pkg.Package) string {
}

if len(parsedLicenses) == 0 {
return "NOASSERTION"
return NOASSERTION
}

return strings.Join(parsedLicenses, " AND ")
Expand Down
4 changes: 2 additions & 2 deletions internal/formats/common/spdxhelpers/license_test.go
Expand Up @@ -16,7 +16,7 @@ func Test_License(t *testing.T) {
{
name: "no licenses",
input: pkg.Package{},
expected: "NONE",
expected: NONE,
},
{
name: "no SPDX licenses",
Expand All @@ -25,7 +25,7 @@ func Test_License(t *testing.T) {
"made-up",
},
},
expected: "NOASSERTION",
expected: NOASSERTION,
},
{
name: "with SPDX license",
Expand Down
2 changes: 1 addition & 1 deletion internal/formats/common/spdxhelpers/none_if_empty.go
Expand Up @@ -6,7 +6,7 @@ import (

func NoneIfEmpty(value string) string {
if strings.TrimSpace(value) == "" {
return "NONE"
return NONE
}
return value
}
6 changes: 3 additions & 3 deletions internal/formats/common/spdxhelpers/none_if_empty_test.go
Expand Up @@ -20,17 +20,17 @@ func Test_noneIfEmpty(t *testing.T) {
{
name: "empty",
value: "",
expected: "NONE",
expected: NONE,
},
{
name: "space",
value: " ",
expected: "NONE",
expected: NONE,
},
{
name: "tab",
value: "\t",
expected: "NONE",
expected: NONE,
},
}
for _, test := range tests {
Expand Down

0 comments on commit fae760f

Please sign in to comment.