mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
* Improve CycloneDX format output ## Additions to CycloneDX output * CPEs * Authors * Publishers * External References (Website, Distribution, VCS) * Description Signed-off-by: Sambhav Kothari <skothari44@bloomberg.net>
117 lines
3.2 KiB
Go
117 lines
3.2 KiB
Go
package cyclonedxhelpers
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/CycloneDX/cyclonedx-go"
|
|
"github.com/anchore/syft/internal"
|
|
"github.com/anchore/syft/internal/version"
|
|
"github.com/anchore/syft/syft/linux"
|
|
"github.com/anchore/syft/syft/sbom"
|
|
"github.com/anchore/syft/syft/source"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func ToFormatModel(s sbom.SBOM) *cyclonedx.BOM {
|
|
cdxBOM := cyclonedx.NewBOM()
|
|
versionInfo := version.FromBuild()
|
|
|
|
// NOTE(jonasagx): cycloneDX requires URN uuids (URN returns the RFC 2141 URN form of uuid):
|
|
// https://github.com/CycloneDX/specification/blob/master/schema/bom-1.3-strict.schema.json#L36
|
|
// "pattern": "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
|
cdxBOM.SerialNumber = uuid.New().URN()
|
|
cdxBOM.Metadata = toBomDescriptor(internal.ApplicationName, versionInfo.Version, s.Source)
|
|
|
|
packages := s.Artifacts.PackageCatalog.Sorted()
|
|
components := make([]cyclonedx.Component, len(packages))
|
|
for i, p := range packages {
|
|
components[i] = Component(p)
|
|
}
|
|
components = append(components, toOSComponent(s.Artifacts.LinuxDistribution)...)
|
|
cdxBOM.Components = &components
|
|
return cdxBOM
|
|
}
|
|
|
|
func toOSComponent(distro *linux.Release) []cyclonedx.Component {
|
|
if distro == nil {
|
|
return []cyclonedx.Component{}
|
|
}
|
|
eRefs := &[]cyclonedx.ExternalReference{}
|
|
if distro.BugReportURL != "" {
|
|
*eRefs = append(*eRefs, cyclonedx.ExternalReference{
|
|
URL: distro.BugReportURL,
|
|
Type: cyclonedx.ERTypeIssueTracker,
|
|
})
|
|
}
|
|
if distro.HomeURL != "" {
|
|
*eRefs = append(*eRefs, cyclonedx.ExternalReference{
|
|
URL: distro.HomeURL,
|
|
Type: cyclonedx.ERTypeWebsite,
|
|
})
|
|
}
|
|
if distro.SupportURL != "" {
|
|
*eRefs = append(*eRefs, cyclonedx.ExternalReference{
|
|
URL: distro.SupportURL,
|
|
Type: cyclonedx.ERTypeOther,
|
|
Comment: "support",
|
|
})
|
|
}
|
|
if distro.PrivacyPolicyURL != "" {
|
|
*eRefs = append(*eRefs, cyclonedx.ExternalReference{
|
|
URL: distro.PrivacyPolicyURL,
|
|
Type: cyclonedx.ERTypeOther,
|
|
Comment: "privacyPolicy",
|
|
})
|
|
}
|
|
if len(*eRefs) == 0 {
|
|
eRefs = nil
|
|
}
|
|
props := getCycloneDXProperties(*distro)
|
|
if len(*props) == 0 {
|
|
props = nil
|
|
}
|
|
return []cyclonedx.Component{
|
|
{
|
|
Type: cyclonedx.ComponentTypeOS,
|
|
Name: distro.Name,
|
|
Version: distro.Version,
|
|
CPE: distro.CPEName,
|
|
ExternalReferences: eRefs,
|
|
Properties: props,
|
|
},
|
|
}
|
|
}
|
|
|
|
// NewBomDescriptor returns a new BomDescriptor tailored for the current time and "syft" tool details.
|
|
func toBomDescriptor(name, version string, srcMetadata source.Metadata) *cyclonedx.Metadata {
|
|
return &cyclonedx.Metadata{
|
|
Timestamp: time.Now().Format(time.RFC3339),
|
|
Tools: &[]cyclonedx.Tool{
|
|
{
|
|
Vendor: "anchore",
|
|
Name: name,
|
|
Version: version,
|
|
},
|
|
},
|
|
Component: toBomDescriptorComponent(srcMetadata),
|
|
}
|
|
}
|
|
|
|
func toBomDescriptorComponent(srcMetadata source.Metadata) *cyclonedx.Component {
|
|
switch srcMetadata.Scheme {
|
|
case source.ImageScheme:
|
|
return &cyclonedx.Component{
|
|
Type: cyclonedx.ComponentTypeContainer,
|
|
Name: srcMetadata.ImageMetadata.UserInput,
|
|
Version: srcMetadata.ImageMetadata.ManifestDigest,
|
|
}
|
|
case source.DirectoryScheme, source.FileScheme:
|
|
return &cyclonedx.Component{
|
|
Type: cyclonedx.ComponentTypeFile,
|
|
Name: srcMetadata.Path,
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|