Skip to content

Commit

Permalink
test: add uuid package
Browse files Browse the repository at this point in the history
  • Loading branch information
knqyf263 committed Aug 8, 2023
1 parent efdf433 commit fec0ca2
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 128 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ require (
github.com/testcontainers/testcontainers-go/modules/localstack v0.21.0
github.com/tetratelabs/wazero v1.2.1
github.com/twitchtv/twirp v8.1.2+incompatible
github.com/xeipuuv/gojsonschema v1.2.0
github.com/xlab/treeprint v1.1.0
go.etcd.io/bbolt v1.3.7
go.uber.org/zap v1.24.0
Expand Down Expand Up @@ -344,7 +345,6 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/yashtewari/glob-intersection v0.1.0 // indirect
github.com/yuin/gopher-lua v1.1.0 // indirect
github.com/zclconf/go-cty v1.10.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions pkg/k8s/report/cyclonedx.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ type CycloneDXWriter struct {
}

// NewCycloneDXWriter constract new CycloneDXWriter
func NewCycloneDXWriter(output io.Writer, format cdx.BOMFileFormat, appVersion string, opts ...core.Option) CycloneDXWriter {
func NewCycloneDXWriter(output io.Writer, format cdx.BOMFileFormat, appVersion string) CycloneDXWriter {
encoder := cdx.NewBOMEncoder(output, format)
encoder.SetPretty(true)
return CycloneDXWriter{
encoder: encoder,
marshaler: core.NewCycloneDX(appVersion, opts...),
marshaler: core.NewCycloneDX(appVersion),
}
}

Expand Down
42 changes: 9 additions & 33 deletions pkg/sbom/cyclonedx/core/cyclonedx.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import (
"strings"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/google/uuid"
"github.com/samber/lo"
"golang.org/x/exp/slices"
"k8s.io/utils/clock"

dtypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/aquasecurity/trivy/pkg/clock"
"github.com/aquasecurity/trivy/pkg/digest"
"github.com/aquasecurity/trivy/pkg/log"
"github.com/aquasecurity/trivy/pkg/purl"
"github.com/aquasecurity/trivy/pkg/types"
"github.com/aquasecurity/trivy/pkg/uuid"
)

const (
Expand All @@ -29,26 +29,8 @@ const (
timeLayout = "2006-01-02T15:04:05+00:00"
)

type NewUUID func() uuid.UUID

type Option func(dx *CycloneDX)

func WithClock(clock clock.Clock) Option {
return func(opts *CycloneDX) {
opts.clock = clock
}
}

func WithNewUUID(newUUID NewUUID) Option {
return func(opts *CycloneDX) {
opts.newUUID = newUUID
}
}

type CycloneDX struct {
appVersion string
clock clock.Clock
newUUID NewUUID
}

type Component struct {
Expand All @@ -72,22 +54,15 @@ type Property struct {
Namespace string
}

func NewCycloneDX(version string, opts ...Option) *CycloneDX {
c := &CycloneDX{
func NewCycloneDX(version string) *CycloneDX {
return &CycloneDX{
appVersion: version,
clock: clock.RealClock{},
newUUID: uuid.New,
}
for _, opt := range opts {
opt(c)
}

return c
}

func (c *CycloneDX) Marshal(root *Component) *cdx.BOM {
bom := cdx.NewBOM()
bom.SerialNumber = c.newUUID().URN()
bom.SerialNumber = uuid.New().URN()
bom.Metadata = c.Metadata()

components := map[string]*cdx.Component{}
Expand Down Expand Up @@ -200,14 +175,14 @@ func (c *CycloneDX) marshalVulnerability(bomRef string, vuln types.DetectedVulne
func (c *CycloneDX) BOMRef(component *Component) string {
// PURL takes precedence over UUID
if component.PackageURL == nil {
return c.newUUID().String()
return uuid.New().String()
}
return component.PackageURL.BOMRef()
}

func (c *CycloneDX) Metadata() *cdx.Metadata {
return &cdx.Metadata{
Timestamp: c.clock.Now().UTC().Format(timeLayout),
Timestamp: clock.Now().UTC().Format(timeLayout),
Tools: &[]cdx.Tool{
{
Vendor: ToolVendor,
Expand Down Expand Up @@ -306,7 +281,8 @@ func (c *CycloneDX) Licenses(licenses []string) *cdx.Licenses {
choices := lo.Map(licenses, func(license string, i int) cdx.LicenseChoice {
return cdx.LicenseChoice{
License: &cdx.License{
Name: license},
Name: license,
},
}
})
return lo.ToPtr(cdx.Licenses(choices))
Expand Down
94 changes: 66 additions & 28 deletions pkg/sbom/cyclonedx/core/cyclonedx_test.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package core_test

import (
"fmt"
"testing"
"time"

"github.com/aquasecurity/trivy/pkg/digest"
"github.com/aquasecurity/trivy/pkg/purl"
"github.com/aquasecurity/trivy/pkg/sbom/cyclonedx/core"

cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/google/uuid"
"github.com/package-url/packageurl-go"
"github.com/stretchr/testify/assert"
fake "k8s.io/utils/clock/testing"

"github.com/aquasecurity/trivy/pkg/clock"
"github.com/aquasecurity/trivy/pkg/digest"
"github.com/aquasecurity/trivy/pkg/purl"
"github.com/aquasecurity/trivy/pkg/sbom/cyclonedx/core"
"github.com/aquasecurity/trivy/pkg/uuid"
)

func TestMarshaler_CoreComponent(t *testing.T) {
Expand All @@ -33,7 +32,10 @@ func TestMarshaler_CoreComponent(t *testing.T) {
Type: cdx.ComponentTypeApplication,
Name: "kube-apiserver-kind-control-plane",
Properties: []core.Property{
{Name: "control_plane_components", Value: "kube-apiserver"},
{
Name: "control_plane_components",
Value: "kube-apiserver",
},
},
Components: []*core.Component{
{
Expand All @@ -58,8 +60,14 @@ func TestMarshaler_CoreComponent(t *testing.T) {
},
Hashes: []digest.Digest{"sha256:18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f"},
Properties: []core.Property{
{Name: "PkgID", Value: "k8s.gcr.io/kube-apiserver:1.21.1"},
{Name: "PkgType", Value: "oci"},
{
Name: "PkgID",
Value: "k8s.gcr.io/kube-apiserver:1.21.1",
},
{
Name: "PkgType",
Value: "oci",
},
},
},
},
Expand All @@ -68,36 +76,66 @@ func TestMarshaler_CoreComponent(t *testing.T) {
Type: cdx.ComponentTypeContainer,
Name: "kind-control-plane",
Properties: []core.Property{
{Name: "architecture", Value: "arm64"},
{Name: "host_name", Value: "kind-control-plane"},
{Name: "kernel_version", Value: "6.2.13-300.fc38.aarch64"},
{Name: "node_role", Value: "master"},
{Name: "operating_system", Value: "linux"},
{
Name: "architecture",
Value: "arm64",
},
{
Name: "host_name",
Value: "kind-control-plane",
},
{
Name: "kernel_version",
Value: "6.2.13-300.fc38.aarch64",
},
{
Name: "node_role",
Value: "master",
},
{
Name: "operating_system",
Value: "linux",
},
},
Components: []*core.Component{
{
Type: cdx.ComponentTypeOS,
Name: "ubuntu",
Version: "21.04",
Properties: []core.Property{
{Name: "Class", Value: "os-pkgs"},
{Name: "Type", Value: "ubuntu"},
{
Name: "Class",
Value: "os-pkgs",
},
{
Name: "Type",
Value: "ubuntu",
},
},
},
{
Type: cdx.ComponentTypeApplication,
Name: "node-core-components",
Properties: []core.Property{
{Name: "Class", Value: "lang-pkgs"},
{Name: "Type", Value: "golang"},
{
Name: "Class",
Value: "lang-pkgs",
},
{
Name: "Type",
Value: "golang",
},
},
Components: []*core.Component{
{
Type: cdx.ComponentTypeLibrary,
Name: "kubelet",
Version: "1.21.1",
Properties: []core.Property{
{Name: "PkgType", Value: "golang"},
{
Name: "PkgType",
Value: "golang",
},
},
PackageURL: &purl.PackageURL{
PackageURL: packageurl.PackageURL{
Expand All @@ -113,7 +151,10 @@ func TestMarshaler_CoreComponent(t *testing.T) {
Name: "containerd",
Version: "1.5.2",
Properties: []core.Property{
{Name: "PkgType", Value: "golang"},
{
Name: "PkgType",
Value: "golang",
},
},
PackageURL: &purl.PackageURL{
PackageURL: packageurl.PackageURL{
Expand Down Expand Up @@ -321,16 +362,13 @@ func TestMarshaler_CoreComponent(t *testing.T) {
},
},
}
clock := fake.NewFakeClock(time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var count int
newUUID := func() uuid.UUID {
count++
return uuid.Must(uuid.Parse(fmt.Sprintf("3ff14136-e09f-4df9-80ea-%012d", count)))
}
marshaler := core.NewCycloneDX("dev", core.WithClock(clock), core.WithNewUUID(newUUID))
clock.SetFakeTime(t, time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))
uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d")

marshaler := core.NewCycloneDX("dev")
got := marshaler.Marshal(tt.rootComponent)
assert.Equal(t, tt.want, got)
})
Expand Down
69 changes: 54 additions & 15 deletions pkg/sbom/cyclonedx/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ type Marshaler struct {
core *core.CycloneDX
}

func NewMarshaler(version string, opts ...core.Option) *Marshaler {
func NewMarshaler(version string) *Marshaler {
return &Marshaler{
core: core.NewCycloneDX(version, opts...),
core: core.NewCycloneDX(version),
}
}

Expand Down Expand Up @@ -217,7 +217,10 @@ func (e *Marshaler) rootComponent(r types.Report) (*core.Component, error) {
}

props := []core.Property{
{Name: PropertySchemaVersion, Value: strconv.Itoa(r.SchemaVersion)},
{
Name: PropertySchemaVersion,
Value: strconv.Itoa(r.SchemaVersion),
},
}

switch r.ArtifactType {
Expand Down Expand Up @@ -276,8 +279,14 @@ func (e *Marshaler) resultComponent(r types.Result, osFound *ftypes.OS) *core.Co
component := &core.Component{
Name: r.Target,
Properties: []core.Property{
{Name: PropertyType, Value: r.Type},
{Name: PropertyClass, Value: string(r.Class)},
{
Name: PropertyType,
Value: r.Type,
},
{
Name: PropertyClass,
Value: string(r.Class),
},
},
}

Expand Down Expand Up @@ -314,16 +323,46 @@ func pkgComponent(pkg Package) (*core.Component, error) {
}

properties := []core.Property{
{Name: PropertyPkgID, Value: pkg.ID},
{Name: PropertyPkgType, Value: pkg.Type},
{Name: PropertyFilePath, Value: pkg.FilePath},
{Name: PropertySrcName, Value: pkg.SrcName},
{Name: PropertySrcVersion, Value: pkg.SrcVersion},
{Name: PropertySrcRelease, Value: pkg.SrcRelease},
{Name: PropertySrcEpoch, Value: strconv.Itoa(pkg.SrcEpoch)},
{Name: PropertyModularitylabel, Value: pkg.Modularitylabel},
{Name: PropertyLayerDigest, Value: pkg.Layer.Digest},
{Name: PropertyLayerDiffID, Value: pkg.Layer.DiffID},
{
Name: PropertyPkgID,
Value: pkg.ID,
},
{
Name: PropertyPkgType,
Value: pkg.Type,
},
{
Name: PropertyFilePath,
Value: pkg.FilePath,
},
{
Name: PropertySrcName,
Value: pkg.SrcName,
},
{
Name: PropertySrcVersion,
Value: pkg.SrcVersion,
},
{
Name: PropertySrcRelease,
Value: pkg.SrcRelease,
},
{
Name: PropertySrcEpoch,
Value: strconv.Itoa(pkg.SrcEpoch),
},
{
Name: PropertyModularitylabel,
Value: pkg.Modularitylabel,
},
{
Name: PropertyLayerDigest,
Value: pkg.Layer.Digest,
},
{
Name: PropertyLayerDiffID,
Value: pkg.Layer.DiffID,
},
}

return &core.Component{
Expand Down
Loading

0 comments on commit fec0ca2

Please sign in to comment.