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