-
Notifications
You must be signed in to change notification settings - Fork 42
/
cyclonedx_sbom.go
118 lines (110 loc) · 2.92 KB
/
cyclonedx_sbom.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package dxtypes
import (
"bytes"
"fmt"
"strings"
cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/yaklang/yaklang/common/filter"
"github.com/yaklang/yaklang/common/go-funk"
)
func normalCyloneDXHashType(i string) (cdx.HashAlgorithm, bool) {
switch strings.ToLower(i) {
case "md5":
return cdx.HashAlgoMD5, true
case "sha1", "sha-1":
return cdx.HashAlgoSHA1, true
case "sha256", "sha-256":
return cdx.HashAlgoSHA256, true
case "sha384", "sha-384":
return cdx.HashAlgoSHA384, true
case "sha512", "sha-512":
return cdx.HashAlgoSHA512, true
case "sha3-256", "sha3_256":
return cdx.HashAlgoSHA3_256, true
case "sha3-384", "sha3_384":
return cdx.HashAlgoSHA3_384, true
case "sha3-512", "sha3_512":
return cdx.HashAlgoSHA3_512, true
case "blake2b-256", "blake2b_256":
return cdx.HashAlgoBlake2b_256, true
case "blake2b-384", "blake2b_384":
return cdx.HashAlgoBlake2b_384, true
case "blake2b-512", "blake2b_512":
return cdx.HashAlgoBlake2b_512, true
case "blake3":
return cdx.HashAlgoBlake3, true
}
return "", false
}
func dxPackagesToCycloneDXComponent(pkgFilter *filter.StringFilter, pkgs []*Package) []cdx.Component {
ret := make([]cdx.Component, 0, len(pkgs))
for _, pkg := range pkgs {
id := fmt.Sprintf("%v-%v", pkg.Name, pkg.Version)
if pkgFilter.Exist(id) {
continue
}
pkgFilter.Insert(id)
lis := cdx.Licenses(funk.Map(pkg.License, func(s string) cdx.LicenseChoice {
return cdx.LicenseChoice{
License: &cdx.License{
BOMRef: "",
ID: "",
Name: s,
Text: nil,
URL: "",
Licensing: nil,
Properties: nil,
},
}
}).([]cdx.LicenseChoice))
var cpe string
if len(pkg.AmendedCPE) > 0 {
cpe = pkg.AmendedCPE[0]
}
var sub []cdx.Component
if pkg.DownStreamPackages != nil && len(pkg.DownStreamPackages) > 0 {
downstream := make([]*Package, 0, len(pkg.DownStreamPackages))
for _, v := range pkg.DownStreamPackages {
downstream = append(downstream, v)
}
sub = dxPackagesToCycloneDXComponent(pkgFilter, downstream)
}
var hashes []cdx.Hash
if pkg.Verification != "" {
schema, code, _ := strings.Cut(pkg.Verification, ":")
if ret, ok := normalCyloneDXHashType(schema); ok {
hashes = []cdx.Hash{
{
Algorithm: ret,
Value: code,
},
}
}
}
ret = append(ret, cdx.Component{
Name: pkg.Name,
Version: pkg.Version,
Hashes: &hashes, // pkg.Verification
Licenses: &lis,
CPE: cpe,
Components: &sub,
})
}
return ret
}
func CreateCycloneDXSBOMByDXPackages(pkgs []*Package) *cdx.BOM {
bom := cdx.NewBOM()
f := filter.NewFilter()
defer f.Close()
ret := dxPackagesToCycloneDXComponent(f, pkgs)
bom.Components = &ret
return bom
}
func MarshalCycloneDXBomToJSON(bom *cdx.BOM) ([]byte, error) {
var buf bytes.Buffer
err := cdx.NewBOMEncoder(&buf, cdx.BOMFileFormatJSON).Encode(bom)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}