@@ -320,9 +320,52 @@ def build_command:
320320
321321 # TODO consider / check what "crane validate" does and if it would be appropriate here
322322
323- # TODO generate SBOM? ... somehow
324-
325- empty
323+ if build_should_sbom then
324+ # we'll trick BuildKit into generating an SBOM for us, then inject it into our OCI layout
325+ "# SBOM" ,
326+ "originalImageManifest=\" $(jq -r '.manifests[0].digest' temp/index.json)\" " ,
327+ (
328+ [
329+ @sh "SOURCE_DATE_EPOCH=\( .source.entry.SOURCE_DATE_EPOCH ) " ,
330+ "docker buildx build --progress=plain" ,
331+ "--load=false" , "--provenance=false" , # explicitly disable a few features we want to avoid
332+ "--build-arg BUILDKIT_DOCKERFILE_CHECK=skip=all" , # disable linting (https://github.com/moby/buildkit/pull/4962)
333+ "--sbom=generator=\" $BASHBREW_BUILDKIT_SBOM_GENERATOR\" " ,
334+ "--output 'type=oci,tar=false,dest=sbom'" ,
335+ # TODO also add appropriate "--tag" lines (which would give us a mostly correct "subject" block in the generated SBOM, but we'd then need to replace instances of ${sbomImageManifest#*:} with ${originalImageManifest#*:} for their values to be correct)
336+ @sh "--platform \( .source.arches [.build.arch ].platformString ) " ,
337+ "--build-context \" fake=oci-layout://$PWD/temp@$originalImageManifest\" " ,
338+ "- <<<'FROM fake'" , # note: "<<<" is a bashism (so this output must be invoked via bash)
339+ empty
340+ ] | join (" \\\n\t " )
341+ ),
342+ "sbomIndex=\" $(jq -r '.manifests[0].digest' sbom/index.json)\" " ,
343+ @sh "shell=\" $(jq -r --arg originalImageManifest \" $originalImageManifest\" \( "
344+ # https://docs.docker.com/build/attestations/attestation-storage/
345+ first(
346+ .manifests[]
347+ | select(.annotations[\" vnd.docker.reference.type\" ] == \" attestation-manifest\" )
348+ ) as $attDesc
349+ | @sh \" sbomManifest=\\ ($attDesc.digest)\" ,
350+ @sh \" sbomManifestDesc=\\ (
351+ $attDesc
352+ | .annotations[\" vnd.docker.reference.digest\" ] = $originalImageManifest
353+ | tojson
354+ )\"
355+ " | unindent_and_decomment_jq (4 )) \" sbom/blobs/${sbomIndex/://}\" )\" " ,
356+ "eval \" $shell\" " ,
357+ @sh "shell=\" $(jq -r \( "
358+ \" copyBlobs=( \\ ([ .config.digest, .layers[].digest | @sh ] | join(\" \" )) )\"
359+ " | unindent_and_decomment_jq (4 )) \" sbom/blobs/${sbomManifest/://}\" )\" " ,
360+ "eval \" $shell\" " ,
361+ "copyBlobs+=( \" $sbomManifest\" )" ,
362+ "for blob in \" ${copyBlobs[@]}\" ; do" ,
363+ "\t cp \" sbom/blobs/${blob/://}\" \" temp/blobs/${blob/://}\" " ,
364+ "done" ,
365+ "jq -r --argjson sbomManifestDesc \" $sbomManifestDesc\" '.manifests += [ $sbomManifestDesc ]' temp/index.json > temp/index.json.new" ,
366+ "mv temp/index.json.new temp/index.json" ,
367+ empty
368+ else empty end
326369 ] | join ("\n " )
327370 else
328371 error ("unknown/unimplemented Builder: \( $builder ) " )
0 commit comments