Skip to content
Snippets Groups Projects
Select Git revision
  • renovate/major-opa
  • docs/pattern
  • main default protected
  • spike/go-tools-124-gql
  • spike/go-tools-124
  • chore/deepmap
  • docs/mas
  • build/notify
  • fix/du
  • defect/diff
  • defect/json
  • chore/schema
  • feat/diff-json
  • chore/typo
  • build/binaries
  • build/changelog-
  • defect/otel
  • chore/otel
  • chore/dep
  • docs/changelog
  • v0.116.0 protected
  • v0.115.3 protected
  • v0.115.2 protected
  • v0.115.1 protected
  • v0.115.0 protected
  • v0.114.0 protected
  • v0.113.5 protected
  • v0.113.4 protected
  • v0.113.3 protected
  • v0.113.2 protected
  • v0.113.1 protected
  • v0.113.0 protected
  • v0.112.0 protected
  • v0.111.1 protected
  • v0.111.0 protected
  • v0.110.2 protected
  • v0.110.1 protected
  • v0.110.0 protected
  • v0.109.0 protected
  • v0.108.0 protected
40 results

v1.4xml.go

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
}