diff --git a/docs/reference/buildx_imagetools_inspect.md b/docs/reference/buildx_imagetools_inspect.md index 5ebd2401..cc53032f 100644 --- a/docs/reference/buildx_imagetools_inspect.md +++ b/docs/reference/buildx_imagetools_inspect.md @@ -287,69 +287,57 @@ $ docker buildx imagetools inspect moby/buildkit:master --format "{{json .Manife Following command provides [SLSA](https://github.com/moby/buildkit/blob/master/docs/attestations/slsa-provenance.md) JSON output: ```console -$ docker buildx imagetools inspect crazymax/buildkit:attest --format "{{json .SLSA}}" +$ docker buildx imagetools inspect crazymax/buildkit:attest --format "{{json .Provenance}}" ``` ```json { - "Provenance": { - "_type": "https://in-toto.io/Statement/v0.1", - "predicateType": "https://slsa.dev/provenance/v0.2", - "subject": [ + "SLSA": { + "builder": { + "id": "" + }, + "buildType": "https://mobyproject.org/buildkit@v1", + "materials": [ + { + "uri": "pkg:docker/docker/buildkit-syft-scanner@stable-1", + "digest": { + "sha256": "b45f1d207e16c3a3a5a10b254ad8ad358d01f7ea090d382b95c6b2ee2b3ef765" + } + }, { - "name": "pkg:docker/crazymax/buildkit@attest?platform=linux%2Famd64", + "uri": "pkg:docker/alpine@latest?platform=linux%2Famd64", "digest": { - "sha256": "fbd10fe50b4b174bb9ea273e2eb9827fa8bf5c88edd8635a93dc83e0d1aecb55" + "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4" } } ], - "predicate": { - "builder": { - "id": "" - }, - "buildType": "https://mobyproject.org/buildkit@v1", - "materials": [ - { - "uri": "pkg:docker/docker/buildkit-syft-scanner@stable-1", - "digest": { - "sha256": "b45f1d207e16c3a3a5a10b254ad8ad358d01f7ea090d382b95c6b2ee2b3ef765" - } - }, - { - "uri": "pkg:docker/alpine@latest?platform=linux%2Famd64", - "digest": { - "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4" + "invocation": { + "configSource": {}, + "parameters": { + "frontend": "dockerfile.v0", + "locals": [ + { + "name": "context" + }, + { + "name": "dockerfile" } - } - ], - "invocation": { - "configSource": {}, - "parameters": { - "frontend": "dockerfile.v0", - "locals": [ - { - "name": "context" - }, - { - "name": "dockerfile" - } - ] - }, - "environment": { - "platform": "linux/amd64" - } + ] }, - "metadata": { - "buildInvocationID": "02tdha2xkbxvin87mz9drhag4", - "buildStartedOn": "2022-12-01T11:50:07.264704131Z", - "buildFinishedOn": "2022-12-01T11:50:08.243788739Z", - "reproducible": false, - "completeness": { - "parameters": true, - "environment": true, - "materials": false - }, - "https://mobyproject.org/buildkit@v1#metadata": {} + "environment": { + "platform": "linux/amd64" } + }, + "metadata": { + "buildInvocationID": "02tdha2xkbxvin87mz9drhag4", + "buildStartedOn": "2022-12-01T11:50:07.264704131Z", + "buildFinishedOn": "2022-12-01T11:50:08.243788739Z", + "reproducible": false, + "completeness": { + "parameters": true, + "environment": true, + "materials": false + }, + "https://mobyproject.org/buildkit@v1#metadata": {} } } } @@ -363,32 +351,20 @@ $ docker buildx imagetools inspect crazymax/buildkit:attest --format "{{json .SB ```json { "SPDX": { - "_type": "https://in-toto.io/Statement/v0.1", - "predicateType": "https://spdx.dev/Document", - "subject": [ - { - "name": "pkg:docker/crazymax/buildkit@attest?platform=linux%2Famd64", - "digest": { - "sha256": "fbd10fe50b4b174bb9ea273e2eb9827fa8bf5c88edd8635a93dc83e0d1aecb55" - } - } - ], - "predicate": { - "SPDXID": "SPDXRef-DOCUMENT", - "creationInfo": { - "created": "2022-12-01T11:46:48.063400162Z", - "creators": [ - "Tool: syft-v0.60.3", - "Tool: buildkit-1ace2bb", - "Organization: Anchore, Inc" - ], - "licenseListVersion": "3.18" - }, - "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/dir/run/src/core-0a4ccc6d-1a72-4c3a-a40e-3df1a2ffca94", - "files": [...], - "spdxVersion": "SPDX-2.2" - } + "SPDXID": "SPDXRef-DOCUMENT", + "creationInfo": { + "created": "2022-12-01T11:46:48.063400162Z", + "creators": [ + "Tool: syft-v0.60.3", + "Tool: buildkit-1ace2bb", + "Organization: Anchore, Inc" + ], + "licenseListVersion": "3.18" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https://anchore.com/syft/dir/run/src/core-0a4ccc6d-1a72-4c3a-a40e-3df1a2ffca94", + "files": [...], + "spdxVersion": "SPDX-2.2" } } ``` @@ -465,97 +441,73 @@ $ docker buildx imagetools inspect crazymax/buildkit:attest --format "{{json .}} } ] }, - "SLSA": { - "Provenance": { - "_type": "https://in-toto.io/Statement/v0.1", - "predicateType": "https://slsa.dev/provenance/v0.2", - "subject": [ + "Provenance": { + "SLSA": { + "builder": { + "id": "" + }, + "buildType": "https://mobyproject.org/buildkit@v1", + "materials": [ { - "name": "pkg:docker/crazymax/buildkit@attest?platform=linux%2Famd64", + "uri": "pkg:docker/docker/buildkit-syft-scanner@stable-1", "digest": { - "sha256": "fbd10fe50b4b174bb9ea273e2eb9827fa8bf5c88edd8635a93dc83e0d1aecb55" + "sha256": "b45f1d207e16c3a3a5a10b254ad8ad358d01f7ea090d382b95c6b2ee2b3ef765" + } + }, + { + "uri": "pkg:docker/alpine@latest?platform=linux%2Famd64", + "digest": { + "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4" } } ], - "predicate": { - "builder": { - "id": "" - }, - "buildType": "https://mobyproject.org/buildkit@v1", - "materials": [ - { - "uri": "pkg:docker/docker/buildkit-syft-scanner@stable-1", - "digest": { - "sha256": "b45f1d207e16c3a3a5a10b254ad8ad358d01f7ea090d382b95c6b2ee2b3ef765" - } - }, - { - "uri": "pkg:docker/alpine@latest?platform=linux%2Famd64", - "digest": { - "sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4" + "invocation": { + "configSource": {}, + "parameters": { + "frontend": "dockerfile.v0", + "locals": [ + { + "name": "context" + }, + { + "name": "dockerfile" } - } - ], - "invocation": { - "configSource": {}, - "parameters": { - "frontend": "dockerfile.v0", - "locals": [ - { - "name": "context" - }, - { - "name": "dockerfile" - } - ] - }, - "environment": { - "platform": "linux/amd64" - } + ] }, - "metadata": { - "buildInvocationID": "02tdha2xkbxvin87mz9drhag4", - "buildStartedOn": "2022-12-01T11:50:07.264704131Z", - "buildFinishedOn": "2022-12-01T11:50:08.243788739Z", - "reproducible": false, - "completeness": { - "parameters": true, - "environment": true, - "materials": false - }, - "https://mobyproject.org/buildkit@v1#metadata": {} + "environment": { + "platform": "linux/amd64" } + }, + "metadata": { + "buildInvocationID": "02tdha2xkbxvin87mz9drhag4", + "buildStartedOn": "2022-12-01T11:50:07.264704131Z", + "buildFinishedOn": "2022-12-01T11:50:08.243788739Z", + "reproducible": false, + "completeness": { + "parameters": true, + "environment": true, + "materials": false + }, + "https://mobyproject.org/buildkit@v1#metadata": {} } } }, "SBOM": { "SPDX": { - "_type": "https://in-toto.io/Statement/v0.1", - "predicateType": "https://spdx.dev/Document", - "subject": [ - { - "name": "pkg:docker/crazymax/buildkit@attest?platform=linux%2Famd64", - "digest": { - "sha256": "fbd10fe50b4b174bb9ea273e2eb9827fa8bf5c88edd8635a93dc83e0d1aecb55" - } - } - ], - "predicate": { - "SPDXID": "SPDXRef-DOCUMENT", - "creationInfo": { - "created": "2022-12-01T11:46:48.063400162Z", - "creators": [ - "Tool: syft-v0.60.3", - "Tool: buildkit-1ace2bb", - "Organization: Anchore, Inc" - ], - "licenseListVersion": "3.18" - }, - "dataLicense": "CC0-1.0", - "documentNamespace": "https://anchore.com/syft/dir/run/src/core-0a4ccc6d-1a72-4c3a-a40e-3df1a2ffca94", - "files": [...], - "spdxVersion": "SPDX-2.2" - } + "SPDXID": "SPDXRef-DOCUMENT", + "creationInfo": { + "created": "2022-12-01T11:46:48.063400162Z", + "creators": [ + "Tool: syft-v0.60.3", + "Tool: buildkit-1ace2bb", + "Organization: Anchore, Inc" + ], + "licenseListVersion": "3.18" + }, + "dataLicense": "CC0-1.0", + "documentNamespace": "https://anchore.com/syft/dir/run/src/core-0a4ccc6d-1a72-4c3a-a40e-3df1a2ffca94", + "files": [...], + "spdxVersion": "SPDX-2.2" } } } diff --git a/util/imagetools/loader.go b/util/imagetools/loader.go index 8dbc32a6..86f5a745 100644 --- a/util/imagetools/loader.go +++ b/util/imagetools/loader.go @@ -46,9 +46,9 @@ type index struct { } type asset struct { - config *ocispec.Image - sbom *sbomStub - slsa *slsaStub + config *ocispec.Image + sbom *sbomStub + provenance *provenanceStub } type result struct { @@ -255,7 +255,8 @@ func (l *loader) scanConfig(ctx context.Context, fetcher remotes.Fetcher, desc o } type sbomStub struct { - SPDX json.RawMessage `json:",omitempty"` + SPDX interface{} `json:",omitempty"` + AdditionalSPDXs []interface{} `json:",omitempty"` } func (l *loader) scanSBOM(ctx context.Context, fetcher remotes.Fetcher, r *result, refs []digest.Digest, as *asset) error { @@ -275,8 +276,18 @@ func (l *loader) scanSBOM(ctx context.Context, fetcher remotes.Fetcher, r *resul if err != nil { return err } - as.sbom = &sbomStub{ - SPDX: dt, + var spdx struct { + Predicate interface{} `json:"predicate"` + } + if err := json.Unmarshal(dt, &spdx); err != nil { + return err + } + + if as.sbom == nil { + as.sbom = &sbomStub{} + as.sbom.SPDX = spdx.Predicate + } else { + as.sbom.AdditionalSPDXs = append(as.sbom.AdditionalSPDXs, spdx.Predicate) } } } @@ -284,8 +295,8 @@ func (l *loader) scanSBOM(ctx context.Context, fetcher remotes.Fetcher, r *resul return nil } -type slsaStub struct { - Provenance json.RawMessage `json:",omitempty"` +type provenanceStub struct { + SLSA interface{} `json:",omitempty"` } func (l *loader) scanProvenance(ctx context.Context, fetcher remotes.Fetcher, r *result, refs []digest.Digest, as *asset) error { @@ -305,9 +316,16 @@ func (l *loader) scanProvenance(ctx context.Context, fetcher remotes.Fetcher, r if err != nil { return err } - as.slsa = &slsaStub{ - Provenance: dt, + var slsa struct { + Predicate interface{} `json:"predicate"` + } + if err := json.Unmarshal(dt, &slsa); err != nil { + return err + } + as.provenance = &provenanceStub{ + SLSA: slsa.Predicate, } + break } } } @@ -328,16 +346,16 @@ func (r *result) Configs() map[string]*ocispec.Image { return res } -func (r *result) SLSA() map[string]slsaStub { +func (r *result) Provenance() map[string]provenanceStub { if len(r.assets) == 0 { return nil } - res := make(map[string]slsaStub) + res := make(map[string]provenanceStub) for p, a := range r.assets { - if a.slsa == nil { + if a.provenance == nil { continue } - res[p] = *a.slsa + res[p] = *a.provenance } return res } diff --git a/util/imagetools/printers.go b/util/imagetools/printers.go index a0b1560e..e1768353 100644 --- a/util/imagetools/printers.go +++ b/util/imagetools/printers.go @@ -99,7 +99,7 @@ func (p *Printer) Print(raw bool, out io.Writer) error { } imageconfigs := res.Configs() - slsas := res.SLSA() + provenances := res.Provenance() sboms := res.SBOM() format := tpl.Root.String() @@ -143,43 +143,43 @@ func (p *Printer) Print(raw bool, out io.Writer) error { default: if len(res.platforms) > 1 { return tpl.Execute(out, struct { - Name string `json:"name,omitempty"` - Manifest interface{} `json:"manifest,omitempty"` - Image map[string]*ocispecs.Image `json:"image,omitempty"` - SLSA map[string]slsaStub `json:"SLSA,omitempty"` - SBOM map[string]sbomStub `json:"SBOM,omitempty"` + Name string `json:"name,omitempty"` + Manifest interface{} `json:"manifest,omitempty"` + Image map[string]*ocispecs.Image `json:"image,omitempty"` + Provenance map[string]provenanceStub `json:"Provenance,omitempty"` + SBOM map[string]sbomStub `json:"SBOM,omitempty"` }{ - Name: p.name, - Manifest: mfst, - Image: imageconfigs, - SLSA: slsas, - SBOM: sboms, + Name: p.name, + Manifest: mfst, + Image: imageconfigs, + Provenance: provenances, + SBOM: sboms, }) } var ic *ocispecs.Image for _, v := range imageconfigs { ic = v } - var slsa slsaStub - for _, v := range slsas { - slsa = v + var provenance provenanceStub + for _, v := range provenances { + provenance = v } var sbom sbomStub for _, v := range sboms { sbom = v } return tpl.Execute(out, struct { - Name string `json:"name,omitempty"` - Manifest interface{} `json:"manifest,omitempty"` - Image *ocispecs.Image `json:"image,omitempty"` - SLSA slsaStub `json:"SLSA,omitempty"` - SBOM sbomStub `json:"SBOM,omitempty"` + Name string `json:"name,omitempty"` + Manifest interface{} `json:"manifest,omitempty"` + Image *ocispecs.Image `json:"image,omitempty"` + Provenance provenanceStub `json:"Provenance,omitempty"` + SBOM sbomStub `json:"SBOM,omitempty"` }{ - Name: p.name, - Manifest: mfst, - Image: ic, - SLSA: slsa, - SBOM: sbom, + Name: p.name, + Manifest: mfst, + Image: ic, + Provenance: provenance, + SBOM: sbom, }) }