CycloneDX / sbom-utility

Utility that provides an API platform for validating, querying and managing BOM data
Apache License 2.0
93 stars 13 forks source link

Add support for "legacy" and new `Tool` structure introduced in CycloneDX v1.5 #91

Open mrutkows opened 4 months ago

mrutkows commented 4 months ago

TODO: figure out how to support both current (object)/legacy(array) tools in Metadata.Tools field. Currently, we use an interface{} placeholder in our struct bindings which is NOT ideal for many things we are trying to do with entity hashing, normalization, etc.

type CDXToolLegacy struct {
    Name               string                  `json:"name,omitempty"`
    Version            string                  `json:"version,omitempty"`
    Vendor             string                  `json:"vendor,omitempty"`
    Hashes             *[]CDXHash              `json:"hashes,omitempty"`
    ExternalReferences *[]CDXExternalReference `json:"externalReferences,omitempty"`
}
type CDXTools struct {
  Components *[]CDXComponent `json:"components,omitempty"`
  Services   *[]CDXService   `json:"services,omitempty"`
}

which are both referenced from:

type CDXMetadata struct {
    Timestamp    string                      `json:"timestamp,omitempty" scvs:"bom:core:timestamp"` // urn:owasp:scvs:bom:core:timestamp
    Tools        interface{}                 `json:"tools,omitempty"`                               // v1.2: added; v1.5: "tools" is now an interface{}
    Authors      *[]CDXOrganizationalContact `json:"authors,omitempty"`
    Component    *CDXComponent               `json:"component,omitempty"`
    Manufacturer *CDXOrganizationalEntity    `json:"manufacture,omitempty"` // NOTE: Typo is in spec.
    Supplier     *CDXOrganizationalEntity    `json:"supplier,omitempty"`
    Licenses     *[]CDXLicenseChoice         `json:"licenses,omitempty"`    // v1.3 added
    Properties   *[]CDXProperty              `json:"properties,omitempty"`  // v1.3 added
    Lifecycles   *[]CDXLifecycle             `json:"lifecycles,omitempty"`  // v1.5 added
    Manufacture  *CDXOrganizationalEntity    `json:"manufacture,omitempty"` // v1.5: deprecated
}

See: https://stackoverflow.com/questions/47057240/parsing-multiple-json-types-into-the-same-struct on possible ways to do this efficiently...

mrutkows commented 4 months ago

Note: we already handle the marshaling:

    if IsInterfaceASlice(value.Tools) {
        arrayTools, ok := value.Tools.([]CDXLegacyCreationTool)
        if ok && len(arrayTools) > 0 {
            temp["tools"] = arrayTools
        }
    } else {
        tools, ok := value.Tools.(CDXCreationTools)
        if ok {
            temp["tools"] = tools
        }
    }