feat(sbom): add support for CycloneDX JSON Attestation of the correct specification (#3849)

This commit is contained in:
saso
2023-03-19 22:40:58 +09:00
committed by GitHub
parent a754a04e2b
commit ba9b0410c9
2 changed files with 44 additions and 6 deletions

View File

@@ -73,7 +73,7 @@ func (a Artifact) Inspect(_ context.Context) (types.ArtifactReference, error) {
var artifactType types.ArtifactType
switch format {
case sbom.FormatCycloneDXJSON, sbom.FormatCycloneDXXML, sbom.FormatAttestCycloneDXJSON:
case sbom.FormatCycloneDXJSON, sbom.FormatCycloneDXXML, sbom.FormatAttestCycloneDXJSON, sbom.FormatLegacyCosignAttestCycloneDXJSON:
artifactType = types.ArtifactCycloneDX
case sbom.FormatSPDXTV, sbom.FormatSPDXJSON:
artifactType = types.ArtifactSPDX

View File

@@ -27,6 +27,11 @@ const (
FormatAttestCycloneDXJSON Format = "attest-cyclonedx-json"
FormatUnknown Format = "unknown"
// FormatLegacyCosignAttestCycloneDXJSON is used to support the older format of CycloneDX JSON Attestation
// produced by the Cosign V1.
// ref. https://github.com/sigstore/cosign/pull/2718
FormatLegacyCosignAttestCycloneDXJSON Format = "legacy-cosign-attest-cyclonedx-json"
// PredicateCycloneDXBeforeV05 is the PredicateCycloneDX value defined in in-toto-golang before v0.5.0.
// This is necessary for backward-compatible SBOM detection.
// ref. https://github.com/in-toto/in-toto-golang/pull/188
@@ -100,16 +105,41 @@ func DetectFormat(r io.ReadSeeker) (Format, error) {
}
// Try in-toto attestation
var s attestation.Statement
if err := json.NewDecoder(r).Decode(&s); err == nil {
if s.PredicateType == in_toto.PredicateCycloneDX || s.PredicateType == PredicateCycloneDXBeforeV05 {
return FormatAttestCycloneDXJSON, nil
}
format, ok := decodeAttestCycloneDXJSONFormat(r)
if ok {
return format, nil
}
return FormatUnknown, nil
}
func decodeAttestCycloneDXJSONFormat(r io.ReadSeeker) (Format, bool) {
var s attestation.Statement
if err := json.NewDecoder(r).Decode(&s); err != nil {
return "", false
}
if s.PredicateType != in_toto.PredicateCycloneDX && s.PredicateType != PredicateCycloneDXBeforeV05 {
return "", false
}
if s.Predicate == nil {
return "", false
}
m, ok := s.Predicate.(map[string]interface{})
if !ok {
return "", false
}
if _, ok := m["Data"]; ok {
return FormatLegacyCosignAttestCycloneDXJSON, true
}
return FormatAttestCycloneDXJSON, true
}
func Decode(f io.Reader, format Format) (types.SBOM, error) {
var (
v interface{}
@@ -122,6 +152,14 @@ func Decode(f io.Reader, format Format) (types.SBOM, error) {
v = &cyclonedx.CycloneDX{SBOM: &bom}
decoder = json.NewDecoder(f)
case FormatAttestCycloneDXJSON:
// dsse envelope
// => in-toto attestation
// => CycloneDX JSON
v = &attestation.Statement{
Predicate: &cyclonedx.CycloneDX{SBOM: &bom},
}
decoder = json.NewDecoder(f)
case FormatLegacyCosignAttestCycloneDXJSON:
// dsse envelope
// => in-toto attestation
// => cosign predicate