forked from anchore/syft
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add SPDX JSON format object (anchore#584)
* remove existing spdxjson presenter + helpers Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add new spdx22json format Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add common sdpxhelpers (migrated) Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * use new common spdx helpers Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * wire up new spdx22json format object Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * remove lossless syft-specific property bags Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * remove spdxjson decoder and validator Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * add nil checks in spdx test helpers Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * remove empty default case Signed-off-by: Alex Goodman <alex.goodman@anchore.com> * use explicit golden snapshot Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
- Loading branch information
Showing
49 changed files
with
1,817 additions
and
888 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package spdxhelpers | ||
|
||
import "github.com/anchore/syft/syft/pkg" | ||
|
||
func Description(p *pkg.Package) string { | ||
if hasMetadata(p) { | ||
switch metadata := p.Metadata.(type) { | ||
case pkg.ApkMetadata: | ||
return metadata.Description | ||
case pkg.NpmPackageJSONMetadata: | ||
return metadata.Description | ||
} | ||
} | ||
return "" | ||
} | ||
|
||
func packageExists(p *pkg.Package) bool { | ||
return p != nil | ||
} | ||
|
||
func hasMetadata(p *pkg.Package) bool { | ||
return packageExists(p) && p.Metadata != nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package spdxhelpers | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/anchore/syft/syft/pkg" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_Description(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input pkg.Package | ||
expected string | ||
}{ | ||
{ | ||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION | ||
name: "no metadata", | ||
input: pkg.Package{}, | ||
expected: "", | ||
}, | ||
{ | ||
name: "from apk", | ||
input: pkg.Package{ | ||
Metadata: pkg.ApkMetadata{ | ||
Description: "a description!", | ||
}, | ||
}, | ||
expected: "a description!", | ||
}, | ||
{ | ||
name: "from npm", | ||
input: pkg.Package{ | ||
Metadata: pkg.NpmPackageJSONMetadata{ | ||
Description: "a description!", | ||
}, | ||
}, | ||
expected: "a description!", | ||
}, | ||
{ | ||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION | ||
name: "empty", | ||
input: pkg.Package{ | ||
Metadata: pkg.NpmPackageJSONMetadata{ | ||
Homepage: "", | ||
}, | ||
}, | ||
expected: "", | ||
}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
assert.Equal(t, test.expected, Description(&test.input)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package spdxhelpers | ||
|
||
import "github.com/anchore/syft/syft/pkg" | ||
|
||
func DownloadLocation(p *pkg.Package) string { | ||
// 3.7: Package Download Location | ||
// Cardinality: mandatory, one | ||
// NONE if there is no download location whatsoever. | ||
// NOASSERTION if: | ||
// (i) the SPDX file creator has attempted to but cannot reach a reasonable objective determination; | ||
// (ii) the SPDX file creator has made no attempt to determine this field; or | ||
// (iii) the SPDX file creator has intentionally provided no information (no meaning should be implied by doing so). | ||
|
||
if hasMetadata(p) { | ||
switch metadata := p.Metadata.(type) { | ||
case pkg.ApkMetadata: | ||
return NoneIfEmpty(metadata.URL) | ||
case pkg.NpmPackageJSONMetadata: | ||
return NoneIfEmpty(metadata.URL) | ||
} | ||
} | ||
return "NOASSERTION" | ||
} |
54 changes: 54 additions & 0 deletions
54
internal/formats/common/spdxhelpers/download_location_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package spdxhelpers | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/anchore/syft/syft/pkg" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_DownloadLocation(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input pkg.Package | ||
expected string | ||
}{ | ||
{ | ||
name: "no metadata", | ||
input: pkg.Package{}, | ||
expected: "NOASSERTION", | ||
}, | ||
{ | ||
name: "from apk", | ||
input: pkg.Package{ | ||
Metadata: pkg.ApkMetadata{ | ||
URL: "http://a-place.gov", | ||
}, | ||
}, | ||
expected: "http://a-place.gov", | ||
}, | ||
{ | ||
name: "from npm", | ||
input: pkg.Package{ | ||
Metadata: pkg.NpmPackageJSONMetadata{ | ||
URL: "http://a-place.gov", | ||
}, | ||
}, | ||
expected: "http://a-place.gov", | ||
}, | ||
{ | ||
name: "empty", | ||
input: pkg.Package{ | ||
Metadata: pkg.NpmPackageJSONMetadata{ | ||
URL: "", | ||
}, | ||
}, | ||
expected: "NONE", | ||
}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
assert.Equal(t, test.expected, DownloadLocation(&test.input)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
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) | ||
|
||
if !packageExists(p) { | ||
return externalRefs | ||
} | ||
|
||
for _, c := range p.CPEs { | ||
externalRefs = append(externalRefs, model.ExternalRef{ | ||
ReferenceCategory: model.SecurityReferenceCategory, | ||
ReferenceLocator: c.BindToFmtString(), | ||
ReferenceType: model.Cpe23ExternalRefType, | ||
}) | ||
} | ||
|
||
if p.PURL != "" { | ||
externalRefs = append(externalRefs, model.ExternalRef{ | ||
ReferenceCategory: model.PackageManagerReferenceCategory, | ||
ReferenceLocator: p.PURL, | ||
ReferenceType: model.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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package spdxhelpers | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/anchore/syft/internal/formats/spdx22json/model" | ||
"github.com/anchore/syft/syft/pkg" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_ExternalRefs(t *testing.T) { | ||
testCPE := pkg.MustCPE("cpe:2.3:a:name:name:3.2:*:*:*:*:*:*:*") | ||
tests := []struct { | ||
name string | ||
input pkg.Package | ||
expected []model.ExternalRef | ||
}{ | ||
{ | ||
name: "cpe + purl", | ||
input: pkg.Package{ | ||
CPEs: []pkg.CPE{ | ||
testCPE, | ||
}, | ||
PURL: "a-purl", | ||
}, | ||
expected: []model.ExternalRef{ | ||
{ | ||
ReferenceCategory: model.SecurityReferenceCategory, | ||
ReferenceLocator: testCPE.BindToFmtString(), | ||
ReferenceType: model.Cpe23ExternalRefType, | ||
}, | ||
{ | ||
ReferenceCategory: model.PackageManagerReferenceCategory, | ||
ReferenceLocator: "a-purl", | ||
ReferenceType: model.PurlExternalRefType, | ||
}, | ||
}, | ||
}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
assert.ElementsMatch(t, test.expected, ExternalRefs(&test.input)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package spdxhelpers | ||
|
||
import ( | ||
"crypto/sha256" | ||
"fmt" | ||
"path/filepath" | ||
|
||
"github.com/anchore/syft/internal/formats/spdx22json/model" | ||
"github.com/anchore/syft/syft/pkg" | ||
) | ||
|
||
func Files(packageSpdxID string, p *pkg.Package) (files []model.File, fileIDs []string, relationships []model.Relationship) { | ||
files = make([]model.File, 0) | ||
fileIDs = make([]string, 0) | ||
relationships = make([]model.Relationship, 0) | ||
|
||
if !hasMetadata(p) { | ||
return files, fileIDs, relationships | ||
} | ||
|
||
pkgFileOwner, ok := p.Metadata.(pkg.FileOwner) | ||
if !ok { | ||
return files, fileIDs, relationships | ||
} | ||
|
||
for _, ownedFilePath := range pkgFileOwner.OwnedFiles() { | ||
baseFileName := filepath.Base(ownedFilePath) | ||
pathHash := sha256.Sum256([]byte(ownedFilePath)) | ||
fileSpdxID := model.ElementID(fmt.Sprintf("File-%s-%x", p.Name, pathHash)).String() | ||
|
||
fileIDs = append(fileIDs, fileSpdxID) | ||
|
||
files = append(files, model.File{ | ||
FileName: ownedFilePath, | ||
Item: model.Item{ | ||
Element: model.Element{ | ||
SPDXID: fileSpdxID, | ||
Name: baseFileName, | ||
}, | ||
}, | ||
}) | ||
|
||
relationships = append(relationships, model.Relationship{ | ||
SpdxElementID: packageSpdxID, | ||
RelationshipType: model.ContainsRelationship, | ||
RelatedSpdxElement: fileSpdxID, | ||
}) | ||
} | ||
|
||
return files, fileIDs, relationships | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package spdxhelpers | ||
|
||
import "github.com/anchore/syft/syft/pkg" | ||
|
||
func Homepage(p *pkg.Package) string { | ||
if hasMetadata(p) { | ||
switch metadata := p.Metadata.(type) { | ||
case pkg.GemMetadata: | ||
return metadata.Homepage | ||
case pkg.NpmPackageJSONMetadata: | ||
return metadata.Homepage | ||
} | ||
} | ||
return "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package spdxhelpers | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/anchore/syft/syft/pkg" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_Homepage(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input pkg.Package | ||
expected string | ||
}{ | ||
{ | ||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION | ||
name: "no metadata", | ||
input: pkg.Package{}, | ||
expected: "", | ||
}, | ||
{ | ||
name: "from gem", | ||
input: pkg.Package{ | ||
Metadata: pkg.GemMetadata{ | ||
Homepage: "http://a-place.gov", | ||
}, | ||
}, | ||
expected: "http://a-place.gov", | ||
}, | ||
{ | ||
name: "from npm", | ||
input: pkg.Package{ | ||
Metadata: pkg.NpmPackageJSONMetadata{ | ||
Homepage: "http://a-place.gov", | ||
}, | ||
}, | ||
expected: "http://a-place.gov", | ||
}, | ||
{ | ||
// note: since this is an optional field, no value is preferred over NONE or NOASSERTION | ||
name: "empty", | ||
input: pkg.Package{ | ||
Metadata: pkg.NpmPackageJSONMetadata{ | ||
Homepage: "", | ||
}, | ||
}, | ||
expected: "", | ||
}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
assert.Equal(t, test.expected, Homepage(&test.input)) | ||
}) | ||
} | ||
} |
Oops, something went wrong.