Select Git revision
-
Jamie Tanna authored
Introduce `external_licenses` for prioritised license lookups + consume licenses from SBOMs Closes #223 See merge request !162
Jamie Tanna authoredIntroduce `external_licenses` for prioritised license lookups + consume licenses from SBOMs Closes #223 See merge request !162
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
v1.4xml.go 2.53 KiB
package cyclonedx
import (
"bytes"
"encoding/xml"
"dmd.tanna.dev/internal/domain"
cdx "github.com/CycloneDX/cyclonedx-go"
"github.com/package-url/packageurl-go"
)
type CycloneDXv1_4XMLFormat struct{}
type cycloneDXv1_4XMLBody struct {
XMLNS string `xml:"xmlns,attr"`
}
func (s *CycloneDXv1_4XMLFormat) Matches(body []byte) bool {
var b cycloneDXv1_4XMLBody
err := xml.Unmarshal(body, &b)
if err != nil {
return false
}
if b.XMLNS != "http://cyclonedx.org/schema/bom/1.4" {
return false
}
var bom cdx.BOM
decoder := cdx.NewBOMDecoder(bytes.NewReader(body), cdx.BOMFileFormatXML)
err = decoder.Decode(&bom)
if err != nil {
return false
}
return true
}
func (s *CycloneDXv1_4XMLFormat) Name() string {
return "CycloneDX-1.4.json"
}
func (s *CycloneDXv1_4XMLFormat) Parse(body []byte, platform string, org string, repo string) ([]domain.SBOMDependency, []domain.License) {
var bom cdx.BOM
decoder := cdx.NewBOMDecoder(bytes.NewReader(body), cdx.BOMFileFormatXML)
err := decoder.Decode(&bom)
if err != nil {
return nil, nil
}
return s.parseInternal(&bom, platform, org, repo)
}
func (s *CycloneDXv1_4XMLFormat) parseInternal(bom *cdx.BOM, platform string, org string, repo string) ([]domain.SBOMDependency, []domain.License) {
if bom.Components == nil {
return nil, nil
}
var deps []domain.SBOMDependency
var licenses []domain.License
for _, c := range *bom.Components {
purl, err := packageurl.FromString(c.PackageURL)
if err != nil {
continue
}
d := domain.SBOMDependency{
Platform: platform,
Organisation: org,
Repo: repo,
PackageName: purlToPackageName(purl),
Version: toNilIfEmpty(c.Version),
CurrentVersion: currentVersion(c.Version),
PackageType: purl.Type,
}
deps = append(deps, d)
if c.Licenses == nil {
continue
}
for _, license := range *c.Licenses {
l := domain.License{
PackageName: d.PackageName,
// Version is done below
PackageManager: purl.Type,
// License is done below
}
if d.CurrentVersion != nil {
l.Version = *d.CurrentVersion
} else if d.Version != nil {
l.Version = *d.Version
}
if license.Expression != "" {
l.License = license.Expression
} else if license.License.ID != "" {
l.License = license.License.ID
} else if license.License.Name != "" {
l.License = license.License.Name
}
if !l.Valid() {
// TODO log an error here to note that the determined License object wasn't valid
continue
}
licenses = append(licenses, l)
}
}
return deps, licenses
}