diff --git a/convert.go b/convert.go
index ac27448..6c53145 100644
--- a/convert.go
+++ b/convert.go
@@ -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)
@@ -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) {
diff --git a/convert_test.go b/convert_test.go
index 251a7a2..f071258 100644
--- a/convert_test.go
+++ b/convert_test.go
@@ -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)
+ })
+}
diff --git a/cyclonedx.go b/cyclonedx.go
index f530bb7..378f878 100644
--- a/cyclonedx.go
+++ b/cyclonedx.go
@@ -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 {
@@ -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 {
diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-component-authors.json b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-component-authors.json
new file mode 100644
index 0000000..e2f8bff
--- /dev/null
+++ b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-component-authors.json
@@ -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"
+ }
+ ]
+}
+
diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-component-manufacturer.json b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-component-manufacturer.json
new file mode 100644
index 0000000..881a63c
--- /dev/null
+++ b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-component-manufacturer.json
@@ -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"
+ }
+ ]
+}
+
diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-metadata-manufacturer.json b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-metadata-manufacturer.json
new file mode 100644
index 0000000..f1eb8c0
--- /dev/null
+++ b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-metadata-manufacturer.json
@@ -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": []
+}
+
diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-component-authors.xml b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-component-authors.xml
new file mode 100644
index 0000000..73a5759
--- /dev/null
+++ b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-component-authors.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ Anthony Edward Stark
+ ironman@example.org
+ 555-212-970-4133
+
+
+ Peter Benjamin Parker
+ spiderman@example.org
+
+
+ Acme Application
+ 9.1.1
+
+
+
diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-component-manufacturer.xml b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-component-manufacturer.xml
new file mode 100644
index 0000000..6d05a1a
--- /dev/null
+++ b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-component-manufacturer.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Acme, Inc.
+ https://example.com
+
+ Acme Professional Services
+ professional.services@example.com
+
+
+ Acme Application
+ 9.1.1
+
+
+
diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-metadata-manufacturer.xml b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-metadata-manufacturer.xml
new file mode 100644
index 0000000..2050638
--- /dev/null
+++ b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-metadata-manufacturer.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ Acme, Inc.
+ https://example.com
+
+ Acme Professional Services
+ professional.services@example.com
+
+
+
+
diff --git a/testdata/valid-component-authors.json b/testdata/valid-component-authors.json
new file mode 100644
index 0000000..1d9c3fc
--- /dev/null
+++ b/testdata/valid-component-authors.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/testdata/valid-component-authors.xml b/testdata/valid-component-authors.xml
new file mode 100644
index 0000000..49e6b96
--- /dev/null
+++ b/testdata/valid-component-authors.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ Anthony Edward Stark
+ ironman@example.org
+ 555-212-970-4133
+
+
+ Peter Benjamin Parker
+ spiderman@example.org
+
+
+ Acme Application
+ 9.1.1
+
+
+
diff --git a/testdata/valid-component-manufacturer.json b/testdata/valid-component-manufacturer.json
new file mode 100644
index 0000000..9653fc0
--- /dev/null
+++ b/testdata/valid-component-manufacturer.json
@@ -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"
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/testdata/valid-component-manufacturer.xml b/testdata/valid-component-manufacturer.xml
new file mode 100644
index 0000000..f9b4d44
--- /dev/null
+++ b/testdata/valid-component-manufacturer.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ Acme, Inc.
+ https://example.com
+
+ Acme Professional Services
+ professional.services@example.com
+
+
+ Acme Application
+ 9.1.1
+
+
+
diff --git a/testdata/valid-metadata-manufacturer.json b/testdata/valid-metadata-manufacturer.json
new file mode 100644
index 0000000..838213f
--- /dev/null
+++ b/testdata/valid-metadata-manufacturer.json
@@ -0,0 +1,21 @@
+{
+ "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": []
+}
diff --git a/testdata/valid-metadata-manufacturer.xml b/testdata/valid-metadata-manufacturer.xml
new file mode 100644
index 0000000..294e4e5
--- /dev/null
+++ b/testdata/valid-metadata-manufacturer.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ Acme, Inc.
+ https://example.com
+
+ Acme Professional Services
+ professional.services@example.com
+
+
+
+
+