Merge pull request #282 from anchore/issue_270

Corrected syft cyclonedx generated bom to adhere to the specifications found in CycloneDX 1.2
This commit is contained in:
Toure Dunnon 2020-12-04 13:48:55 -05:00 committed by GitHub
commit 2d0c127419
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 225 deletions

View File

@ -1,183 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
CycloneDX BOM Descriptor Extension
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
xmlns:bom="http://cyclonedx.org/schema/bom/1.1"
xmlns:bd="http://cyclonedx.org/schema/ext/bom-descriptor/1.0"
elementFormDefault="qualified"
targetNamespace="http://cyclonedx.org/schema/ext/bom-descriptor/1.0"
vc:minVersion="1.0"
vc:maxVersion="1.1"
version="1.0">
<xs:annotation>
<xs:documentation>
<name>CycloneDX BOM Descriptor Extension</name>
<url>https://cyclonedx.org/ext/bom-descriptor</url>
<license uri="http://www.apache.org/licenses/LICENSE-2.0"
version="2.0">Apache License, Version 2.0</license>
<authors>
<author>Steve Springett</author>
</authors>
</xs:documentation>
</xs:annotation>
<xs:import namespace="http://cyclonedx.org/schema/bom/1.1" schemaLocation="http://cyclonedx.org/schema/bom/1.1"/>
<xs:complexType name="metadata">
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="timestamp" type="xs:dateTime" minOccurs="0">
<xs:annotation>
<xs:documentation>The date and time (timestamp) when the document was created.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="tool" minOccurs="0" type="bd:toolType">
<xs:annotation>
<xs:documentation>The tool used to create the BOM.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="authors" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>The person(s) who created the BOM. Authors are common in BOMs created through
manual processes. BOMs created through automated means may not have authors.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="author" type="bd:organizationalPerson"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="component" type="bom:component" minOccurs="0">
<xs:annotation>
<xs:documentation>The component that the BOM describes.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="manufacture" type="bd:organizationalEntity" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>The organization that manufactured the component that the BOM describes.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="supplier" type="bd:organizationalEntity" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>The organization that supplied the component that the BOM describes. The
supplier may often be the manufacture, but may also be a distributor or repackager.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax">
<xs:annotation>
<xs:documentation>User-defined attributes may be used on this element as long as they
do not have the same name as an existing attribute used by the schema.</xs:documentation>
</xs:annotation>
</xs:anyAttribute>
</xs:complexType>
<xs:complexType name="organizationalEntity">
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="name" type="xs:normalizedString" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>The name of the organization</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="url" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>The URL of the organization. Multiple URLs are allowed.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="contact" type="bd:organizationalPerson" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>A contact person at the organization. Multiple contacts are allowed.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax">
<xs:annotation>
<xs:documentation>User-defined attributes may be used on this element as long as they
do not have the same name as an existing attribute used by the schema.</xs:documentation>
</xs:annotation>
</xs:anyAttribute>
</xs:complexType>
<xs:complexType name="toolType">
<xs:annotation>
<xs:documentation>Specifies a tool (manual or automated).</xs:documentation>
</xs:annotation>
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="vendor" minOccurs="0" maxOccurs="1" type="xs:normalizedString">
<xs:annotation>
<xs:documentation>The vendor of the tool used to create the BOM.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="name" minOccurs="0" maxOccurs="1" type="xs:normalizedString">
<xs:annotation>
<xs:documentation>The name of the tool used to create the BOM.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="version" minOccurs="0" maxOccurs="1" type="xs:normalizedString">
<xs:annotation>
<xs:documentation>The version of the tool used to create the BOM.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="hashes" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="hash" type="bom:hashType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax">
<xs:annotation>
<xs:documentation>User-defined attributes may be used on this element as long as they
do not have the same name as an existing attribute used by the schema.</xs:documentation>
</xs:annotation>
</xs:anyAttribute>
</xs:complexType>
<xs:complexType name="organizationalPerson">
<xs:sequence minOccurs="0" maxOccurs="1">
<xs:element name="name" type="xs:normalizedString" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>The name of the person</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="email" type="xs:normalizedString" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>The email address of the person. Multiple email addresses are allowed.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="phone" type="xs:normalizedString" minOccurs="0" maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>The phone number of the person. Multiple phone numbers are allowed.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:anyAttribute namespace="##other" processContents="lax">
<xs:annotation>
<xs:documentation>User-defined attributes may be used on this element as long as they
do not have the same name as an existing attribute used by the schema.</xs:documentation>
</xs:annotation>
</xs:anyAttribute>
</xs:complexType>
<xs:element name="metadata" type="bd:metadata">
<xs:annotation>
<xs:documentation>Provides additional information about a BOM.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>

