Skip to content

UID2-6764: Add attestation_enabled opt-out to docker publish workflows#230

Merged
BehnamMozafari merged 5 commits into
mainfrom
bmz-UID2-6764-attestation-opt-out
May 12, 2026
Merged

UID2-6764: Add attestation_enabled opt-out to docker publish workflows#230
BehnamMozafari merged 5 commits into
mainfrom
bmz-UID2-6764-attestation-opt-out

Conversation

@BehnamMozafari
Copy link
Copy Markdown
Contributor

@BehnamMozafari BehnamMozafari commented May 12, 2026

Summary

Adds a boolean attestation_enabled input (default true) on the two shared docker publish workflows and the non-Java composite, and uses it to gate the existing attest_image step via the caller's if:. The attest_image composite itself is unchanged — it's the implementation; opt-out is a caller concern.

Lets private consumers opt out with one line (attestation_enabled: false) instead of granting id-token: write + attestations: write + artifact-metadata: write permissions they don't otherwise need.

Default-on means public callers do nothing — the existing six rolled out in #228 continue working unchanged.

Files

File Change
actions/attest_image/action.yaml No change. Composite stays focused on doing the attest+verify work.
actions/shared_publish_to_docker/action.yaml New attestation_enabled input (default 'true'); ANDed into the existing if: inputs.not_snapshot == 'true' on the attest_image step
.github/workflows/shared-publish-to-docker-versioned.yaml New attestation_enabled: type: boolean, default: true workflow input; piped to the composite
.github/workflows/shared-publish-java-to-docker-versioned.yaml Same — workflow input ANDed into the attest_image step's if:

Smoke test evidence

Ran on a throwaway .github/workflows/test-attest-opt-out.yaml (since deleted; following the UID2-6764 precedent where test-attest-image.yaml lived only long enough to capture run 25542801315). Two jobs simulate the caller-side gating pattern: each builds + pushes a throwaway alpine image, gates a call to ./actions/attest_image on env.ATTEST_ENABLED == 'true', then externally verifies the expected outcome.

Run 25710314847 — both jobs green:

  1. default-enabled (ATTEST_ENABLED=true):

    • Built + pushed ghcr.io/iabtechlab/uid2-shared-actions/test-attest-optout-default@<digest>
    • Call attest_image (gated, expect runs) step executed (the if: was true)
    • External gh attestation verify --owner IABTechLab --signer-repo IABTechLab/uid2-shared-actionsexit 0
    • Log: Default behavior confirmed: attestation present, verify succeeded.
  2. opted-out (ATTEST_ENABLED=false):

    • Built + pushed ghcr.io/iabtechlab/uid2-shared-actions/test-attest-optout-disabled@<digest>
    • Call attest_image (gated, expect skipped) step skipped (visible as a dash in the run summary)
    • External gh attestation verify returned Error: HTTP 404: Not Found (https://api.github.com/orgs/IABTechLab/attestations/sha256:...) confirming no attestation was created
    • Log: Opt-out confirmed: no attestation present, verify failed as expected.

How private consumers will use this

Drop one line into the calling job's with: block (instead of granting id-token/attestations/artifact-metadata perms):

jobs:
  buildImage:
    uses: IABTechLab/uid2-shared-actions/.github/workflows/shared-publish-java-to-docker-versioned.yaml@v3
    with:
      release_type: ${{ inputs.release_type }}
      attestation_enabled: false   # private repo — skip provenance

Test plan

  • Smoke test exercises both paths end-to-end against a real GHCR push + external gh attestation verify (run 25710314847)
  • After merge, re-cut v3 (release + update-major-version-tags.yaml) so consumers can use the new input
  • Use this input in the uid2-validator and uid2-alb-log-processor perm-PRs being filed under UID2-6764 follow-up

Linked: UID2-6764 (follow-up to #228)

🤖 Generated with Claude Code

BehnamMozafari and others added 5 commits May 12, 2026 12:18
Adds a boolean attestation_enabled input (default true) on the
attest_image composite and pipes it through both shared docker publish
workflows + the non-Java composite. Callers opt out with one line
(attestation_enabled: false) instead of granting id-token / attestations
/ artifact-metadata permissions they don't otherwise need.

Includes a throwaway .github/workflows/test-attest-opt-out.yaml that
exercises both paths against a built-inline alpine image and asserts via
external gh attestation verify that:
  - default: attestation exists, verify exits 0
  - opt-out: no attestation exists, verify fails with "no attestations"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Empty-attestation lookup returns "HTTP 404: Not Found" against the
GitHub attestations API, not "no attestations found". Accept either.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Evidence permanent in run 25709336298 (both jobs green). Re-add ad-hoc
if a future change to attest_image needs re-validation, mirroring the
UID2-6764 precedent (test-attest-image.yaml lived only long enough to
capture run 25542801315).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
attest_image is just the implementation — opt-out is a caller concern.
Drop the input on the composite; the existing callers already had to
gate on not_snapshot, so adding && inputs.attestation_enabled (workflow)
or && inputs.attestation_enabled == 'true' (composite) keeps the gate
where it belongs.

Re-adds the smoke workflow (deleted in the previous commit) to verify
the new caller-side gating pattern end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@BehnamMozafari BehnamMozafari merged commit ea78dcd into main May 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants