fix: add BOMRef to CycloneDX OS Component (#2634)

This commit is contained in:
Keith Zantow 2024-02-14 08:18:16 -05:00 committed by GitHub
parent 25d3c06962
commit 6288530835
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 106 additions and 5 deletions

View File

@ -1,6 +1,7 @@
package cyclonedxhelpers package cyclonedxhelpers
import ( import (
"fmt"
"slices" "slices"
"strings" "strings"
"time" "time"
@ -84,8 +85,9 @@ func toOSComponent(distro *linux.Release) []cyclonedx.Component {
} }
return []cyclonedx.Component{ return []cyclonedx.Component{
{ {
Type: cyclonedx.ComponentTypeOS, BOMRef: toOSBomRef(distro.ID, distro.VersionID),
// FIXME is it idiomatic to be using SWID here for specific name and version information? Type: cyclonedx.ComponentTypeOS,
// is it idiomatic to be using SWID here for specific name and version information?
SWID: &cyclonedx.SWID{ SWID: &cyclonedx.SWID{
TagID: distro.ID, TagID: distro.ID,
Name: distro.ID, Name: distro.ID,
@ -94,7 +96,7 @@ func toOSComponent(distro *linux.Release) []cyclonedx.Component {
Description: distro.PrettyName, Description: distro.PrettyName,
Name: distro.ID, Name: distro.ID,
Version: distro.VersionID, Version: distro.VersionID,
// TODO should we add a PURL? // should we add a PURL?
CPE: formatCPE(distro.CPEName), CPE: formatCPE(distro.CPEName),
ExternalReferences: eRefs, ExternalReferences: eRefs,
Properties: properties, Properties: properties,
@ -102,6 +104,16 @@ func toOSComponent(distro *linux.Release) []cyclonedx.Component {
} }
} }
func toOSBomRef(name string, version string) string {
if name == "" {
return "os:unknown"
}
if version == "" {
return fmt.Sprintf("os:%s", name)
}
return fmt.Sprintf("os:%s@%s", name, version)
}
func formatCPE(cpeString string) string { func formatCPE(cpeString string) string {
c, err := cpe.NewAttributes(cpeString) c, err := cpe.NewAttributes(cpeString)
if err != nil { if err != nil {

View File

@ -11,6 +11,7 @@ import (
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/format/internal/cyclonedxutil/helpers" "github.com/anchore/syft/syft/format/internal/cyclonedxutil/helpers"
"github.com/anchore/syft/syft/linux"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/sbom" "github.com/anchore/syft/syft/sbom"
"github.com/anchore/syft/syft/source" "github.com/anchore/syft/syft/source"
@ -234,3 +235,89 @@ func Test_toBomDescriptor(t *testing.T) {
}) })
} }
} }
func Test_toOsComponent(t *testing.T) {
tests := []struct {
name string
release linux.Release
expected cyclonedx.Component
}{
{
name: "basic os component",
release: linux.Release{
ID: "myLinux",
VersionID: "myVersion",
},
expected: cyclonedx.Component{
BOMRef: "os:myLinux@myVersion",
Type: cyclonedx.ComponentTypeOS,
Name: "myLinux",
Version: "myVersion",
SWID: &cyclonedx.SWID{
TagID: "myLinux",
Name: "myLinux",
Version: "myVersion",
},
Properties: &[]cyclonedx.Property{
{
Name: "syft:distro:id",
Value: "myLinux",
},
{
Name: "syft:distro:versionID",
Value: "myVersion",
},
},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
gotSlice := toOSComponent(&test.release)
require.Len(t, gotSlice, 1)
got := gotSlice[0]
require.Equal(t, test.expected, got)
})
}
}
func Test_toOSBomRef(t *testing.T) {
tests := []struct {
name string
osName string
osVersion string
expected string
}{
{
name: "no name or version specified",
osName: "",
osVersion: "",
expected: "os:unknown",
},
{
name: "no version specified",
osName: "my-name",
osVersion: "",
expected: "os:my-name",
},
{
name: "no name specified",
osName: "",
osVersion: "my-version",
expected: "os:unknown",
},
{
name: "both name and version specified",
osName: "my-name",
osVersion: "my-version",
expected: "os:my-name@my-version",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got := toOSBomRef(test.osName, test.osVersion)
require.Equal(t, test.expected, got)
})
}
}

View File

@ -91,6 +91,7 @@
] ]
}, },
{ {
"bom-ref":"redacted",
"type": "operating-system", "type": "operating-system",
"name": "debian", "name": "debian",
"version": "1.2.3", "version": "1.2.3",

View File

@ -100,6 +100,7 @@
] ]
}, },
{ {
"bom-ref":"redacted",
"type": "operating-system", "type": "operating-system",
"name": "debian", "name": "debian",
"version": "1.2.3", "version": "1.2.3",

View File

@ -47,7 +47,7 @@
<property name="syft:metadata:installedSize">0</property> <property name="syft:metadata:installedSize">0</property>
</properties> </properties>
</component> </component>
<component type="operating-system"> <component bom-ref="redacted" type="operating-system">
<name>debian</name> <name>debian</name>
<version>1.2.3</version> <version>1.2.3</version>
<description>debian</description> <description>debian</description>

View File

@ -50,7 +50,7 @@
<property name="syft:metadata:installedSize">0</property> <property name="syft:metadata:installedSize">0</property>
</properties> </properties>
</component> </component>
<component type="operating-system"> <component bom-ref="redacted" type="operating-system">
<name>debian</name> <name>debian</name>
<version>1.2.3</version> <version>1.2.3</version>
<description>debian</description> <description>debian</description>