Skip to content

Commit 279ca59

Browse files
authored
fix cdx:1.7 integration (#303)
* fix cdx:1.7 integration * move examples into test dir * fix rm operation for license field * fix edit operation for license field
1 parent 3cda898 commit 279ca59

17 files changed

Lines changed: 1036 additions & 94 deletions

cmd/assemble.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func init() {
130130
assembleCmd.Flags().BoolP("outputSpecSpdx", "s", false, "output in SPDX format")
131131
assembleCmd.MarkFlagsMutuallyExclusive("outputSpecCdx", "outputSpecSpdx")
132132

133-
assembleCmd.Flags().StringP("outputSpecVersion", "e", "", "spec version of the output sbom (e.g., 1.5, 1.6 for CycloneDX)")
133+
assembleCmd.Flags().StringP("outputSpecVersion", "e", "", "spec version of the output sbom (e.g., 1.5, 1.6, 1.7 for CycloneDX)")
134134

135135
assembleCmd.Flags().BoolP("xml", "x", false, "output in XML format")
136136
assembleCmd.Flags().BoolP("json", "j", true, "output in JSON format")

pkg/assemble/cdx/interface.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,20 @@ var cdx_strings_to_types = map[string]cydx.ComponentType{
3737
}
3838

3939
var cdx_hash_algos = map[string]cydx.HashAlgorithm{
40-
"MD5": cydx.HashAlgoMD5,
41-
"SHA-1": cydx.HashAlgoSHA1,
42-
"SHA-256": cydx.HashAlgoSHA256,
43-
"SHA-384": cydx.HashAlgoSHA384,
44-
"SHA-512": cydx.HashAlgoSHA512,
45-
"SHA3-256": cydx.HashAlgoSHA3_256,
46-
"SHA3-384": cydx.HashAlgoSHA3_384,
47-
"SHA3-512": cydx.HashAlgoSHA3_512,
48-
"BLAKE2b-256": cydx.HashAlgoBlake2b_256,
49-
"BLAKE2b-384": cydx.HashAlgoBlake2b_384,
50-
"BLAKE2b-512": cydx.HashAlgoBlake2b_512,
51-
"BLAKE3": cydx.HashAlgoBlake3,
40+
"MD5": cydx.HashAlgoMD5,
41+
"SHA-1": cydx.HashAlgoSHA1,
42+
"SHA-256": cydx.HashAlgoSHA256,
43+
"SHA-384": cydx.HashAlgoSHA384,
44+
"SHA-512": cydx.HashAlgoSHA512,
45+
"SHA3-256": cydx.HashAlgoSHA3_256,
46+
"SHA3-384": cydx.HashAlgoSHA3_384,
47+
"SHA3-512": cydx.HashAlgoSHA3_512,
48+
"BLAKE2b-256": cydx.HashAlgoBlake2b_256,
49+
"BLAKE2b-384": cydx.HashAlgoBlake2b_384,
50+
"BLAKE2b-512": cydx.HashAlgoBlake2b_512,
51+
"BLAKE3": cydx.HashAlgoBlake3,
52+
"STREEBOG-256": cydx.HashAlgoStreebog256,
53+
"STREEBOG-512": cydx.HashAlgoStreebog512,
5254
}
5355

5456
func SupportedChecksums() []string {

pkg/assemble/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535

3636
const (
3737
DEFAULT_OUTPUT_SPEC = "cyclonedx"
38-
DEFAULT_OUTPUT_SPEC_VERSION = "1.6"
38+
DEFAULT_OUTPUT_SPEC_VERSION = "1.7"
3939
DEFAULT_OUTPUT_FILE_FORMAT = "json"
4040
DEFAULT_OUTPUT_LICENSE = "CC0-1.0"
4141
)

pkg/edit/cdx.go

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -323,35 +323,40 @@ func cdxConstructHashes(_ *cydx.BOM, c *configParams) *[]cydx.Hash {
323323
}
324324

325325
func cdxConstructLicenses(_ *cydx.BOM, c *configParams) cydx.Licenses {
326-
licenses := cydx.Licenses{}
326+
var licenses cydx.Licenses
327327

328-
for _, license := range c.licenses {
329-
if liclib.IsSpdxExpression(license.name) {
328+
for _, in := range c.licenses {
329+
330+
// SPDX expression
331+
if liclib.IsSpdxExpression(in.name) {
330332
licenses = append(licenses, cydx.LicenseChoice{
331-
Expression: license.name,
333+
Expression: in.name,
332334
})
333-
} else {
334-
lic, err := liclib.LookupSpdxLicense(license.name)
335-
if err != nil {
336-
licenses = append(licenses, cydx.LicenseChoice{
337-
License: &cydx.License{
338-
BOMRef: newBomRef(),
339-
Name: license.name,
340-
URL: license.value,
341-
},
342-
})
343-
} else {
344-
licenses = append(licenses, cydx.LicenseChoice{
345-
License: &cydx.License{
346-
BOMRef: newBomRef(),
347-
ID: lic.ShortID(),
348-
Name: lic.Name(),
349-
URL: license.value,
350-
},
351-
})
352-
}
335+
continue
336+
}
337+
338+
// SPDX license
339+
if lic, err := liclib.LookupSpdxLicense(in.name); err == nil {
340+
licenses = append(licenses, cydx.LicenseChoice{
341+
License: &cydx.License{
342+
BOMRef: newBomRef(),
343+
ID: lic.ShortID(),
344+
URL: in.value,
345+
},
346+
})
347+
continue
353348
}
349+
350+
// Custom license
351+
licenses = append(licenses, cydx.LicenseChoice{
352+
License: &cydx.License{
353+
BOMRef: newBomRef(),
354+
Name: in.name,
355+
URL: in.value,
356+
},
357+
})
354358
}
359+
355360
return licenses
356361
}
357362

pkg/rm/field/cdx/remove.go

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,7 @@ func RemoveHashFromComponent(doc *cydx.BOM, entries []interface{}, params *types
611611
func RemoveLicenseFromComponent(doc *cydx.BOM, entries []interface{}, params *types.RmParams) error {
612612
log := logger.FromContext(*params.Ctx)
613613
removedCount := 0
614+
614615
for _, e := range entries {
615616
entry, ok := e.(LicenseEntry)
616617
if !ok || entry.Value == "" {
@@ -619,58 +620,81 @@ func RemoveLicenseFromComponent(doc *cydx.BOM, entries []interface{}, params *ty
619620
}
620621

621622
comp := entry.Component
622-
found := false
623-
if doc.Metadata.Component != nil && comp == doc.Metadata.Component {
624-
found = true
625-
} else if doc.Components != nil {
626-
for i := range *doc.Components {
627-
if &(*doc.Components)[i] == comp {
628-
found = true
629-
break
630-
}
631-
}
632-
}
633-
if !found {
634-
log.Warnf("Warning: Component %s@%s not found in document\n", comp.Name, comp.Version)
623+
624+
if comp.Licenses == nil {
635625
continue
636626
}
637627

638-
if params.Value == "NOASSERTION" {
639-
log.Warnf("Warning: NOASSERTION is unlikely for license field")
640-
}
628+
var newLicenses cydx.Licenses
641629

642-
if comp.Licenses != nil {
643-
var newLicenses cydx.Licenses
644-
for _, license := range *comp.Licenses {
645-
licenseValue := license.License.ID
646-
field := "ID"
647-
if licenseValue == "" {
648-
licenseValue = license.License.Name
649-
field = "Name"
650-
}
651-
if licenseValue == "" {
652-
licenseValue = license.Expression
653-
field = "Expression"
654-
}
655-
if licenseValue == "" || !strings.EqualFold(licenseValue, entry.Value) {
656-
newLicenses = append(newLicenses, license)
657-
} else {
658-
removedCount++
659-
log.Debugf("Removed license from component: %s@%s, License: %s (Field: %s)\n",
660-
comp.Name, comp.Version, licenseValue, field)
661-
}
630+
for _, license := range *comp.Licenses {
631+
632+
remove := false
633+
634+
// Match license ID
635+
if license.License != nil &&
636+
license.License.ID != "" &&
637+
strings.EqualFold(license.License.ID, entry.Value) {
638+
639+
remove = true
640+
641+
log.Debugf(
642+
"Removed license from component: %s@%s, License: %s (Field: ID)",
643+
comp.Name,
644+
comp.Version,
645+
license.License.ID,
646+
)
662647
}
663-
comp.Licenses = &newLicenses
664-
if len(newLicenses) == 0 {
665-
comp.Licenses = nil
648+
649+
// Match license Name
650+
if license.License != nil &&
651+
license.License.Name != "" &&
652+
strings.EqualFold(license.License.Name, entry.Value) {
653+
654+
remove = true
655+
656+
log.Debugf(
657+
"Removed license from component: %s@%s, License: %s (Field: Name)",
658+
comp.Name,
659+
comp.Version,
660+
license.License.Name,
661+
)
662+
}
663+
664+
// Match expression
665+
if license.Expression != "" &&
666+
strings.EqualFold(license.Expression, entry.Value) {
667+
668+
remove = true
669+
670+
log.Debugf(
671+
"Removed license from component: %s@%s, License: %s (Field: Expression)",
672+
comp.Name,
673+
comp.Version,
674+
license.Expression,
675+
)
676+
}
677+
678+
if remove {
679+
removedCount++
680+
} else {
681+
newLicenses = append(newLicenses, license)
666682
}
667683
}
684+
685+
if len(newLicenses) == 0 {
686+
comp.Licenses = nil
687+
} else {
688+
comp.Licenses = &newLicenses
689+
}
668690
}
669691

670-
log.Debugf("Removed %d license entries from components\n", removedCount)
692+
log.Debugf("Removed %d license entries from components", removedCount)
693+
671694
if len(entries) > 0 && removedCount == 0 {
672-
log.Debugf("No license entries removed\n")
695+
log.Debugf("No license entries removed")
673696
}
697+
674698
return nil
675699
}
676700

pkg/rm/field/cdx/select.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -273,20 +273,36 @@ func SelectLicenseFromComponent(doc *cydx.BOM, params *types.RmParams) ([]interf
273273
}
274274
if c.Licenses != nil {
275275
for _, license := range *c.Licenses {
276-
licenseValue := license.License.ID
277-
field := "ID"
278-
if licenseValue == "" {
279-
licenseValue = license.License.Name
280-
field = "Name"
281-
}
282-
if licenseValue == "" {
283-
licenseValue = license.Expression
284-
field = "Expression"
276+
277+
if license.License != nil {
278+
279+
if license.License.ID != "" {
280+
selected = append(selected, LicenseEntry{
281+
Component: c,
282+
Value: license.License.ID,
283+
})
284+
log.Debugf("Selecting license from component: %s@%s, License: %s (Field: %s)",
285+
c.Name, c.Version, license.License.ID, "ID")
286+
287+
}
288+
289+
if license.License.Name != "" {
290+
selected = append(selected, LicenseEntry{
291+
Component: c,
292+
Value: license.License.Name,
293+
})
294+
log.Debugf("Selecting license from component: %s@%s, License: %s (Field: %s)",
295+
c.Name, c.Version, license.License.Name, "Name")
296+
}
285297
}
286-
if licenseValue != "" {
298+
299+
if license.Expression != "" {
300+
selected = append(selected, LicenseEntry{
301+
Component: c,
302+
Value: license.Expression,
303+
})
287304
log.Debugf("Selecting license from component: %s@%s, License: %s (Field: %s)",
288-
c.Name, c.Version, licenseValue, field)
289-
selected = append(selected, LicenseEntry{Component: c, Value: licenseValue})
305+
c.Name, c.Version, license.Expression, "Expression")
290306
}
291307
}
292308
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{
2+
"$schema": "http://cyclonedx.org/schema/bom-1.7.schema.json",
3+
"bomFormat": "CycloneDX",
4+
"specVersion": "1.7",
5+
"serialNumber": "urn:uuid:4d2edcda-fcc4-42fe-8e9d-87cf33e47b94",
6+
"version": 1,
7+
"metadata": {
8+
"timestamp": "2025-04-25T00:42:27Z",
9+
"component": {
10+
"bom-ref": "pkg:golang/github.com/kyverno/kyverno@v1.14.0?type=module#cmd/kyverno",
11+
"type": "application",
12+
"name": "github.com/kyverno/kyverno",
13+
"version": "v1.14.0",
14+
"purl": "pkg:golang/github.com/kyverno/kyverno@v1.14.0",
15+
"cpe": "cpe:/golang/github.com/kyverno/kyverno:v1.14.0",
16+
"hashes": [
17+
{
18+
"alg": "SHA-256",
19+
"content": "89fb71dddbb3389dd3018c7f63dd6350b1611f382613c5c31edfee67006ac28e"
20+
}
21+
],
22+
"licenses": [
23+
{
24+
"license": {
25+
"id": "Apache-2.0"
26+
}
27+
},
28+
{
29+
"expression": "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0"
30+
},
31+
{
32+
"expression": "LicenseRef-MIT-Style-2",
33+
"expressionDetails": [
34+
{
35+
"licenseIdentifier": "LicenseRef-MIT-Style-2",
36+
"url": "https://example.com/license"
37+
}
38+
]
39+
}
40+
]
41+
}
42+
},
43+
"components": [
44+
{
45+
"bom-ref": "pkg:golang/github.com/fluxcd/pkg/oci@v0.45.0?type=module",
46+
"type": "library",
47+
"name": "github.com/fluxcd/pkg/oci",
48+
"version": "v0.45.0",
49+
"scope": "required",
50+
"hashes": [
51+
{
52+
"alg": "SHA-256",
53+
"content": "94fb71aaacc3385dd3018c7e63dd6750b1622f382613c5c31edfee67006ac78e"
54+
}
55+
],
56+
"purl": "pkg:golang/github.com/fluxcd/pkg/oci@v0.45.0",
57+
"cpe": "cpe:2.3:a:fluxcd:oci:v0.45.0:*:*:*:*:*:*:*"
58+
},
59+
{
60+
"bom-ref": "pkg:golang/github.com/Azure/azure-sdk-for-go/sdk/azcore@v1.17.0?type=module",
61+
"type": "library",
62+
"name": "github.com/Azure/azure-sdk-for-go/sdk/azcore",
63+
"version": "v1.17.0",
64+
"scope": "required",
65+
"hashes": [
66+
{
67+
"alg": "SHA-256",
68+
"content": "834119270cfbc645d0899008e718bd7f75961580655f508f4eb47e3434e84644"
69+
}
70+
],
71+
"purl": "pkg:golang/github.com/Azure/azure-sdk-for-go/sdk/azcore@v1.17.0",
72+
"cpe": "cpe:/golang/github.com/azure/azure-sdk-for-go/sdk/azcore:v1.17.0"
73+
}
74+
],
75+
"dependencies": [
76+
{
77+
"ref": "pkg:golang/github.com/kyverno/kyverno@v1.14.0?type=module#cmd/kyverno",
78+
"dependsOn": [
79+
"pkg:golang/github.com/fluxcd/pkg/oci@v0.45.0?type=module"
80+
]
81+
},
82+
{
83+
"ref": "pkg:golang/github.com/fluxcd/pkg/oci@v0.45.0?type=module",
84+
"dependsOn": [
85+
"pkg:golang/github.com/Azure/azure-sdk-for-go/sdk/azcore@v1.17.0?type=module"
86+
]
87+
}
88+
]
89+
}
90+

0 commit comments

Comments
 (0)