Skip to content

UID2-7080: Add SLSA provenance for private operator artifacts - #2696

Merged
swibi-ttd merged 9 commits into
mainfrom
swi-UID2-7080-private-artifact-provenance
Aug 18, 2026
Merged

UID2-7080: Add SLSA provenance for private operator artifacts#2696
swibi-ttd merged 9 commits into
mainfrom
swi-UID2-7080-private-artifact-provenance

Conversation

@swibi-ttd

@swibi-ttd swibi-ttd commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add producer-side SLSA attest+verify for private operator images (GCP GHCR/GAR, Azure, EKS), EIFs/PCR0, AMI metadata, enclave-id manifests, and release ZIP archives.
  • Gate non-snapshot tag promotion and release upload on successful attestation verification (attest_file, shared attest_image@v3, plus registry --bundle-from-oci checks).
  • Document gh attestation verify usage with --signer-workflow / --bundle-from-oci; snapshots continue to skip attestation.

Notes

  • Same-run version-bump commit identity gap is unchanged (accepted; shared with public image path / UID2-6764).
  • No changes to uid2-private-operator-release, uid2-deployment, or consumer enforcement.

Test plan

  • actionlint / workflow YAML review of changed publish paths
  • Dry-run or snapshot publish confirms attestation steps are skipped for -SNAPSHOT
  • Non-snapshot GCP publish: digest push → attest GHCR+GAR → --bundle-from-oci verify → tag promotion; both tags resolve to attested digest
  • Non-snapshot Azure / EKS publish: same digest-first + attest + verify + promote flow
  • AWS Nitro: EIF/PCR0 and standalone deployment ZIPs attest before upload/release
  • AMI build verifies consumed EIF provenance before Packer; AMI metadata attested before artifact upload
  • publish-all-operators attests combined release ZIPs before action-gh-release
  • Spot-check gh attestation verify commands from README against a real non-snapshot artifact set

Made with Cursor

Gate non-snapshot private image tags and release files on attest+verify so
enclave images, measurements, and deployment archives publish with the same
producer-side provenance controls as the public operator image.

Co-authored-by: Cursor <cursoragent@cursor.com>
@UID2SourceAdmin

UID2SourceAdmin commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

🤖 AI Code Review

Generated by Azure OpenAI (gpt-5). Automated — human review is still required.

Summary

This PR adds artifact/image provenance attestation across the release pipelines: local file attestations for EIFs, manifests, AMI measurement files, and release archives; OCI attestation/verification for published images; digest-first image publishing with post-promotion digest checks; and updated README guidance for consumers to verify provenance.

Strengths

  • Verifying the consumed EIF before the AMI build is a strong supply-chain hardening step.
  • The digest-first push flow plus post-tag-resolution check is a good pattern: it avoids attesting mutable tags and then confirms the promoted tags still resolve to the attested digest.
  • Permissions were tightened explicitly on the jobs that mint attestations, instead of relying on broad defaults.

Findings

🟡 Important

Unpinned external attestation action reintroduces supply-chain risk
The new image attestation steps use IABTechLab/uid2-shared-actions/actions/attest_image@v3 by mutable tag, while the rest of the workflows are SHA-pinned. That makes the provenance path itself depend on a retargetable reference. Pin this action to a full commit SHA and keep the version in a comment.
.github/actions/build_eks_docker_image/action.yaml:162, .github/workflows/publish-azure-cc-enclave-docker.yaml:183, .github/workflows/publish-gcp-oidc-enclave-docker.yaml:188

Fresh attestation verification has no retry/backoff, so these release paths may flake
Both new composite actions do a single immediate gh attestation verify right after the attestation is created/published. GitHub attestation APIs and OCI bundle publication are not always instantly visible, so transient no attestations found failures are likely here. Wrap verification in a bounded retry loop with small backoff.
.github/actions/attest_file/action.yaml:24-38, .github/actions/verify_oci_attestation/action.yaml:20-34

🟢 Minor

verify_oci_attestation is advertised as generic, but hardcodes the current repo
The action accepts any signer_workflow, but always verifies with --repo "$GITHUB_REPOSITORY". That makes the abstraction incorrect for cross-repo signers and weaker than its input contract suggests. Add a repo input or derive owner/repo from signer_workflow.
.github/actions/verify_oci_attestation/action.yaml:29-34

