fix(sbom): use Annotation instead of AttributionTexts for SPDX formats (#7811)

This commit is contained in:
DmitriyLewen
2024-10-30 16:32:40 +06:00
committed by GitHub
parent b661d680ff
commit f2bb9c6227
6 changed files with 316 additions and 158 deletions

View File

@@ -31,10 +31,15 @@
"referenceLocator": "pkg:conda/openssl@1.1.1q"
}
],
"attributionTexts": [
"PkgType: conda-pkg"
],
"primaryPackagePurpose": "LIBRARY"
"primaryPackagePurpose": "LIBRARY",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgType: conda-pkg"
}
]
},
{
"name": "pip",
@@ -55,20 +60,30 @@
"referenceLocator": "pkg:conda/pip@22.2.2"
}
],
"attributionTexts": [
"PkgType: conda-pkg"
],
"primaryPackagePurpose": "LIBRARY"
"primaryPackagePurpose": "LIBRARY",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgType: conda-pkg"
}
]
},
{
"name": "testdata/fixtures/repo/conda",
"SPDXID": "SPDXRef-Filesystem-2e2426fd0f2580ef",
"downloadLocation": "NONE",
"filesAnalyzed": false,
"attributionTexts": [
"SchemaVersion: 2"
],
"primaryPackagePurpose": "SOURCE"
"primaryPackagePurpose": "SOURCE",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "SchemaVersion: 2"
}
]
}
],
"files": [

View File

@@ -17,11 +17,21 @@
"SPDXID": "SPDXRef-Application-18fc3597717a3e56",
"downloadLocation": "NONE",
"filesAnalyzed": false,
"attributionTexts": [
"Class: lang-pkgs",
"Type: julia"
],
"primaryPackagePurpose": "APPLICATION"
"primaryPackagePurpose": "APPLICATION",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "Class: lang-pkgs"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "Type: julia"
}
]
},
{
"name": "A",
@@ -40,11 +50,21 @@
"referenceLocator": "pkg:julia/A@1.9.0?uuid=ead4f63c-334e-11e9-00e6-e7f0a5f21b60"
}
],
"attributionTexts": [
"PkgID: ead4f63c-334e-11e9-00e6-e7f0a5f21b60",
"PkgType: julia"
],
"primaryPackagePurpose": "LIBRARY"
"primaryPackagePurpose": "LIBRARY",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgID: ead4f63c-334e-11e9-00e6-e7f0a5f21b60"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgType: julia"
}
]
},
{
"name": "B",
@@ -63,11 +83,21 @@
"referenceLocator": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24"
}
],
"attributionTexts": [
"PkgID: f41f7b98-334e-11e9-1257-49272045fb24",
"PkgType: julia"
],
"primaryPackagePurpose": "LIBRARY"
"primaryPackagePurpose": "LIBRARY",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgID: f41f7b98-334e-11e9-1257-49272045fb24"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgType: julia"
}
]
},
{
"name": "B",
@@ -86,21 +116,36 @@
"referenceLocator": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c"
}
],
"attributionTexts": [
"PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c",
"PkgType: julia"
],
"primaryPackagePurpose": "LIBRARY"
"primaryPackagePurpose": "LIBRARY",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "PkgType: julia"
}
]
},
{
"name": "testdata/fixtures/repo/julia",
"SPDXID": "SPDXRef-Filesystem-1be792dd0077c431",
"downloadLocation": "NONE",
"filesAnalyzed": false,
"attributionTexts": [
"SchemaVersion: 2"
],
"primaryPackagePurpose": "SOURCE"
"primaryPackagePurpose": "SOURCE",
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2021-08-25T12:20:30Z",
"annotationType": "OTHER",
"comment": "SchemaVersion: 2"
}
]
}
],
"relationships": [

View File

@@ -50,6 +50,8 @@ const (
PackageSupplierNoAssertion = "NOASSERTION"
PackageSupplierOrganization = "Organization"
PackageAnnotatorToolField = "Tool"
RelationShipContains = common.TypeRelationshipContains
RelationShipDescribe = common.TypeRelationshipDescribe
RelationShipDependsOn = common.TypeRelationshipDependsOn
@@ -122,6 +124,9 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document,
packages []*spdx.Package
)
// Lock time to use same time for all spdx fields
timeNow := clock.Now(ctx).UTC().Format(time.RFC3339)
root := bom.Root()
pkgDownloadLocation := m.packageDownloadLocation(root)
@@ -129,7 +134,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document,
packageIDs := make(map[uuid.UUID]spdx.ElementID)
// Root package contains OS, OS packages, language-specific packages and so on.
rootPkg, err := m.rootSPDXPackage(root, pkgDownloadLocation)
rootPkg, err := m.rootSPDXPackage(root, timeNow, pkgDownloadLocation)
if err != nil {
return nil, xerrors.Errorf("failed to generate a root package: %w", err)
}
@@ -144,7 +149,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document,
if c.Root {
continue
}
spdxPackage, err := m.spdxPackage(c, pkgDownloadLocation)
spdxPackage, err := m.spdxPackage(c, timeNow, pkgDownloadLocation)
if err != nil {
return nil, xerrors.Errorf("spdx package error: %w", err)
}
@@ -216,7 +221,7 @@ func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*spdx.Document,
CreatorType: "Tool",
},
},
Created: clock.Now(ctx).UTC().Format(time.RFC3339),
Created: timeNow,
},
Packages: packages,
Relationships: relationShips,
@@ -237,7 +242,7 @@ func (m *Marshaler) packageDownloadLocation(root *core.Component) string {
return location
}
func (m *Marshaler) rootSPDXPackage(root *core.Component, pkgDownloadLocation string) (*spdx.Package, error) {
func (m *Marshaler) rootSPDXPackage(root *core.Component, timeNow, pkgDownloadLocation string) (*spdx.Package, error) {
var externalReferences []*spdx.PackageExternalReference
// When the target is a container image, add PURL to the external references of the root package.
if root.PkgIdentifier.PURL != nil {
@@ -258,17 +263,25 @@ func (m *Marshaler) rootSPDXPackage(root *core.Component, pkgDownloadLocation st
PackageName: root.Name,
PackageSPDXIdentifier: elementID(camelCase(string(root.Type)), pkgID),
PackageDownloadLocation: pkgDownloadLocation,
PackageAttributionTexts: m.spdxAttributionTexts(root),
Annotations: m.spdxAnnotations(root, timeNow),
PackageExternalReferences: externalReferences,
PrimaryPackagePurpose: pkgPurpose,
}, nil
}
func (m *Marshaler) appendAttributionText(attributionTexts []string, key, value string) []string {
func (m *Marshaler) appendAnnotation(annotations []spdx.Annotation, timeNow, key, value string) []spdx.Annotation {
if value == "" {
return attributionTexts
return annotations
}
return append(attributionTexts, fmt.Sprintf("%s: %s", key, value))
return append(annotations, spdx.Annotation{
AnnotationDate: timeNow,
AnnotationType: spdx.CategoryOther,
Annotator: spdx.Annotator{
Annotator: fmt.Sprintf("%s-%s", CreatorTool, m.appVersion),
AnnotatorType: PackageAnnotatorToolField,
},
AnnotationComment: fmt.Sprintf("%s: %s", key, value),
})
}
func (m *Marshaler) purlExternalReference(packageURL string) *spdx.PackageExternalReference {
@@ -287,7 +300,7 @@ func (m *Marshaler) advisoryExternalReference(primaryURL string) *spdx.PackageEx
}
}
func (m *Marshaler) spdxPackage(c *core.Component, pkgDownloadLocation string) (spdx.Package, error) {
func (m *Marshaler) spdxPackage(c *core.Component, timeNow, pkgDownloadLocation string) (spdx.Package, error) {
pkgID, err := calcPkgID(m.hasher, c)
if err != nil {
return spdx.Package{}, xerrors.Errorf("failed to get os metadata package ID: %w", err)
@@ -343,7 +356,7 @@ func (m *Marshaler) spdxPackage(c *core.Component, pkgDownloadLocation string) (
PrimaryPackagePurpose: purpose,
PackageDownloadLocation: pkgDownloadLocation,
PackageExternalReferences: pkgExtRefs,
PackageAttributionTexts: m.spdxAttributionTexts(c),
Annotations: m.spdxAnnotations(c, timeNow),
PackageSourceInfo: sourceInfo,
PackageSupplier: supplier,
PackageChecksums: m.spdxChecksums(digests),
@@ -365,16 +378,15 @@ func spdxPkgName(component *core.Component) string {
}
return component.Name
}
func (m *Marshaler) spdxAttributionTexts(c *core.Component) []string {
var texts []string
func (m *Marshaler) spdxAnnotations(c *core.Component, timeNow string) []spdx.Annotation {
var annotations []spdx.Annotation
for _, p := range c.Properties {
// Add properties that are not in other fields.
if !slices.Contains(duplicateProperties, p.Name) {
texts = m.appendAttributionText(texts, p.Name, p.Value)
annotations = m.appendAnnotation(annotations, timeNow, p.Name, p.Value)
}
}
return texts
return annotations
}
func (m *Marshaler) spdxLicense(c *core.Component) string {

View File

@@ -25,6 +25,20 @@ import (
"github.com/aquasecurity/trivy/pkg/uuid"
)
func annotation(t *testing.T, comment string) spdx.Annotation {
t.Helper()
return spdx.Annotation{
AnnotationDate: "2021-08-25T12:20:30Z",
AnnotationType: spdx.CategoryOther,
Annotator: spdx.Annotator{
Annotator: "trivy-0.56.2",
AnnotatorType: tspdx.PackageAnnotatorToolField,
},
AnnotationComment: comment,
}
}
func TestMarshaler_Marshal(t *testing.T) {
testCases := []struct {
name string
@@ -164,7 +178,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -176,9 +190,9 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageDownloadLocation: "NONE",
PackageName: "app/Gemfile.lock",
PrimaryPackagePurpose: tspdx.PackagePurposeApplication,
PackageAttributionTexts: []string{
"Class: lang-pkgs",
"Type: bundler",
Annotations: []spdx.Annotation{
annotation(t, "Class: lang-pkgs"),
annotation(t, "Type: bundler"),
},
},
{
@@ -186,9 +200,9 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageDownloadLocation: "NONE",
PackageName: "app/subproject/Gemfile.lock",
PrimaryPackagePurpose: tspdx.PackagePurposeApplication,
PackageAttributionTexts: []string{
"Class: lang-pkgs",
"Type: bundler",
Annotations: []spdx.Annotation{
annotation(t, "Class: lang-pkgs"),
annotation(t, "Type: bundler"),
},
},
{
@@ -202,14 +216,14 @@ func TestMarshaler_Marshal(t *testing.T) {
Locator: "pkg:oci/rails@sha256%3Aa27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?arch=arm64&repository_url=index.docker.io%2Flibrary%2Frails",
},
},
PackageAttributionTexts: []string{
"DiffID: sha256:d871dadfb37b53ef1ca45be04fc527562b91989991a8f545345ae3be0b93f92a",
"ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"Labels:vendor: aquasecurity",
"RepoDigest: rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177",
"RepoTag: rails:latest",
"SchemaVersion: 2",
"Size: 1024",
Annotations: []spdx.Annotation{
annotation(t, "DiffID: sha256:d871dadfb37b53ef1ca45be04fc527562b91989991a8f545345ae3be0b93f92a"),
annotation(t, "ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6"),
annotation(t, "Labels:vendor: aquasecurity"),
annotation(t, "RepoDigest: rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177"),
annotation(t, "RepoTag: rails:latest"),
annotation(t, "SchemaVersion: 2"),
annotation(t, "Size: 1024"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeContainer,
},
@@ -220,8 +234,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageVersion: "7.0.1",
PackageLicenseConcluded: "NOASSERTION",
PackageLicenseDeclared: "NOASSERTION",
PackageAttributionTexts: []string{
"PkgType: bundler",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: bundler"),
},
PackageExternalReferences: []*spdx.PackageExternalReference{
{
@@ -241,8 +255,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageVersion: "7.0.1",
PackageLicenseConcluded: "NOASSERTION",
PackageLicenseDeclared: "NOASSERTION",
PackageAttributionTexts: []string{
"PkgType: bundler",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: bundler"),
},
PackageExternalReferences: []*spdx.PackageExternalReference{
{
@@ -262,8 +276,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageVersion: "7.0.1",
PackageLicenseConcluded: "NOASSERTION",
PackageLicenseDeclared: "NOASSERTION",
PackageAttributionTexts: []string{
"PkgType: bundler",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: bundler"),
},
PackageExternalReferences: []*spdx.PackageExternalReference{
{
@@ -283,8 +297,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageVersion: "2.30-93.el8",
PackageLicenseConcluded: "GPL-3.0-or-later",
PackageLicenseDeclared: "GPL-3.0-or-later",
PackageAttributionTexts: []string{
"PkgType: centos",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: centos"),
},
PackageSupplier: &spdx.Supplier{
SupplierType: tspdx.PackageSupplierOrganization,
@@ -312,9 +326,9 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageName: "centos",
PackageVersion: "8.3.2011",
PrimaryPackagePurpose: tspdx.PackagePurposeOS,
PackageAttributionTexts: []string{
"Class: os-pkgs",
"Type: centos",
Annotations: []spdx.Annotation{
annotation(t, "Class: os-pkgs"),
annotation(t, "Type: centos"),
},
},
},
@@ -486,7 +500,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -497,11 +511,11 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageName: "centos:latest",
PackageSPDXIdentifier: "ContainerImage-413bfede37ad01fc",
PackageDownloadLocation: "NONE",
PackageAttributionTexts: []string{
"ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
"RepoTag: centos:latest",
"SchemaVersion: 2",
"Size: 1024",
Annotations: []spdx.Annotation{
annotation(t, "ImageID: sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6"),
annotation(t, "RepoTag: centos:latest"),
annotation(t, "SchemaVersion: 2"),
annotation(t, "Size: 1024"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeContainer,
},
@@ -512,8 +526,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageVersion: "1:2.2.53-1.el8",
PackageLicenseConcluded: "GPL-2.0-or-later",
PackageLicenseDeclared: "GPL-2.0-or-later",
PackageAttributionTexts: []string{
"PkgType: centos",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: centos"),
},
PackageExternalReferences: []*spdx.PackageExternalReference{
{
@@ -546,9 +560,9 @@ func TestMarshaler_Marshal(t *testing.T) {
Locator: "pkg:gem/actionpack@7.0.1",
},
},
PackageAttributionTexts: []string{
"LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488",
"PkgType: gemspec",
Annotations: []spdx.Annotation{
annotation(t, "LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488"),
annotation(t, "PkgType: gemspec"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
@@ -571,9 +585,9 @@ func TestMarshaler_Marshal(t *testing.T) {
Locator: "pkg:gem/actionpack@7.0.1",
},
},
PackageAttributionTexts: []string{
"LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488",
"PkgType: gemspec",
Annotations: []spdx.Annotation{
annotation(t, "LayerDiffID: sha256:ccb64cf0b7ba2e50741d0b64cae324eb5de3b1e2f580bbf177e721b67df38488"),
annotation(t, "PkgType: gemspec"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
@@ -588,9 +602,9 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageName: "centos",
PackageVersion: "8.3.2011",
PrimaryPackagePurpose: tspdx.PackagePurposeOS,
PackageAttributionTexts: []string{
"Class: os-pkgs",
"Type: centos",
Annotations: []spdx.Annotation{
annotation(t, "Class: os-pkgs"),
annotation(t, "Type: centos"),
},
},
},
@@ -719,7 +733,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -731,9 +745,9 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageDownloadLocation: "NONE",
PackageName: "Gemfile.lock",
PrimaryPackagePurpose: tspdx.PackagePurposeApplication,
PackageAttributionTexts: []string{
"Class: lang-pkgs",
"Type: bundler",
Annotations: []spdx.Annotation{
annotation(t, "Class: lang-pkgs"),
annotation(t, "Type: bundler"),
},
},
{
@@ -741,9 +755,9 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageDownloadLocation: "NONE",
PackageName: "pom.xml",
PrimaryPackagePurpose: tspdx.PackagePurposeApplication,
PackageAttributionTexts: []string{
"Class: lang-pkgs",
"Type: pom",
Annotations: []spdx.Annotation{
annotation(t, "Class: lang-pkgs"),
annotation(t, "Type: pom"),
},
},
{
@@ -763,8 +777,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
PackageSourceInfo: "package found in: Gemfile.lock",
PackageAttributionTexts: []string{
"PkgType: bundler",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: bundler"),
},
},
{
@@ -784,17 +798,17 @@ func TestMarshaler_Marshal(t *testing.T) {
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
PackageSourceInfo: "package found in: pom.xml",
PackageAttributionTexts: []string{
"PkgID: com.example:example:1.0.0",
"PkgType: pom",
Annotations: []spdx.Annotation{
annotation(t, "PkgID: com.example:example:1.0.0"),
annotation(t, "PkgType: pom"),
},
},
{
PackageSPDXIdentifier: spdx.ElementID("Filesystem-5af0f1f08c20909a"),
PackageDownloadLocation: "NONE",
PackageName: "masahiro331/CVE-2021-41098",
PackageAttributionTexts: []string{
"SchemaVersion: 2",
Annotations: []spdx.Annotation{
annotation(t, "SchemaVersion: 2"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeSource,
},
@@ -878,7 +892,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -906,16 +920,16 @@ func TestMarshaler_Marshal(t *testing.T) {
},
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
PackageAttributionTexts: []string{
"PkgType: jar",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: jar"),
},
},
{
PackageSPDXIdentifier: spdx.ElementID("Filesystem-121e7e7a43f02ab"),
PackageDownloadLocation: "NONE",
PackageName: "log4j-core-2.17.0.jar",
PackageAttributionTexts: []string{
"SchemaVersion: 2",
Annotations: []spdx.Annotation{
annotation(t, "SchemaVersion: 2"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeSource,
},
@@ -980,7 +994,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -1001,9 +1015,9 @@ func TestMarshaler_Marshal(t *testing.T) {
Locator: "pkg:npm/ruby-typeprof@0.20.1",
},
},
PackageAttributionTexts: []string{
"LayerDiffID: sha256:661c3fd3cc16b34c070f3620ca6b03b6adac150f9a7e5d0e3c707a159990f88e",
"PkgType: node-pkg",
Annotations: []spdx.Annotation{
annotation(t, "LayerDiffID: sha256:661c3fd3cc16b34c070f3620ca6b03b6adac150f9a7e5d0e3c707a159990f88e"),
annotation(t, "PkgType: node-pkg"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
@@ -1016,8 +1030,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageSPDXIdentifier: "Repository-1a78857c1a6a759e",
PackageName: "http://test-aggregate",
PackageDownloadLocation: "git+http://test-aggregate",
PackageAttributionTexts: []string{
"SchemaVersion: 2",
Annotations: []spdx.Annotation{
annotation(t, "SchemaVersion: 2"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeSource,
},
@@ -1075,7 +1089,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -1086,8 +1100,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageName: "empty/path",
PackageSPDXIdentifier: "Filesystem-70f34983067dba86",
PackageDownloadLocation: "NONE",
PackageAttributionTexts: []string{
"SchemaVersion: 2",
Annotations: []spdx.Annotation{
annotation(t, "SchemaVersion: 2"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeSource,
},
@@ -1137,7 +1151,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -1148,8 +1162,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageName: "secret",
PackageSPDXIdentifier: "Filesystem-5c08d34162a2c5d3",
PackageDownloadLocation: "NONE",
PackageAttributionTexts: []string{
"SchemaVersion: 2",
Annotations: []spdx.Annotation{
annotation(t, "SchemaVersion: 2"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeSource,
},
@@ -1209,7 +1223,7 @@ func TestMarshaler_Marshal(t *testing.T) {
CreatorType: "Organization",
},
{
Creator: "trivy-0.38.1",
Creator: "trivy-0.56.2",
CreatorType: "Tool",
},
},
@@ -1221,9 +1235,9 @@ func TestMarshaler_Marshal(t *testing.T) {
PackageDownloadLocation: "NONE",
PackageName: "/usr/local/bin/test",
PrimaryPackagePurpose: tspdx.PackagePurposeApplication,
PackageAttributionTexts: []string{
"Class: lang-pkgs",
"Type: gobinary",
Annotations: []spdx.Annotation{
annotation(t, "Class: lang-pkgs"),
annotation(t, "Type: gobinary"),
},
},
{
@@ -1235,8 +1249,8 @@ func TestMarshaler_Marshal(t *testing.T) {
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
PackageSourceInfo: "package found in: /usr/local/bin/test",
PackageAttributionTexts: []string{
"PkgType: gobinary",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: gobinary"),
},
},
{
@@ -1256,16 +1270,16 @@ func TestMarshaler_Marshal(t *testing.T) {
PrimaryPackagePurpose: tspdx.PackagePurposeLibrary,
PackageSupplier: &spdx.Supplier{Supplier: tspdx.PackageSupplierNoAssertion},
PackageSourceInfo: "package found in: /usr/local/bin/test",
PackageAttributionTexts: []string{
"PkgType: gobinary",
Annotations: []spdx.Annotation{
annotation(t, "PkgType: gobinary"),
},
},
{
PackageName: "go-artifact",
PackageSPDXIdentifier: "Filesystem-e340f27468b382be",
PackageDownloadLocation: "NONE",
PackageAttributionTexts: []string{
"SchemaVersion: 2",
Annotations: []spdx.Annotation{
annotation(t, "SchemaVersion: 2"),
},
PrimaryPackagePurpose: tspdx.PackagePurposeSource,
},
@@ -1326,7 +1340,7 @@ func TestMarshaler_Marshal(t *testing.T) {
ctx := clock.With(context.Background(), time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))
uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d")
marshaler := tspdx.NewMarshaler("0.38.1", tspdx.WithHasher(hasher))
marshaler := tspdx.NewMarshaler("0.56.2", tspdx.WithHasher(hasher))
spdxDoc, err := marshaler.MarshalReport(ctx, tc.inputReport)
require.NoError(t, err)

View File

@@ -37,13 +37,43 @@
},
{
"SPDXID": "SPDXRef-ContainerImage-b5d81cde5f95c8fc",
"attributionTexts": [
"SchemaVersion: 2",
"ImageID: sha256:49193a2310dbad4c02382da87ac624a80a92387a4f7536235f9ba590e5bcd7b5",
"DiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3",
"DiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1",
"RepoTag: maven-test-project:latest",
"RepoTag: tmp-test:latest"
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "SchemaVersion: 2"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "ImageID: sha256:49193a2310dbad4c02382da87ac624a80a92387a4f7536235f9ba590e5bcd7b5"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "DiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "DiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "RepoTag: maven-test-project:latest"
},
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "RepoTag: tmp-test:latest"
}
],
"filesAnalyzed": false,
"name": "meven-test-project"
@@ -56,8 +86,13 @@
},
{
"SPDXID": "SPDXRef-Package-2906575950df652b",
"attributionTexts": [
"LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
}
],
"externalRefs": [
{
@@ -74,8 +109,13 @@
},
{
"SPDXID": "SPDXRef-Package-2a53baa495b9ddaf",
"attributionTexts": [
"LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
}
],
"externalRefs": [
{
@@ -92,8 +132,13 @@
},
{
"SPDXID": "SPDXRef-Package-5e2e255ac76747ef",
"attributionTexts": [
"LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
}
],
"externalRefs": [
{
@@ -110,8 +155,13 @@
},
{
"SPDXID": "SPDXRef-Package-5f1dbaff8de5eb06",
"attributionTexts": [
"LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
}
],
"externalRefs": [
{
@@ -128,8 +178,13 @@
},
{
"SPDXID": "SPDXRef-Package-84ebffe38343d949",
"attributionTexts": [
"LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "LayerDiffID: sha256:3c79e832b1b4891a1cb4a326ef8524e0bd14a2537150ac0e203a5677176c1ca1"
}
],
"externalRefs": [
{
@@ -146,8 +201,13 @@
},
{
"SPDXID": "SPDXRef-Package-b7ebaf0233f1ef7b",
"attributionTexts": [
"LayerDiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3"
"annotations": [
{
"annotator": "Tool: trivy-dev",
"annotationDate": "2024-10-29T06:50:38Z",
"annotationType": "OTHER",
"comment": "LayerDiffID: sha256:dd565ff850e7003356e2b252758f9bdc1ff2803f61e995e24c7844f6297f8fc3"
}
],
"externalRefs": [
{

View File

@@ -194,9 +194,21 @@ func (s *SPDX) parsePackage(spdxPkg spdx.Package) (*core.Component, error) {
}
}
// Attributions
for _, attr := range spdxPkg.PackageAttributionTexts {
k, v, ok := strings.Cut(attr, ": ")
// Trivy stores properties in Annotations
// But previous versions stored properties in AttributionTexts
// So we need to check both cases to maintain backward compatibility
var props []string
if len(spdxPkg.Annotations) > 0 {
for _, annotation := range spdxPkg.Annotations {
props = append(props, annotation.AnnotationComment)
}
} else if len(spdxPkg.PackageAttributionTexts) > 0 {
for _, attr := range spdxPkg.PackageAttributionTexts {
props = append(props, attr)
}
}
for _, prop := range props {
k, v, ok := strings.Cut(prop, ": ")
if !ok {
continue
}