View File

@ -11,25 +11,25 @@ import (
// BomDescriptor represents all metadata surrounding the BOM report (such as when the BOM was made, with which tool, and the item being cataloged). // BomDescriptor represents all metadata surrounding the BOM report (such as when the BOM was made, with which tool, and the item being cataloged).
type BomDescriptor struct { type BomDescriptor struct {
XMLName xml.Name `xml:"bd:metadata"` XMLName xml.Name `xml:"metadata"`
Timestamp string `xml:"bd:timestamp,omitempty"` // The date and time (timestamp) when the document was created Timestamp string `xml:"timestamp,omitempty"` // The date and time (timestamp) when the document was created
Tool *BdTool `xml:"bd:tool"` // The tool used to create the BOM. Tools []BdTool `xml:"tools>tool"` // The tool used to create the BOM.
Component *BdComponent `xml:"bd:component"` // The component that the BOM describes. Component *BdComponent `xml:"component"` // The component that the BOM describes.
} }
// BdTool represents the tool that created the BOM report. // BdTool represents the tool that created the BOM report.
type BdTool struct { type BdTool struct {
XMLName xml.Name `xml:"bd:tool"` XMLName xml.Name `xml:"tool"`
Vendor string `xml:"bd:vendor,omitempty"` // The vendor of the tool used to create the BOM. Vendor string `xml:"vendor,omitempty"` // The vendor of the tool used to create the BOM.
Name string `xml:"bd:name,omitempty"` // The name of the tool used to create the BOM. Name string `xml:"name,omitempty"` // The name of the tool used to create the BOM.
Version string `xml:"bd:version,omitempty"` // The version of the tool used to create the BOM. Version string `xml:"version,omitempty"` // The version of the tool used to create the BOM.
// TODO: hashes, author, manufacture, supplier // TODO: hashes, author, manufacture, supplier
// TODO: add user-defined fields for the remaining build/version parameters // TODO: add user-defined fields for the remaining build/version parameters
} }
// BdComponent represents the software/package being cataloged. // BdComponent represents the software/package being cataloged.
type BdComponent struct { type BdComponent struct {
XMLName xml.Name `xml:"bd:component"` XMLName xml.Name `xml:"component"`
Component Component
} }
@ -38,11 +38,13 @@ func NewBomDescriptor(name, version string, srcMetadata source.Metadata) *BomDes
descriptor := BomDescriptor{ descriptor := BomDescriptor{
XMLName: xml.Name{}, XMLName: xml.Name{},
Timestamp: time.Now().Format(time.RFC3339), Timestamp: time.Now().Format(time.RFC3339),
Tool: &BdTool{ Tools: []BdTool{
{
Vendor: "anchore", Vendor: "anchore",
Name: name, Name: name,
Version: version, Version: version,
}, },
},
} }
switch srcMetadata.Scheme { switch srcMetadata.Scheme {

View File

@ -16,11 +16,10 @@ import (
type Document struct { type Document struct {
XMLName xml.Name `xml:"bom"` XMLName xml.Name `xml:"bom"`
XMLNs string `xml:"xmlns,attr"` XMLNs string `xml:"xmlns,attr"`
XMLNsBd string `xml:"xmlns:bd,attr"`
Version int `xml:"version,attr"` Version int `xml:"version,attr"`
SerialNumber string `xml:"serialNumber,attr"` SerialNumber string `xml:"serialNumber,attr"`
BomDescriptor *BomDescriptor `xml:"metadata"` // The BOM descriptor extension
Components []Component `xml:"components>component"` // The BOM contents Components []Component `xml:"components>component"` // The BOM contents
BomDescriptor *BomDescriptor `xml:"bd:metadata"` // The BOM descriptor extension
} }
// NewDocumentFromCatalog returns a CycloneDX Document object populated with the catalog contents. // NewDocumentFromCatalog returns a CycloneDX Document object populated with the catalog contents.
@ -29,7 +28,6 @@ func NewDocument(catalog *pkg.Catalog, srcMetadata source.Metadata) Document {
doc := Document{ doc := Document{
XMLNs: "http://cyclonedx.org/schema/bom/1.2", XMLNs: "http://cyclonedx.org/schema/bom/1.2",
XMLNsBd: "http://cyclonedx.org/schema/ext/bom-descriptor/1.0",
Version: 1, Version: 1,
SerialNumber: uuid.New().URN(), SerialNumber: uuid.New().URN(),
BomDescriptor: NewBomDescriptor(internal.ApplicationName, versionInfo.Version, srcMetadata), BomDescriptor: NewBomDescriptor(internal.ApplicationName, versionInfo.Version, srcMetadata),

View File

@ -1,5 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.2" xmlns:bd="http://cyclonedx.org/schema/ext/bom-descriptor/1.0" version="1" serialNumber="urn:uuid:aa1738d1-1c6e-45e4-a530-5a04d2c2b1a7"> <bom xmlns="http://cyclonedx.org/schema/bom/1.2" version="1" serialNumber="urn:uuid:553b2601-a7b0-4461-bce9-fd56e2e2a4be">
<metadata>
<timestamp>2020-12-01T22:19:00-05:00</timestamp>
<tools>
<tool>
<vendor>anchore</vendor>
<name>syft</name>
<version>[not provided]</version>
</tool>
</tools>
<component type="file">
<name>/some/path</name>
<version></version>
</component>
</metadata>
<components> <components>
<component type="library"> <component type="library">
<name>package1</name> <name>package1</name>
@ -18,16 +32,4 @@
</licenses> </licenses>
</component> </component>
</components> </components>
<bd:metadata>
<bd:timestamp>2020-11-19T10:11:26-05:00</bd:timestamp>
<bd:tool>
<bd:vendor>anchore</bd:vendor>
<bd:name>syft</bd:name>
<bd:version>[not provided]</bd:version>
</bd:tool>
<bd:component type="file">
<name>/some/path</name>
<version></version>
</bd:component>
</bd:metadata>
</bom> </bom>

View File

@ -1,5 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.2" xmlns:bd="http://cyclonedx.org/schema/ext/bom-descriptor/1.0" version="1" serialNumber="urn:uuid:8a4c332c-365c-454d-a43c-d9344577d105"> <bom xmlns="http://cyclonedx.org/schema/bom/1.2" version="1" serialNumber="urn:uuid:4a54c180-9469-4513-a1cb-af3fe1e83738">
<metadata>
<timestamp>2020-12-01T22:19:00-05:00</timestamp>
<tools>
<tool>
<vendor>anchore</vendor>
<name>syft</name>
<version>[not provided]</version>
</tool>
</tools>
<component type="container">
<name>user-image-input</name>
<version>sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368</version>
</component>
</metadata>
<components> <components>
<component type="library"> <component type="library">
<name>package1</name> <name>package1</name>
@ -20,16 +34,4 @@
<purl>the-purl-2</purl> <purl>the-purl-2</purl>
</component> </component>
</components> </components>
<bd:metadata>
<bd:timestamp>2020-11-19T10:11:26-05:00</bd:timestamp>
<bd:tool>
<bd:vendor>anchore</bd:vendor>
<bd:name>syft</bd:name>
<bd:version>[not provided]</bd:version>
</bd:tool>
<bd:component type="container">
<name>user-image-input</name>
<version>sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368</version>
</bd:component>
</bd:metadata>
</bom> </bom>