@@ -320,9 +320,52 @@ def build_command:
320
320
321
321
# TODO consider / check what "crane validate" does and if it would be appropriate here
322
322
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
326
369
] | join ("\n " )
327
370
else
328
371
error ("unknown/unimplemented Builder: \( $builder ) " )
0 commit comments