mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +01:00
Also adds artifact location to sort key for Sorted() to ensure consistent sorts when artifacts of same name, version, and type are found in different locations in the image. Location should be sufficient since we assume only one package of a given name and version can exist in one location, even if that location is an package-db like rpmdb. Signed-off-by: Zach Hill <zach@anchore.com>
58 lines
1.8 KiB
Go
58 lines
1.8 KiB
Go
package packages
|
|
|
|
import (
|
|
"encoding/xml"
|
|
|
|
"github.com/anchore/syft/internal"
|
|
"github.com/anchore/syft/internal/version"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
"github.com/anchore/syft/syft/source"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// Source: https://github.com/CycloneDX/specification
|
|
|
|
// CycloneDxDocument represents a CycloneDX BOM CycloneDxDocument.
|
|
type CycloneDxDocument struct {
|
|
XMLName xml.Name `xml:"bom"`
|
|
XMLNs string `xml:"xmlns,attr"`
|
|
Version int `xml:"version,attr"`
|
|
SerialNumber string `xml:"serialNumber,attr"`
|
|
BomDescriptor *CycloneDxBomDescriptor `xml:"metadata"` // The BOM descriptor extension
|
|
Components []CycloneDxComponent `xml:"components>component"` // The BOM contents
|
|
}
|
|
|
|
// NewCycloneDxDocument returns a CycloneDX CycloneDxDocument object populated with the catalog contents.
|
|
func NewCycloneDxDocument(catalog *pkg.Catalog, srcMetadata source.Metadata) CycloneDxDocument {
|
|
versionInfo := version.FromBuild()
|
|
|
|
doc := CycloneDxDocument{
|
|
XMLNs: "http://cyclonedx.org/schema/bom/1.2",
|
|
Version: 1,
|
|
SerialNumber: uuid.New().URN(),
|
|
BomDescriptor: NewCycloneDxBomDescriptor(internal.ApplicationName, versionInfo.Version, srcMetadata),
|
|
}
|
|
|
|
// attach components
|
|
for _, p := range catalog.Sorted() {
|
|
component := CycloneDxComponent{
|
|
Type: "library", // TODO: this is not accurate
|
|
Name: p.Name,
|
|
Version: p.Version,
|
|
PackageURL: p.PURL,
|
|
}
|
|
var licenses []CycloneDxLicense
|
|
for _, licenseName := range p.Licenses {
|
|
licenses = append(licenses, CycloneDxLicense{
|
|
Name: licenseName,
|
|
})
|
|
}
|
|
if len(licenses) > 0 {
|
|
component.Licenses = &licenses
|
|
}
|
|
doc.Components = append(doc.Components, component)
|
|
}
|
|
|
|
return doc
|
|
}
|