diff --git a/convert.go b/convert.go index a1b6875..6f252e7 100644 --- a/convert.go +++ b/convert.go @@ -90,6 +90,10 @@ func (b *BOM) convert(specVersion SpecVersion) { convertVulnerabilities(b.Vulnerabilities, specVersion) } + if b.Compositions != nil { + convertCompositions(b.Compositions, specVersion) + } + if b.ExternalReferences != nil { convertExternalReferences(b.ExternalReferences, specVersion) } @@ -145,6 +149,19 @@ func componentConverter(specVersion SpecVersion) func(*Component) { } } +func convertCompositions(comps *[]Composition, specVersion SpecVersion) { + if comps == nil { + return + } + + for i := range *comps { + comp := &(*comps)[i] + if !specVersion.supportsCompositionAggregate(comp.Aggregate) { + comp.Aggregate = CompositionAggregateUnknown + } + } +} + // convertExternalReferences modifies an ExternalReference slice such that it adheres to a given SpecVersion. func convertExternalReferences(extRefs *[]ExternalReference, specVersion SpecVersion) { if extRefs == nil { @@ -342,6 +359,16 @@ func (sv SpecVersion) supportsComponentType(cType ComponentType) bool { return false } +func (sv SpecVersion) supportsCompositionAggregate(ca CompositionAggregate) bool { + switch ca { + case CompositionAggregateIncompleteFirstPartyOpenSourceOnly, CompositionAggregateIncompleteFirstPartyProprietaryOnly, + CompositionAggregateIncompleteThirdPartyOpenSourceOnly, CompositionAggregateIncompleteThirdPartyProprietaryOnly: + return sv >= SpecVersion1_5 + } + + return sv >= SpecVersion1_3 +} + func (sv SpecVersion) supportsExternalReferenceType(ert ExternalReferenceType) bool { switch ert { case ERTypeAdversaryModel, diff --git a/cyclonedx.go b/cyclonedx.go index 08f782a..54ef21e 100644 --- a/cyclonedx.go +++ b/cyclonedx.go @@ -169,20 +169,26 @@ type Component struct { } type Composition struct { - Aggregate CompositionAggregate `json:"aggregate" xml:"aggregate"` - Assemblies *[]BOMReference `json:"assemblies,omitempty" xml:"assemblies>assembly,omitempty"` - Dependencies *[]BOMReference `json:"dependencies,omitempty" xml:"dependencies>dependency,omitempty"` + BOMRef string `json:"bom-ref,omitempty" xml:"bom-ref,attr,omitempty"` + Aggregate CompositionAggregate `json:"aggregate" xml:"aggregate"` + Assemblies *[]BOMReference `json:"assemblies,omitempty" xml:"assemblies>assembly,omitempty"` + Dependencies *[]BOMReference `json:"dependencies,omitempty" xml:"dependencies>dependency,omitempty"` + Vulnerabilities *[]BOMReference `json:"vulnerabilities,omitempty" xml:"vulnerabilities>vulnerability,omitempty"` } type CompositionAggregate string const ( - CompositionAggregateComplete CompositionAggregate = "complete" - CompositionAggregateIncomplete CompositionAggregate = "incomplete" - CompositionAggregateIncompleteFirstPartyOnly CompositionAggregate = "incomplete_first_party_only" - CompositionAggregateIncompleteThirdPartyOnly CompositionAggregate = "incomplete_third_party_only" - CompositionAggregateUnknown CompositionAggregate = "unknown" - CompositionAggregateNotSpecified CompositionAggregate = "not_specified" + CompositionAggregateComplete CompositionAggregate = "complete" + CompositionAggregateIncomplete CompositionAggregate = "incomplete" + CompositionAggregateIncompleteFirstPartyOnly CompositionAggregate = "incomplete_first_party_only" + CompositionAggregateIncompleteFirstPartyOpenSourceOnly CompositionAggregate = "incomplete_first_party_opensource_only" + CompositionAggregateIncompleteFirstPartyProprietaryOnly CompositionAggregate = "incomplete_first_party_proprietary_only" + CompositionAggregateIncompleteThirdPartyOnly CompositionAggregate = "incomplete_third_party_only" + CompositionAggregateIncompleteThirdPartyOpenSourceOnly CompositionAggregate = "incomplete_third_party_opensource_only" + CompositionAggregateIncompleteThirdPartyProprietaryOnly CompositionAggregate = "incomplete_third_party_proprietary_only" + CompositionAggregateNotSpecified CompositionAggregate = "not_specified" + CompositionAggregateUnknown CompositionAggregate = "unknown" ) type Copyright struct { diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-compositions.json b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-compositions.json index 0bb37e0..ca75376 100644 --- a/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-compositions.json +++ b/testdata/snapshots/cyclonedx-go-TestRoundTripJSON-func1-valid-compositions.json @@ -46,6 +46,7 @@ ], "compositions": [ { + "bom-ref": "composition-1", "aggregate": "complete", "assemblies": [ "pkg:maven/partner/shaded-library@1.0" @@ -59,6 +60,21 @@ "assemblies": [ "pkg:maven/acme/library@3.0" ] + }, + { + "aggregate": "incomplete_first_party_only", + "vulnerabilities": [ + "vulnerability-1" + ] + } + ], + "vulnerabilities": [ + { + "bom-ref": "vulnerability-1", + "id": "ACME-12345", + "source": { + "name": "Acme Inc" + } } ] } diff --git a/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-compositions.xml b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-compositions.xml index 54aea6c..34baab1 100644 --- a/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-compositions.xml +++ b/testdata/snapshots/cyclonedx-go-TestRoundTripXML-func1-valid-compositions.xml @@ -32,7 +32,7 @@ - + complete @@ -47,5 +47,19 @@ + + incomplete_first_party_only + + + + + + + ACME-12345 + + Acme Inc + + + diff --git a/testdata/valid-compositions.json b/testdata/valid-compositions.json index 551834e..11c8a00 100644 --- a/testdata/valid-compositions.json +++ b/testdata/valid-compositions.json @@ -44,8 +44,18 @@ ] } ], + "vulnerabilities": [ + { + "bom-ref": "vulnerability-1", + "id": "ACME-12345", + "source": { + "name": "Acme Inc" + } + } + ], "compositions": [ { + "bom-ref": "composition-1", "aggregate": "complete", "assemblies": [ "pkg:maven/partner/shaded-library@1.0" @@ -59,6 +69,12 @@ "assemblies": [ "pkg:maven/acme/library@3.0" ] + }, + { + "aggregate": "incomplete_first_party_only", + "vulnerabilities": [ + "vulnerability-1" + ] } ] } diff --git a/testdata/valid-compositions.xml b/testdata/valid-compositions.xml index 82c16c5..06800df 100644 --- a/testdata/valid-compositions.xml +++ b/testdata/valid-compositions.xml @@ -31,8 +31,16 @@ + + + ACME-12345 + + Acme Inc + + + - + complete @@ -47,5 +55,11 @@ + + incomplete_first_party_only + + + +