Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add manufacturer and authors #171

Merged
merged 1 commit into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ func (b *BOM) convert(specVersion SpecVersion) {
b.Metadata.Lifecycles = nil
}

if specVersion < SpecVersion1_6 {
b.Metadata.Manufacturer = nil
}

recurseComponent(b.Metadata.Component, componentConverter(specVersion))
convertLicenses(b.Metadata.Licenses, specVersion)
convertTools(b.Metadata.Tools, specVersion)
Expand Down Expand Up @@ -147,6 +151,8 @@ func componentConverter(specVersion SpecVersion) func(*Component) {
if specVersion < SpecVersion1_6 {
c.SWHID = nil
c.OmniborID = nil
c.Manufacturer = nil
c.Authors = nil
}

if !specVersion.supportsComponentType(c.Type) {
Expand Down
44 changes: 44 additions & 0 deletions convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,47 @@ func Test_convertModelCard(t *testing.T) {
assert.Nil(t, bom.Metadata.Component.ModelCard.Considerations.EnvironmentalConsiderations)
})
}

func Test_convertManufacturer(t *testing.T) {
t.Run("spec 1.5 and lower", func(t *testing.T) {
bom := NewBOM()
bom.Metadata = &Metadata{
Manufacturer: &OrganizationalEntity{
Name: "Acme, Inc.",
},
}
bom.Components = &[]Component{
{
Name: "foo",
Manufacturer: &OrganizationalEntity{
Name: "Acme, Inc.",
},
},
}

bom.convert(SpecVersion1_5)

assert.Nil(t, bom.Metadata.Manufacturer)
assert.Nil(t, (*bom.Components)[0].Manufacturer)
})
}

func Test_convertAuthors(t *testing.T) {
t.Run("spec 1.5 and lower", func(t *testing.T) {
bom := NewBOM()
bom.Components = &[]Component{
{
Name: "foo",
Authors: &[]OrganizationalContact{
{
Name: "Acme Professional Services",
},
},
},
}

bom.convert(SpecVersion1_5)

assert.Nil(t, (*bom.Components)[0].Authors)
})
}
79 changes: 41 additions & 38 deletions cyclonedx.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,35 +221,37 @@ type Commit struct {
}

