@@ -224,33 +224,115 @@ Every release includes:
224224
225225### Container Attestations
226226
227- ``` bash
228- export TAG=$( curl -s https://api.github.com/repos/NVIDIA/aicr/releases/latest | jq -r ' .tag_name' )
227+ Verify the ** digest-pinned** image that a tag currently resolves to. Tag refs
228+ are registry-rewritable; attestations bind to digests. Requires ` crane ` (or
229+ substitute ` docker buildx imagetools inspect ` for digest resolution).
229230
230- # GitHub CLI (core images)
231- gh attestation verify oci://ghcr.io/nvidia/aicr:${TAG} --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
232- gh attestation verify oci://ghcr.io/nvidia/aicrd:${TAG} --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
233- gh attestation verify oci://ghcr.io/nvidia/aicr-gate:${TAG} --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
231+ Predicate types attach at two different levels of the image index, so the
232+ digest you verify against depends on what you are asking for:
234233
235- # GitHub CLI (validator images)
236- gh attestation verify oci://ghcr.io/nvidia/aicr-validators/deployment: ${TAG} --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/ ${TAG} "
237- gh attestation verify oci://ghcr.io/nvidia/aicr-validators/performance: ${TAG} --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/ ${TAG} "
238- gh attestation verify oci://ghcr.io/nvidia/aicr-validators/conformance: ${TAG} --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/ ${TAG} "
239- gh attestation verify oci://ghcr.io/nvidia/aicr-validators/aiperf-bench: ${TAG} --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/ ${TAG} "
234+ | Predicate | Attached to | Verify against |
235+ | ----------- | ------------- | ---------------- |
236+ | SLSA provenance ( ` slsaprovenance1 ` ) | multi-arch index | ` crane digest <image>:<tag> ` |
237+ | OpenVEX ( ` openvex ` ) | multi-arch index | ` crane digest <image>:<tag> ` |
238+ | SBOM ( ` spdxjson ` ) | per-platform child manifest | ` crane digest --platform <os>/<arch> <image>:<tag> ` |
240239
241- # Cosign
240+ Asking for ` spdxjson ` against the index digest fails with `none of the
241+ attestations matched the predicate type`.
242+
243+ ``` bash
244+ set -euo pipefail
245+ TAG=$( gh release view --repo NVIDIA/aicr --json tagName -q .tagName)
246+ [[ -n " ${TAG} " ]] || { echo " failed to resolve latest TAG" >&2 ; exit 1; }
247+
248+ # Resolve immutable digests up front so a missing image / crane failure
249+ # aborts here (set -e) instead of being attributed to a later gh/cosign step.
250+ AICR_INDEX=$( crane digest " ghcr.io/nvidia/aicr:${TAG} " )
251+ AICRD_INDEX=$( crane digest " ghcr.io/nvidia/aicrd:${TAG} " )
252+ GATE_INDEX=$( crane digest " ghcr.io/nvidia/aicr-gate:${TAG} " )
253+ DEPLOY_INDEX=$( crane digest " ghcr.io/nvidia/aicr-validators/deployment:${TAG} " )
254+ PERF_INDEX=$( crane digest " ghcr.io/nvidia/aicr-validators/performance:${TAG} " )
255+ CONF_INDEX=$( crane digest " ghcr.io/nvidia/aicr-validators/conformance:${TAG} " )
256+ AIPERF_INDEX=$( crane digest " ghcr.io/nvidia/aicr-validators/aiperf-bench:${TAG} " )
257+
258+ # GitHub CLI (core images) — --source-ref binds the attestation to this tag
259+ gh attestation verify " oci://ghcr.io/nvidia/aicr@${AICR_INDEX} " --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
260+ gh attestation verify " oci://ghcr.io/nvidia/aicrd@${AICRD_INDEX} " --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
261+ gh attestation verify " oci://ghcr.io/nvidia/aicr-gate@${GATE_INDEX} " --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
262+
263+ # GitHub CLI (validator images)
264+ gh attestation verify " oci://ghcr.io/nvidia/aicr-validators/deployment@${DEPLOY_INDEX} " --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
265+ gh attestation verify " oci://ghcr.io/nvidia/aicr-validators/performance@${PERF_INDEX} " --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
266+ gh attestation verify " oci://ghcr.io/nvidia/aicr-validators/conformance@${CONF_INDEX} " --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
267+ gh attestation verify " oci://ghcr.io/nvidia/aicr-validators/aiperf-bench@${AIPERF_INDEX} " --repo NVIDIA/aicr --signer-workflow NVIDIA/aicr/.github/workflows/attest-images.yaml --source-ref " refs/tags/${TAG} "
268+
269+ # Cosign — provenance and OpenVEX are on the index. Pin the workflow *and*
270+ # the exact tag ref (same binding as --source-ref above): without
271+ # --certificate-github-workflow-ref, the identity regexp alone would accept
272+ # an attestation signed for any release tag on a digest this tag was
273+ # rewritten to point at.
274+ IDENTITY=' ^https://github\.com/NVIDIA/aicr/\.github/workflows/attest-images\.yaml@refs/tags/.+$'
275+ for predicate in slsaprovenance1 openvex; do
276+ cosign verify-attestation \
277+ --type " ${predicate} " \
278+ --certificate-oidc-issuer https://token.actions.githubusercontent.com \
279+ --certificate-identity-regexp " ${IDENTITY} " \
280+ --certificate-github-workflow-ref " refs/tags/${TAG} " \
281+ " ghcr.io/nvidia/aicr@${AICR_INDEX} " > /dev/null
282+ done
283+
284+ # Cosign — the SBOM is on the per-platform child manifest
285+ platform=" linux/$( uname -m | sed ' s/x86_64/amd64/;s/aarch64/arm64/' ) "
286+ AICR_CHILD=$( crane digest --platform " ${platform} " " ghcr.io/nvidia/aicr@${AICR_INDEX} " )
242287cosign verify-attestation \
243288 --type spdxjson \
244289 --certificate-oidc-issuer https://token.actions.githubusercontent.com \
245- --certificate-identity-regexp ' ^https://github\.com/NVIDIA/aicr/\.github/workflows/attest-images\.yaml@refs/tags/.+$' \
246- ghcr.io/nvidia/aicr:${TAG}
290+ --certificate-identity-regexp " ${IDENTITY} " \
291+ --certificate-github-workflow-ref " refs/tags/${TAG} " \
292+ " ghcr.io/nvidia/aicr@${AICR_CHILD} " > /dev/null
247293```
248294
249295### Binary Checksums
250296
297+ ` aicr_checksums.txt ` lists digests for release archives (and SBOMs). Download
298+ the archive you intend to verify ** and** the checksums file into the same
299+ directory, assert the archive is present and non-empty, then check ** that**
300+ file’s line — do not use ` --ignore-missing ` (it can pass with zero files
301+ verified). On macOS, use ` shasum -a 256 ` (built-in); on Linux, ` sha256sum `
302+ (GNU coreutils).
303+
251304``` bash
252- curl -sL " https://github.com/NVIDIA/aicr/releases/download/${TAG} /aicr_checksums.txt" -o checksums.txt
253- sha256sum -c checksums.txt --ignore-missing
305+ set -euo pipefail
306+ TAG=$( gh release view --repo NVIDIA/aicr --json tagName -q .tagName)
307+ [[ -n " ${TAG} " ]] || { echo " failed to resolve latest TAG" >&2 ; exit 1; }
308+
309+ os=$( uname -s | tr ' [:upper:]' ' [:lower:]' )
310+ arch=$( uname -m | sed ' s/x86_64/amd64/;s/aarch64/arm64/' )
311+ archive=" aicr_${TAG# v} _${os} _${arch} .tar.gz"
312+
313+ tmpdir=$( mktemp -d)
314+ trap ' rm -rf "${tmpdir}"' EXIT
315+ gh release download " ${TAG} " -R NVIDIA/aicr -D " ${tmpdir} " \
316+ -p " aicr_checksums.txt" \
317+ -p " ${archive} "
318+
319+ cd " ${tmpdir} "
320+ [[ -s " ${archive} " ]] || { echo " missing or empty archive: ${archive} " >&2 ; exit 1; }
321+ [[ -s aicr_checksums.txt ]] || { echo " missing aicr_checksums.txt" >&2 ; exit 1; }
322+
323+ # Fail closed: verify only the downloaded archive line from the checksums file.
324+ line=$( grep -F " ${archive} " aicr_checksums.txt) || {
325+ echo " no checksum entry for ${archive} " >&2
326+ exit 1
327+ }
328+ if command -v sha256sum > /dev/null 2>&1 ; then
329+ printf ' %s\n' " ${line} " | sha256sum -c -
330+ elif command -v shasum > /dev/null 2>&1 ; then
331+ printf ' %s\n' " ${line} " | shasum -a 256 -c -
332+ else
333+ echo " need sha256sum (GNU coreutils) or shasum" >&2
334+ exit 1
335+ fi
254336```
255337
256338## Demo Deployment
0 commit comments