Skip to content

Commit

Permalink
feat(vex): support non-root components for products in OpenVEX (#6728)
Browse files Browse the repository at this point in the history
Signed-off-by: knqyf263 <knqyf263@gmail.com>
Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
  • Loading branch information
knqyf263 and DmitriyLewen authored May 21, 2024
1 parent 2bc54ad commit 9515695
Show file tree
Hide file tree
Showing 13 changed files with 393 additions and 114 deletions.
12 changes: 6 additions & 6 deletions integration/testdata/conda-spdx.json.golden
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"packages": [
{
"name": "openssl",
"SPDXID": "SPDXRef-Package-32b6b37a6fa2e57f",
"SPDXID": "SPDXRef-Package-22a178da112ac20a",
"versionInfo": "1.1.1q",
"supplier": "NOASSERTION",
"downloadLocation": "NONE",
Expand All @@ -38,7 +38,7 @@
},
{
"name": "pip",
"SPDXID": "SPDXRef-Package-e260029d0b6fd07b",
"SPDXID": "SPDXRef-Package-c22b9ee9a601ba6",
"versionInfo": "22.2.2",
"supplier": "NOASSERTION",
"downloadLocation": "NONE",
Expand Down Expand Up @@ -103,21 +103,21 @@
},
{
"spdxElementId": "SPDXRef-Filesystem-2e2426fd0f2580ef",
"relatedSpdxElement": "SPDXRef-Package-32b6b37a6fa2e57f",
"relatedSpdxElement": "SPDXRef-Package-22a178da112ac20a",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Filesystem-2e2426fd0f2580ef",
"relatedSpdxElement": "SPDXRef-Package-e260029d0b6fd07b",
"relatedSpdxElement": "SPDXRef-Package-c22b9ee9a601ba6",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-32b6b37a6fa2e57f",
"spdxElementId": "SPDXRef-Package-22a178da112ac20a",
"relatedSpdxElement": "SPDXRef-File-600e5e0110a84891",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-e260029d0b6fd07b",
"spdxElementId": "SPDXRef-Package-c22b9ee9a601ba6",
"relatedSpdxElement": "SPDXRef-File-7eb62e2a3edddc0a",
"relationshipType": "CONTAINS"
}
Expand Down
24 changes: 12 additions & 12 deletions integration/testdata/julia-spdx.json.golden
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
},
{
"name": "A",
"SPDXID": "SPDXRef-Package-2a46714189f3b9de",
"SPDXID": "SPDXRef-Package-7784b00da0cb0cb0",
"versionInfo": "1.9.0",
"supplier": "NOASSERTION",
"downloadLocation": "NONE",
Expand All @@ -48,7 +48,7 @@
},
{
"name": "B",
"SPDXID": "SPDXRef-Package-4a8e351c4c9b7318",
"SPDXID": "SPDXRef-Package-960543ac5c5f7e10",
"versionInfo": "1.9.0",
"supplier": "NOASSERTION",
"downloadLocation": "NONE",
Expand All @@ -60,18 +60,18 @@
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c"
"referenceLocator": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24"
}
],
"attributionTexts": [
"PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c",
"PkgID: f41f7b98-334e-11e9-1257-49272045fb24",
"PkgType: julia"
],
"primaryPackagePurpose": "LIBRARY"
},
{
"name": "B",
"SPDXID": "SPDXRef-Package-d10d5e4a30a43fff",
"SPDXID": "SPDXRef-Package-a4705eb108e4f15c",
"versionInfo": "1.9.0",
"supplier": "NOASSERTION",
"downloadLocation": "NONE",
Expand All @@ -83,11 +83,11 @@
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:julia/B@1.9.0?uuid=f41f7b98-334e-11e9-1257-49272045fb24"
"referenceLocator": "pkg:julia/B@1.9.0?uuid=edca9bc6-334e-11e9-3554-9595dbb4349c"
}
],
"attributionTexts": [
"PkgID: f41f7b98-334e-11e9-1257-49272045fb24",
"PkgID: edca9bc6-334e-11e9-3554-9595dbb4349c",
"PkgType: julia"
],
"primaryPackagePurpose": "LIBRARY"
Expand All @@ -106,17 +106,17 @@
"relationships": [
{
"spdxElementId": "SPDXRef-Application-18fc3597717a3e56",
"relatedSpdxElement": "SPDXRef-Package-2a46714189f3b9de",
"relatedSpdxElement": "SPDXRef-Package-7784b00da0cb0cb0",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Application-18fc3597717a3e56",
"relatedSpdxElement": "SPDXRef-Package-4a8e351c4c9b7318",
"relatedSpdxElement": "SPDXRef-Package-960543ac5c5f7e10",
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Application-18fc3597717a3e56",
"relatedSpdxElement": "SPDXRef-Package-d10d5e4a30a43fff",
"relatedSpdxElement": "SPDXRef-Package-a4705eb108e4f15c",
"relationshipType": "CONTAINS"
},
{
Expand All @@ -130,8 +130,8 @@
"relationshipType": "CONTAINS"
},
{
"spdxElementId": "SPDXRef-Package-2a46714189f3b9de",
"relatedSpdxElement": "SPDXRef-Package-d10d5e4a30a43fff",
"spdxElementId": "SPDXRef-Package-7784b00da0cb0cb0",
"relatedSpdxElement": "SPDXRef-Package-960543ac5c5f7e10",
"relationshipType": "DEPENDS_ON"
}
]
Expand Down
2 changes: 1 addition & 1 deletion pkg/fanal/applier/applier_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package applier_test