type Component struct {
BOMRef string `json:"bom-ref,omitempty" xml:"bom-ref,attr,omitempty"`
MIMEType string `json:"mime-type,omitempty" xml:"mime-type,attr,omitempty"`
Type ComponentType `json:"type" xml:"type,attr"`
Supplier *OrganizationalEntity `json:"supplier,omitempty" xml:"supplier,omitempty"`
Author string `json:"author,omitempty" xml:"author,omitempty"`
Publisher string `json:"publisher,omitempty" xml:"publisher,omitempty"`
Group string `json:"group,omitempty" xml:"group,omitempty"`
Name string `json:"name" xml:"name"`
Version string `json:"version,omitempty" xml:"version,omitempty"`
Description string `json:"description,omitempty" xml:"description,omitempty"`
Scope Scope `json:"scope,omitempty" xml:"scope,omitempty"`
Hashes *[]Hash `json:"hashes,omitempty" xml:"hashes>hash,omitempty"`
Licenses *Licenses `json:"licenses,omitempty" xml:"licenses,omitempty"`
Copyright string `json:"copyright,omitempty" xml:"copyright,omitempty"`
CPE string `json:"cpe,omitempty" xml:"cpe,omitempty"`
PackageURL string `json:"purl,omitempty" xml:"purl,omitempty"`
OmniborID *[]string `json:"omniborId,omitempty" xml:"omniborId,omitempty"`
SWHID *[]string `json:"swhid,omitempty" xml:"swhid,omitempty"`
SWID *SWID `json:"swid,omitempty" xml:"swid,omitempty"`
Modified *bool `json:"modified,omitempty" xml:"modified,omitempty"`
Pedigree *Pedigree `json:"pedigree,omitempty" xml:"pedigree,omitempty"`
ExternalReferences *[]ExternalReference `json:"externalReferences,omitempty" xml:"externalReferences>reference,omitempty"`
Properties *[]Property `json:"properties,omitempty" xml:"properties>property,omitempty"`
Components *[]Component `json:"components,omitempty" xml:"components>component,omitempty"`
Evidence *Evidence `json:"evidence,omitempty" xml:"evidence,omitempty"`
ReleaseNotes *ReleaseNotes `json:"releaseNotes,omitempty" xml:"releaseNotes,omitempty"`
ModelCard *MLModelCard `json:"modelCard,omitempty" xml:"modelCard,omitempty"`
Data *ComponentData `json:"data,omitempty" xml:"data,omitempty"`
CryptoProperties *CryptoProperties `json:"cryptoProperties,omitempty" xml:"cryptoProperties,omitempty"`
BOMRef string `json:"bom-ref,omitempty" xml:"bom-ref,attr,omitempty"`
MIMEType string `json:"mime-type,omitempty" xml:"mime-type,attr,omitempty"`
Type ComponentType `json:"type" xml:"type,attr"`
Supplier *OrganizationalEntity `json:"supplier,omitempty" xml:"supplier,omitempty"`
Manufacturer *OrganizationalEntity `json:"manufacturer,omitempty" xml:"manufacturer,omitempty"`
Author string `json:"author,omitempty" xml:"author,omitempty"` // Deprecated: Use authors or manufacturer instead.
Authors *[]OrganizationalContact `json:"authors,omitempty" xml:"authors>author,omitempty"`
Publisher string `json:"publisher,omitempty" xml:"publisher,omitempty"`
Group string `json:"group,omitempty" xml:"group,omitempty"`
Name string `json:"name" xml:"name"`
Version string `json:"version,omitempty" xml:"version,omitempty"`
Description string `json:"description,omitempty" xml:"description,omitempty"`
Scope Scope `json:"scope,omitempty" xml:"scope,omitempty"`
Hashes *[]Hash `json:"hashes,omitempty" xml:"hashes>hash,omitempty"`
Licenses *Licenses `json:"licenses,omitempty" xml:"licenses,omitempty"`
Copyright string `json:"copyright,omitempty" xml:"copyright,omitempty"`
CPE string `json:"cpe,omitempty" xml:"cpe,omitempty"`
PackageURL string `json:"purl,omitempty" xml:"purl,omitempty"`
OmniborID *[]string `json:"omniborId,omitempty" xml:"omniborId,omitempty"`
SWHID *[]string `json:"swhid,omitempty" xml:"swhid,omitempty"`
SWID *SWID `json:"swid,omitempty" xml:"swid,omitempty"`
Modified *bool `json:"modified,omitempty" xml:"modified,omitempty"`
Pedigree *Pedigree `json:"pedigree,omitempty" xml:"pedigree,omitempty"`
ExternalReferences *[]ExternalReference `json:"externalReferences,omitempty" xml:"externalReferences>reference,omitempty"`
Properties *[]Property `json:"properties,omitempty" xml:"properties>property,omitempty"`
Components *[]Component `json:"components,omitempty" xml:"components>component,omitempty"`
Evidence *Evidence `json:"evidence,omitempty" xml:"evidence,omitempty"`
ReleaseNotes *ReleaseNotes `json:"releaseNotes,omitempty" xml:"releaseNotes,omitempty"`
ModelCard *MLModelCard `json:"modelCard,omitempty" xml:"modelCard,omitempty"`
Data *ComponentData `json:"data,omitempty" xml:"data,omitempty"`
CryptoProperties *CryptoProperties `json:"cryptoProperties,omitempty" xml:"cryptoProperties,omitempty"`
}

