|
1 | 1 | #!/usr/bin/env bash |
2 | 2 | set -euo pipefail |
3 | 3 |
|
4 | | -IMAGE_URI="$1" |
| 4 | +IMAGE_URI="${1:?Usage: deploy-verify.sh IMAGE_URI}" |
5 | 5 | REPO="acme/payments-api" |
| 6 | +SIGNER_WORKFLOW="acme/payments-api/.github/workflows/release.yml" |
6 | 7 |
|
7 | 8 | echo "1) Verify Sigstore signature" |
8 | 9 | cosign verify \ |
9 | 10 | --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ |
10 | | - --certificate-identity-regexp "https://github.com/acme/payments-api/.github/workflows/release.yml@refs/heads/main" \ |
| 11 | + --certificate-identity-regexp "https://github.com/${SIGNER_WORKFLOW}@refs/heads/main" \ |
11 | 12 | "${IMAGE_URI}" >/dev/null |
12 | 13 |
|
| 14 | +# Verification uses GitHub API lookup by default (requires network access to |
| 15 | +# api.github.com). For air-gapped or OCI-native verification, add |
| 16 | +# --bundle-from-oci instead of -R. See: |
| 17 | +# https://cli.github.com/manual/gh_attestation_verify |
13 | 18 | echo "2) Verify build provenance" |
14 | 19 | gh attestation verify \ |
15 | 20 | "oci://${IMAGE_URI}" \ |
16 | | - -R "${REPO}" >/dev/null |
| 21 | + -R "${REPO}" \ |
| 22 | + --signer-workflow "${SIGNER_WORKFLOW}" >/dev/null |
17 | 23 |
|
18 | 24 | echo "3) Verify SBOM attestation" |
19 | 25 | gh attestation verify \ |
20 | 26 | "oci://${IMAGE_URI}" \ |
21 | 27 | -R "${REPO}" \ |
| 28 | + --signer-workflow "${SIGNER_WORKFLOW}" \ |
22 | 29 | --predicate-type "https://spdx.dev/Document/v2.3" >/dev/null |
23 | 30 |
|
24 | 31 | echo "4) Pull SBOM payload for policy checks" |
25 | 32 | gh attestation verify \ |
26 | 33 | "oci://${IMAGE_URI}" \ |
27 | 34 | -R "${REPO}" \ |
| 35 | + --signer-workflow "${SIGNER_WORKFLOW}" \ |
28 | 36 | --predicate-type "https://spdx.dev/Document/v2.3" \ |
29 | 37 | --format json \ |
30 | 38 | --jq '.[].verificationResult.statement.predicate' > verified-sbom.json |
31 | 39 |
|
32 | | -# Check that the SBOM contains package data (SPDX uses .packages, CycloneDX uses .components) |
33 | | -jq -e '.packages // .components | length > 0' verified-sbom.json >/dev/null |
| 40 | +echo "4a) Check SBOM contains package data" |
| 41 | +jq -e '(.packages // .components) | length > 0' verified-sbom.json >/dev/null |
| 42 | + |
| 43 | +echo "4b) Check all packages have non-empty names" |
| 44 | +jq -e '[(.packages // .components)[] | select(.name == null or .name == "")] | length == 0' verified-sbom.json >/dev/null |
| 45 | + |
| 46 | +echo "4c) Check all packages have versions" |
| 47 | +jq -e '[(.packages // .components)[] | select(.versionInfo == null and .version == null)] | length == 0' verified-sbom.json >/dev/null |
| 48 | + |
| 49 | +echo "4d) Check license information is present" |
| 50 | +jq -e '[(.packages // .components)[] | select(.licenseConcluded != null or .licenseDeclared != null or .licenses != null)] | length > 0' verified-sbom.json >/dev/null |
34 | 51 |
|
35 | 52 | echo "All supply-chain checks passed" |
0 commit comments