import (
"github.com/package-url/packageurl-go"
"sort"
"testing"

"github.com/package-url/packageurl-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand Down
2 changes: 1 addition & 1 deletion pkg/result/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func filterByVEX(report types.Report, opt FilterOption) error {
return nil
}

bom, err := sbomio.NewEncoder(core.Options{}).Encode(report)
bom, err := sbomio.NewEncoder(core.Options{Parents: true}).Encode(report)
if err != nil {
return xerrors.Errorf("unable to encode the SBOM: %w", err)
}
Expand Down
56 changes: 39 additions & 17 deletions pkg/result/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package result_test

import (
"context"
"github.com/aquasecurity/trivy/pkg/fanal/artifact"
"github.com/package-url/packageurl-go"
"testing"
"time"
Expand All @@ -18,36 +19,42 @@ import (

func TestFilter(t *testing.T) {
var (
vuln1 = types.DetectedVulnerability{
VulnerabilityID: "CVE-2019-0001",
PkgName: "foo",
PkgIdentifier: ftypes.PkgIdentifier{
pkg1 = ftypes.Package{
ID: "foo@1.2.3",
Name: "foo",
Version: "1.2.3",
Identifier: ftypes.PkgIdentifier{
UID: "01",
PURL: &packageurl.PackageURL{
Type: packageurl.TypeGolang,
Namespace: "github.com/aquasecurity",
Name: "foo",
Version: "1.2.3",
},
},
InstalledVersion: "1.2.3",
}
vuln1 = types.DetectedVulnerability{
VulnerabilityID: "CVE-2019-0001",
PkgName: pkg1.Name,
InstalledVersion: pkg1.Version,
FixedVersion: "1.2.4",
PkgIdentifier: ftypes.PkgIdentifier{
UID: pkg1.Identifier.UID,
PURL: pkg1.Identifier.PURL,
},
Vulnerability: dbTypes.Vulnerability{
Severity: dbTypes.SeverityLow.String(),
},
}
vuln2 = types.DetectedVulnerability{
VulnerabilityID: "CVE-2019-0002",
PkgName: "foo",
VulnerabilityID: "CVE-2019-0002",
PkgName: pkg1.Name,
InstalledVersion: pkg1.Version,
FixedVersion: "1.2.4",
PkgIdentifier: ftypes.PkgIdentifier{
PURL: &packageurl.PackageURL{
Type: packageurl.TypeGolang,
Namespace: "github.com/aquasecurity",
Name: "foo",
Version: "4.5.6",
},
UID: pkg1.Identifier.UID,
PURL: pkg1.Identifier.PURL,
},
InstalledVersion: "1.2.3",
FixedVersion: "1.2.4",
Vulnerability: dbTypes.Vulnerability{
Severity: dbTypes.SeverityCritical.String(),
},
Expand Down Expand Up @@ -243,8 +250,14 @@ func TestFilter(t *testing.T) {
name: "filter by VEX",
args: args{
report: types.Report{
ArtifactName: ".",
ArtifactType: artifact.TypeFilesystem,
Results: types.Results{
types.Result{
Target: "gobinary",
Class: types.ClassLangPkg,
Type: ftypes.GoBinary,
Packages: []ftypes.Package{pkg1},
Vulnerabilities: []types.DetectedVulnerability{
vuln1,
vuln2,
Expand All @@ -262,8 +275,14 @@ func TestFilter(t *testing.T) {
vexPath: "testdata/openvex.json",
},
want: types.Report{
ArtifactName: ".",
ArtifactType: artifact.TypeFilesystem,
Results: types.Results{
types.Result{
Target: "gobinary",
Class: types.ClassLangPkg,
Type: ftypes.GoBinary,
Packages: []ftypes.Package{pkg1},
Vulnerabilities: []types.DetectedVulnerability{
vuln2,
},
Expand Down Expand Up @@ -658,7 +677,10 @@ func TestFilter(t *testing.T) {
},
},
},
severities: []dbTypes.Severity{dbTypes.SeverityLow, dbTypes.SeverityHigh},
severities: []dbTypes.Severity{
dbTypes.SeverityLow,
dbTypes.SeverityHigh,
},
policyFile: "./testdata/test-ignore-policy-licenses-and-secrets.rego",
},
want: types.Report{
Expand All @@ -671,7 +693,7 @@ func TestFilter(t *testing.T) {
secret1,
},
ModifiedFindings: []types.ModifiedFinding{
{
{
Type: types.FindingTypeSecret,
Status: types.FindingStatusIgnored,
Statement: "Filtered by Rego",
Expand Down
16 changes: 13 additions & 3 deletions pkg/sbom/core/bom.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ type BOM struct {
// This is used to ensure that each package URL is only represented once in the BOM.
purls map[string][]uuid.UUID

// parents is a map of parent components to their children
// This field is populated when Options.Parents is set to true.
parents map[uuid.UUID][]uuid.UUID

// opts is a set of options for the BOM.
opts Options
}
Expand Down Expand Up @@ -199,7 +203,8 @@ type Vulnerability struct {
}

type Options struct {
GenerateBOMRef bool
GenerateBOMRef bool // Generate BOMRef for CycloneDX
Parents bool // Hold parent maps
}

func NewBOM(opts Options) *BOM {
Expand All @@ -208,6 +213,7 @@ func NewBOM(opts Options) *BOM {
relationships: make(map[uuid.UUID][]Relationship),
vulnerabilities: make(map[uuid.UUID][]Vulnerability),
purls: make(map[string][]uuid.UUID),
parents: make(map[uuid.UUID][]uuid.UUID),
opts: opts,
}
}
Expand Down Expand Up @@ -257,6 +263,10 @@ func (b *BOM) AddRelationship(parent, child *Component, relationshipType Relatio
Type: relationshipType,
Dependency: child.id,
})

if b.opts.Parents {
b.parents[child.id] = append(b.parents[child.id], parent.id)
}
}

func (b *BOM) AddVulnerabilities(c *Component, vulns []Vulnerability) {
Expand Down Expand Up @@ -298,8 +308,8 @@ func (b *BOM) Vulnerabilities() map[uuid.UUID][]Vulnerability {
return b.vulnerabilities
}

func (b *BOM) NumComponents() int {
return len(b.components) + 1 // +1 for the root component
func (b *BOM) Parents() map[uuid.UUID][]uuid.UUID {
return b.parents
}

// bomRef returns BOMRef for CycloneDX
Expand Down
2 changes: 1 addition & 1 deletion pkg/sbom/cyclonedx/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (m *Marshaler) MarshalReport(ctx context.Context, report types.Report) (*cd
// Marshal converts the Trivy component to the CycloneDX format
func (m *Marshaler) Marshal(ctx context.Context, bom *core.BOM) (*cdx.BOM, error) {
m.bom = bom
m.componentIDs = make(map[uuid.UUID]string, m.bom.NumComponents())
m.componentIDs = make(map[uuid.UUID]string, len(m.bom.Components()))

cdxBOM := cdx.NewBOM()
cdxBOM.SerialNumber = uuid.New().URN()
Expand Down
1 change: 1 addition & 0 deletions pkg/sbom/io/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ func (*Encoder) component(result types.Result, pkg ftypes.Package) *core.Compone
SrcVersion: utils.FormatSrcVersion(pkg),
SrcFile: srcFile,
PkgIdentifier: ftypes.PkgIdentifier{
UID: pkg.Identifier.UID,
PURL: pkg.Identifier.PURL,
},
Supplier: pkg.Maintainer,
Expand Down
2 changes: 1 addition & 1 deletion pkg/vex/csaf.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package vex

import (
csaf "github.com/csaf-poc/csaf_distribution/v3/csaf"
"github.com/csaf-poc/csaf_distribution/v3/csaf"
"github.com/package-url/packageurl-go"
"github.com/samber/lo"

Expand Down
Loading

0 comments on commit 9515695

Please sign in to comment.