From 360b27c41fdd30edcf61789b8e5dc896290f09ff Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Fri, 11 Oct 2024 10:59:01 -0400 Subject: [PATCH 1/2] Add sbom scanning command --- .test/meta-commands/out.sh | 70 ++++++++++++++++++++++++++++++++++++++ meta.jq | 55 ++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/.test/meta-commands/out.sh b/.test/meta-commands/out.sh index cf8cc9a..25fa445 100644 --- a/.test/meta-commands/out.sh +++ b/.test/meta-commands/out.sh @@ -53,6 +53,24 @@ jq ' ' temp/index.json > temp/index.json.new mv temp/index.json.new temp/index.json # +# +docker buildx build --progress=plain \ + --provenance=false \ + --sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" \ + --tag 'docker:24.0.7-cli' \ + --tag 'docker:24.0-cli' \ + --tag 'docker:24-cli' \ + --tag 'docker:cli' \ + --tag 'docker:24.0.7-cli-alpine3.18' \ + --tag 'amd64/docker:24.0.7-cli' \ + --tag 'amd64/docker:24.0-cli' \ + --tag 'amd64/docker:24-cli' \ + --tag 'amd64/docker:cli' \ + --tag 'amd64/docker:24.0.7-cli-alpine3.18' \ + --tag 'oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43' \ + --output '"type=oci","tar=false","dest=sbom"' \ + - <<<'FROM oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43@sha256:0432a4d379794811b4a2e01d0d3e67a9bcf95d6c2bf71545f03bce3f1d60f401' +# # crane push temp 'oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43' rm -rf temp @@ -88,6 +106,30 @@ SOURCE_DATE_EPOCH=1700741054 \ --file 'Dockerfile' \ 'https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/windows/windowsservercore-ltsc2022' # +# +docker buildx build --progress=plain \ + --provenance=false \ + --sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" \ + --tag 'docker:24.0.7-windowsservercore-ltsc2022' \ + --tag 'docker:24.0-windowsservercore-ltsc2022' \ + --tag 'docker:24-windowsservercore-ltsc2022' \ + --tag 'docker:windowsservercore-ltsc2022' \ + --tag 'docker:24.0.7-windowsservercore' \ + --tag 'docker:24.0-windowsservercore' \ + --tag 'docker:24-windowsservercore' \ + --tag 'docker:windowsservercore' \ + --tag 'winamd64/docker:24.0.7-windowsservercore-ltsc2022' \ + --tag 'winamd64/docker:24.0-windowsservercore-ltsc2022' \ + --tag 'winamd64/docker:24-windowsservercore-ltsc2022' \ + --tag 'winamd64/docker:windowsservercore-ltsc2022' \ + --tag 'winamd64/docker:24.0.7-windowsservercore' \ + --tag 'winamd64/docker:24.0-windowsservercore' \ + --tag 'winamd64/docker:24-windowsservercore' \ + --tag 'winamd64/docker:windowsservercore' \ + --tag 'oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e' \ + --output '"type=oci","tar=false","dest=sbom"' \ + - <<<'FROM oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e@sha256:69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce' +# # docker push 'oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e' # @@ -174,6 +216,34 @@ done jq -r --argjson sbomManifestDesc "$sbomManifestDesc" '.manifests += [ $sbomManifestDesc ]' temp/index.json > temp/index.json.new mv temp/index.json.new temp/index.json # +# +docker buildx build --progress=plain \ + --provenance=false \ + --sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" \ + --tag 'busybox:1.36.1' \ + --tag 'busybox:1.36' \ + --tag 'busybox:1' \ + --tag 'busybox:stable' \ + --tag 'busybox:latest' \ + --tag 'busybox:1.36.1-glibc' \ + --tag 'busybox:1.36-glibc' \ + --tag 'busybox:1-glibc' \ + --tag 'busybox:stable-glibc' \ + --tag 'busybox:glibc' \ + --tag 'amd64/busybox:1.36.1' \ + --tag 'amd64/busybox:1.36' \ + --tag 'amd64/busybox:1' \ + --tag 'amd64/busybox:stable' \ + --tag 'amd64/busybox:latest' \ + --tag 'amd64/busybox:1.36.1-glibc' \ + --tag 'amd64/busybox:1.36-glibc' \ + --tag 'amd64/busybox:1-glibc' \ + --tag 'amd64/busybox:stable-glibc' \ + --tag 'amd64/busybox:glibc' \ + --tag 'oisupport/staging-amd64:191402ad0feacf03daf9d52a492207e73ef08b0bd17265043aea13aa27e2bb3f' \ + --output '"type=oci","tar=false","dest=sbom"' \ + - <<<'FROM oisupport/staging-amd64:191402ad0feacf03daf9d52a492207e73ef08b0bd17265043aea13aa27e2bb3f@sha256:4be429a5fbb2e71ae7958bfa558bc637cf3a61baf40a708cb8fff532b39e52d0' +# # crane push --index temp 'oisupport/staging-amd64:191402ad0feacf03daf9d52a492207e73ef08b0bd17265043aea13aa27e2bb3f' rm -rf temp diff --git a/meta.jq b/meta.jq index 947531e..77b007d 100644 --- a/meta.jq +++ b/meta.jq @@ -369,6 +369,60 @@ def build_command: error("unknown/unimplemented Builder: \($builder)") end ; + +# input: "build" object (with "buildId" top level key) +def image_digest: + .build.resolved.manifests[0].digest +; + +# input: "build" object (with "buildId" top level key) +def image_ref: + "\(.build.img)@\(image_digest)" +; + +# input: "build" object (with "buildId" top level key) +# output: string "command for generating an SBOM from an OCI layout", may be multiple lines, expects to run in Bash with "set -Eeuo pipefail" +def sbom_command: + [ + ( + [ + "docker buildx build --progress=plain", + "--provenance=false", + "--sbom=generator=\"$BASHBREW_BUILDKIT_SBOM_GENERATOR\"", + ( + ( + .source.arches[.build.arch] + | .tags[], .archTags[] + ), + .build.img + | "--tag " + @sh + ), + "--output " + ( + [ + "type=oci", + "tar=false", + "dest=sbom", + empty + ] + | @csv + | @sh + ), + "- <<<" + ( + [ + "FROM ", + image_ref, + empty + ] + | join("") + | @sh + ), + empty + ] | join(" \\\n\t") + ), + empty + ] | join("\n") +; + # input: "build" object (with "buildId" top level key) # output: string "push command" ("docker push ..."), may be multiple lines, expects to run in Bash with "set -Eeuo pipefail" def push_command: @@ -398,6 +452,7 @@ def commands: { pull: pull_command, build: build_command, + sbom_scan: sbom_command, push: push_command, } ; From e49263ec90631af550e29fb3902e126bc2fc6b98 Mon Sep 17 00:00:00 2001 From: Laurent Goderre Date: Wed, 16 Oct 2024 11:35:50 -0400 Subject: [PATCH 2/2] wip --- .test/meta-commands/out.sh | 66 ++++++++++++++++++++++++++++++++++---- meta.jq | 51 +++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 8 deletions(-) diff --git a/.test/meta-commands/out.sh b/.test/meta-commands/out.sh index 25fa445..4807a46 100644 --- a/.test/meta-commands/out.sh +++ b/.test/meta-commands/out.sh @@ -54,7 +54,8 @@ jq ' mv temp/index.json.new temp/index.json # # -docker buildx build --progress=plain \ +build_output=$( + docker buildx build --progress=rawjson \ --provenance=false \ --sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" \ --tag 'docker:24.0.7-cli' \ @@ -69,7 +70,24 @@ docker buildx build --progress=plain \ --tag 'amd64/docker:24.0.7-cli-alpine3.18' \ --tag 'oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43' \ --output '"type=oci","tar=false","dest=sbom"' \ - - <<<'FROM oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43@sha256:0432a4d379794811b4a2e01d0d3e67a9bcf95d6c2bf71545f03bce3f1d60f401' + - <<<'FROM oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43@sha256:0432a4d379794811b4a2e01d0d3e67a9bcf95d6c2bf71545f03bce3f1d60f401' 2>&1 +) +attest_manifest_digest=$( + echo "$build_output" | jq -rs ' + .[] + | select(.statuses).statuses[] + | select((.completed != null) and (.id | startswith("exporting attestation manifest"))).id + | sub("exporting attestation manifest "; "") + ' +) +sbom_digest=$( + jq -r ' + .layers[] | select(.annotations["in-toto.io/predicate-type"] == "https://spdx.dev/Document").digest + ' "sbom/blobs/${attest_manifest_digest//://}" +) +jq -c --arg digest "sha256:0432a4d379794811b4a2e01d0d3e67a9bcf95d6c2bf71545f03bce3f1d60f401" ' + .subject[].digest |= ($digest | split(":") | {(.[0]): .[1]}) +' "sbom/blobs/${sbom_digest//://}" > sbom.json # # crane push temp 'oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43' @@ -107,7 +125,8 @@ SOURCE_DATE_EPOCH=1700741054 \ 'https://github.com/docker-library/docker.git#6d541d27b5dd12639e5a33a675ebca04d3837d74:24/windows/windowsservercore-ltsc2022' # # -docker buildx build --progress=plain \ +build_output=$( + docker buildx build --progress=rawjson \ --provenance=false \ --sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" \ --tag 'docker:24.0.7-windowsservercore-ltsc2022' \ @@ -128,7 +147,24 @@ docker buildx build --progress=plain \ --tag 'winamd64/docker:windowsservercore' \ --tag 'oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e' \ --output '"type=oci","tar=false","dest=sbom"' \ - - <<<'FROM oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e@sha256:69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce' + - <<<'FROM oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e@sha256:69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce' 2>&1 +) +attest_manifest_digest=$( + echo "$build_output" | jq -rs ' + .[] + | select(.statuses).statuses[] + | select((.completed != null) and (.id | startswith("exporting attestation manifest"))).id + | sub("exporting attestation manifest "; "") + ' +) +sbom_digest=$( + jq -r ' + .layers[] | select(.annotations["in-toto.io/predicate-type"] == "https://spdx.dev/Document").digest + ' "sbom/blobs/${attest_manifest_digest//://}" +) +jq -c --arg digest "sha256:69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce" ' + .subject[].digest |= ($digest | split(":") | {(.[0]): .[1]}) +' "sbom/blobs/${sbom_digest//://}" > sbom.json # # docker push 'oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e' @@ -217,7 +253,8 @@ jq -r --argjson sbomManifestDesc "$sbomManifestDesc" '.manifests += [ $sbomManif mv temp/index.json.new temp/index.json # # -docker buildx build --progress=plain \ +build_output=$( + docker buildx build --progress=rawjson \ --provenance=false \ --sbom=generator="$BASHBREW_BUILDKIT_SBOM_GENERATOR" \ --tag 'busybox:1.36.1' \ @@ -242,7 +279,24 @@ docker buildx build --progress=plain \ --tag 'amd64/busybox:glibc' \ --tag 'oisupport/staging-amd64:191402ad0feacf03daf9d52a492207e73ef08b0bd17265043aea13aa27e2bb3f' \ --output '"type=oci","tar=false","dest=sbom"' \ - - <<<'FROM oisupport/staging-amd64:191402ad0feacf03daf9d52a492207e73ef08b0bd17265043aea13aa27e2bb3f@sha256:4be429a5fbb2e71ae7958bfa558bc637cf3a61baf40a708cb8fff532b39e52d0' + - <<<'FROM oisupport/staging-amd64:191402ad0feacf03daf9d52a492207e73ef08b0bd17265043aea13aa27e2bb3f@sha256:4be429a5fbb2e71ae7958bfa558bc637cf3a61baf40a708cb8fff532b39e52d0' 2>&1 +) +attest_manifest_digest=$( + echo "$build_output" | jq -rs ' + .[] + | select(.statuses).statuses[] + | select((.completed != null) and (.id | startswith("exporting attestation manifest"))).id + | sub("exporting attestation manifest "; "") + ' +) +sbom_digest=$( + jq -r ' + .layers[] | select(.annotations["in-toto.io/predicate-type"] == "https://spdx.dev/Document").digest + ' "sbom/blobs/${attest_manifest_digest//://}" +) +jq -c --arg digest "sha256:4be429a5fbb2e71ae7958bfa558bc637cf3a61baf40a708cb8fff532b39e52d0" ' + .subject[].digest |= ($digest | split(":") | {(.[0]): .[1]}) +' "sbom/blobs/${sbom_digest//://}" > sbom.json # # crane push --index temp 'oisupport/staging-amd64:191402ad0feacf03daf9d52a492207e73ef08b0bd17265043aea13aa27e2bb3f' diff --git a/meta.jq b/meta.jq index 77b007d..6ff7632 100644 --- a/meta.jq +++ b/meta.jq @@ -384,9 +384,10 @@ def image_ref: # output: string "command for generating an SBOM from an OCI layout", may be multiple lines, expects to run in Bash with "set -Eeuo pipefail" def sbom_command: [ + "build_output=$(", ( [ - "docker buildx build --progress=plain", + "\tdocker buildx build --progress=rawjson", "--provenance=false", "--sbom=generator=\"$BASHBREW_BUILDKIT_SBOM_GENERATOR\"", ( @@ -415,10 +416,56 @@ def sbom_command: ] | join("") | @sh - ), + ) + " 2>&1", empty ] | join(" \\\n\t") ), + ")", + # Using the method above assigns the wrong image digest in the SBOM subjects. This replaces it with the correct one + # Get the digest of the attestation manifest provided by BuildKit + "attest_manifest_digest=$(", + ( + [ + "\techo \"$build_output\" | jq -rs '", + ( + [ + "\t.[]", + "| select(.statuses).statuses[]", + "| select((.completed != null) and (.id | startswith(\"exporting attestation manifest\"))).id", + "| sub(\"exporting attestation manifest \"; \"\")", + empty + ] | join("\n\t\t") + ), + "'", + empty + ] | join("\n\t") + ), + ")", + # Find the SBOM digest from the attestation manifest + "sbom_digest=$(", + ( + [ + "\tjq -r '", + ( + [ + "\t.layers[] | select(.annotations[\"in-toto.io/predicate-type\"] == \"https://spdx.dev/Document\").digest", + empty + ] | join("\n\t\t") + ), + "' \"sbom/blobs/${attest_manifest_digest//://}\"", + empty + ] | join("\n\t") + ), + ")", + # Replace the subjects digests + "jq -c --arg digest \"\(image_digest)\" '", + ( + [ + "\t.subject[].digest |= ($digest | split(\":\") | {(.[0]): .[1]})", + empty + ] | join("\n\t") + ), + "' \"sbom/blobs/${sbom_digest//://}\" > sbom.json", empty ] | join("\n") ;