README example weakens verification compared with the guidance above it
The new docs say to prefer --signer-workflow, but the public image example still uses --signer-repo, which would trust any workflow in uid2-shared-actions. Update the example to pin the exact shared workflow path as well.
README.md:83-92

Verdict

Ready to merge? With fixes

Reasoning: The overall direction is solid and materially improves provenance coverage, but the unpinned attestation action and lack of retry/backoff in the new verification steps are both worth fixing before relying on this in release pipelines.

swibi-ttd and others added 2 commits August 17, 2026 14:22
Use exact signer workflow policies so verification cannot accept a different workflow through permissive regular-expression matching.

Co-authored-by: Cursor <cursoragent@cursor.com>
Confirm Azure and EKS version tags resolve to the attested digest before their publish workflows continue.

Co-authored-by: Cursor <cursoragent@cursor.com>
@swibi-ttd

Copy link
Copy Markdown
Contributor Author

^ addressed initial comments on AI review but looks like it didn't work when i re-triggered the review workflow

@BehnamMozafari

Copy link
Copy Markdown
Contributor

Can you see if you can run a smoketest to check the new actions or one of the workflows, usually helps check the job permissions and signer repo/wf

@BehnamMozafari BehnamMozafari left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the full diff plus the pinned upstream actions (actions/attest@v4.1.0, docker/build-push-action@v7.2.0, buildx imagetools create), uid2-shared-actions/attest_image@v3, and gh attestation verify flag semantics. Four comments inline, roughly in severity order.

A few things I specifically checked and found correct, noting them so they don't get re-raised: imagetools create preserves the attested digest for a single index source (util/imagetools/create.go, the len(srcs) == 1 && len(ann) == 0 carbon-copy branch); the quoted multi-registry outputs: syntax survives build-push-action's CSV parsing ({ignoreComma: true, quote: false}); actions/attest@59d8942 is genuinely v4.1.0 and defaults to SLSA provenance with no predicate input; and --repo + --signer-workflow are compatible, with the prefix match on job_workflow_ref correctly keeping the reusable workflow as signer. Two real bug fixes in here as well — the new Zip deployment artifacts step finally creates the archives Create release was already referencing, and Prepare EIF archive for Packer now runs on the operator_release path where uid2operatoreif.zip was previously never created.

Comment thread .github/workflows/publish-aws-nitro-eif.yaml Outdated
Comment thread .github/workflows/publish-gcp-oidc-enclave-docker.yaml
Comment thread .github/actions/build_ami/action.yaml
Comment thread .github/workflows/publish-all-operators.yaml
swibi-ttd and others added 6 commits August 18, 2026 08:46
Grant the cleanup job contents write access so its standalone release path can create the draft GitHub Release after provenance checks pass.

Co-authored-by: Cursor <cursoragent@cursor.com>
Grant release jobs read access to pull requests so changelog generation can enumerate merged PR metadata under explicit token permissions.

Co-authored-by: Cursor <cursoragent@cursor.com>
Make pre-provenance AMI rebuild failures recognisable and record that the workflow currently has no compatibility bypass.

Co-authored-by: Cursor <cursoragent@cursor.com>
Disable BuildKit's redundant implicit provenance so private images remain plain single-platform manifests while signed SLSA attestations are published separately.

Co-authored-by: Cursor <cursoragent@cursor.com>
Disable imagetools index preference so private image tags resolve directly to the plain manifest that was attested and verified.

Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve the historical Docker v2 manifest format despite BuildKit's newer OCI media type default.

Co-authored-by: Cursor <cursoragent@cursor.com>
@swibi-ttd

Copy link
Copy Markdown
Contributor Author

Can you see if you can run a smoketest to check the new actions or one of the workflows, usually helps check the job permissions and signer repo/wf

Ran Azure CC and GCP pipelines from this branch as tests and tested out the attestation (more details in the ticket comments)

@swibi-ttd
swibi-ttd merged commit ec5935d into main Aug 18, 2026
24 checks passed
@swibi-ttd
swibi-ttd deleted the swi-UID2-7080-private-artifact-provenance branch August 18, 2026 03:28
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.

3 participants