type ComponentData struct {
Expand Down Expand Up @@ -957,15 +959,16 @@ func (mt MediaType) WithVersion(specVersion SpecVersion) (string, error) {
}

type Metadata struct {
Timestamp string `json:"timestamp,omitempty" xml:"timestamp,omitempty"`
Lifecycles *[]Lifecycle `json:"lifecycles,omitempty" xml:"lifecycles>lifecycle,omitempty"`
Tools *ToolsChoice `json:"tools,omitempty" xml:"tools,omitempty"`
Authors *[]OrganizationalContact `json:"authors,omitempty" xml:"authors>author,omitempty"`
Component *Component `json:"component,omitempty" xml:"component,omitempty"`
Manufacture *OrganizationalEntity `json:"manufacture,omitempty" xml:"manufacture,omitempty"`
Supplier *OrganizationalEntity `json:"supplier,omitempty" xml:"supplier,omitempty"`
Licenses *Licenses `json:"licenses,omitempty" xml:"licenses,omitempty"`
Properties *[]Property `json:"properties,omitempty" xml:"properties>property,omitempty"`
Timestamp string `json:"timestamp,omitempty" xml:"timestamp,omitempty"`
Lifecycles *[]Lifecycle `json:"lifecycles,omitempty" xml:"lifecycles>lifecycle,omitempty"`
Tools *ToolsChoice `json:"tools,omitempty" xml:"tools,omitempty"`
Authors *[]OrganizationalContact `json:"authors,omitempty" xml:"authors>author,omitempty"`
Component *Component `json:"component,omitempty" xml:"component,omitempty"`
Manufacture *OrganizationalEntity `json:"manufacture,omitempty" xml:"manufacture,omitempty"` // Deprecated: Use Component Manufacturer instead.
Manufacturer *OrganizationalEntity `json:"manufacturer,omitempty" xml:"manufacturer,omitempty"`
Supplier *OrganizationalEntity `json:"supplier,omitempty" xml:"supplier,omitempty"`
Licenses *Licenses `json:"licenses,omitempty" xml:"licenses,omitempty"`
Properties *[]Property `json:"properties,omitempty" xml:"properties>property,omitempty"`
}

type MLDatasetChoice struct {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"components": [
{
"type": "application",
"authors": [
{
"name": "Anthony Edward Stark",
"email": "ironman@example.org",
"phone": "555-212-970-4133"
},
{
"name": "Peter Benjamin Parker",
"email": "spiderman@example.org"
}
],
"name": "Acme Application",
"version": "9.1.1"
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"components": [
{
"type": "application",
"manufacturer": {
"name": "Acme, Inc.",
"url": [
"https://example.com"
],
"contact": [
{
"name": "Acme Professional Services",
"email": "professional.services@example.com"
}
]
},
"name": "Acme Application",
"version": "9.1.1"
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"manufacturer": {
"name": "Acme, Inc.",
"url": [
"https://example.com"
],
"contact": [
{
"name": "Acme Professional Services",
"email": "professional.services@example.com"
}
]
}
},
"components": []
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.6" serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1">
<components>
<component type="application">
<authors>
<author>
<name>Anthony Edward Stark</name>
<email>ironman@example.org</email>
<phone>555-212-970-4133</phone>
</author>
<author>
<name>Peter Benjamin Parker</name>
<email>spiderman@example.org</email>
</author>
</authors>
<name>Acme Application</name>
<version>9.1.1</version>
</component>
</components>
</bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.6" serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1">
<components>
<component type="application">
<manufacturer>
<name>Acme, Inc.</name>
<url>https://example.com</url>
<contact>
<name>Acme Professional Services</name>
<email>professional.services@example.com</email>
</contact>
</manufacturer>
<name>Acme Application</name>
<version>9.1.1</version>
</component>
</components>
</bom>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.6" serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1">
<metadata>
<manufacturer>
<name>Acme, Inc.</name>
<url>https://example.com</url>
<contact>
<name>Acme Professional Services</name>
<email>professional.services@example.com</email>
</contact>
</manufacturer>
</metadata>
</bom>
24 changes: 24 additions & 0 deletions testdata/valid-component-authors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"components": [
{
"type": "application",
"name": "Acme Application",
"version": "9.1.1",
"authors": [
{
"name": "Anthony Edward Stark",
"phone": "555-212-970-4133",
"email": "ironman@example.org"
},
{
"name": "Peter Benjamin Parker",
"email": "spiderman@example.org"
}
]
}
]
}
20 changes: 20 additions & 0 deletions testdata/valid-component-authors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<bom serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6">
<components>
<component type="application">
<authors>
<author>
<name>Anthony Edward Stark</name>
<email>ironman@example.org</email>
<phone>555-212-970-4133</phone>
</author>
<author>
<name>Peter Benjamin Parker</name>
<email>spiderman@example.org</email>
</author>
</authors>
<name>Acme Application</name>
<version>9.1.1</version>
</component>
</components>
</bom>
25 changes: 25 additions & 0 deletions testdata/valid-component-manufacturer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"components": [
{
"type": "application",
"name": "Acme Application",
"version": "9.1.1",
"manufacturer": {
"name": "Acme, Inc.",
"url": [
"https://example.com"
],
"contact": [
{
"name": "Acme Professional Services",
"email": "professional.services@example.com"
}
]
}
}
]
}
17 changes: 17 additions & 0 deletions testdata/valid-component-manufacturer.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<bom serialNumber="urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6">
<components>
<component type="application">
<manufacturer>
<name>Acme, Inc.</name>
<url>https://example.com</url>
<contact>
<name>Acme Professional Services</name>
<email>professional.services@example.com</email>
</contact>
</manufacturer>
<name>Acme Application</name>
<version>9.1.1</version>
</component>
</components>
</bom>
Loading