feat(ci): sign Docker images with Sigstore cosign keyless OIDC - #435
Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 4 minutes and 51 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (40)
📝 WalkthroughWalkthroughThis pull request adds cryptographic signing and verification for Docker images using Sigstore cosign with keyless OIDC authentication. The CI/CD workflow is updated to sign released images and verify signatures during smoke tests, while documentation is expanded to guide users and maintainers through the signing and verification processes. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Dependency ReviewThe following issues were found:
License Issuespom.xml
OpenSSF Scorecard
Scanned Files
|
There was a problem hiding this comment.
Pull request overview
This PR adds Sigstore cosign keyless (OIDC) signing for Docker images produced by the GitHub Actions CI pipeline, and documents how users can verify image signatures to improve release integrity.
Changes:
- Update CI workflow to install cosign, sign pushed Docker images using GitHub OIDC, and verify signatures during smoke tests.
- Add new documentation explaining the signing model and verification commands.
- Link signing documentation from existing release/versioning and security docs.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/ci.yml |
Adds cosign install/sign steps after Docker push and signature verification in smoke-test; exports image digest output. |
docs/release-signing.md |
New guide describing signing flow and verification commands. |
SECURITY.md |
Adds “Release Integrity” section with cosign verification snippet. |
docs/SUMMARY.md |
Adds the new signing doc to the docs table of contents. |
docs/release-versioning.md |
References signing as part of the release process and recommends signed git tags. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)
487-537: Consider signing by digest instead of by tag to avoid race conditions and align with cosign best practices.
cosign sign ${DOCKER_IMAGE}:${PRIMARY_TAG}resolves the tag to a manifest digest at sign time. Betweendocker push(line 494) andcosign sign(line 522), the tag could in principle be overwritten—or on re-run, point to a different manifest—causing you to sign the wrong artifact. Signinglatest,major, andminoraliases by tag has the same caveat. Additionally, cosign v3.x emits a warning when signing by tag; the documented recommendation is to sign by digest.Since you already capture
DIGESTat line 504, the cleanest solution is to sign that digest once:cosign sign --yes ${DOCKER_IMAGE}@${DIGEST}. The signature is cryptographically bound to the manifest digest, so verification succeeds for any tag pointing to that digest (primary, minor/major aliases, and latest all resolve to the same digest). This also eliminates the conditional signing logic and removes the cosign warning.♻️ Proposed refactor: sign the digest once
- name: Push to Docker Hub id: push run: | PRIMARY_TAG="${{ steps.meta.outputs.primary-tag }}" IS_RELEASE="${{ steps.meta.outputs.is-release }}" IS_STABLE="${{ steps.meta.outputs.is-stable }}" docker push ${DOCKER_IMAGE}:${PRIMARY_TAG} if [[ "$IS_STABLE" == "true" ]]; then docker push ${DOCKER_IMAGE}:${{ steps.meta.outputs.minor-tag }} docker push ${DOCKER_IMAGE}:${{ steps.meta.outputs.major-tag }} fi if [[ "$IS_RELEASE" == "true" ]]; then docker push ${DOCKER_IMAGE}:latest fi - # Capture the image digest for audit logging (non-blocking) - DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' ${DOCKER_IMAGE}:${PRIMARY_TAG} 2>/dev/null | cut -d@ -f2 || true) + # Capture the image digest (required for sign-by-digest below) + DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' ${DOCKER_IMAGE}:${PRIMARY_TAG} | cut -d@ -f2) + if [ -z "$DIGEST" ]; then + echo "::error::Failed to resolve digest for ${DOCKER_IMAGE}:${PRIMARY_TAG}" + exit 1 + fi echo "digest=${DIGEST}" >> $GITHUB_OUTPUT echo "### ✅ Pushed to Docker Hub" >> $GITHUB_STEP_SUMMARY - if [ -n "$DIGEST" ]; then - echo "- Digest: \`${DIGEST}\`" >> $GITHUB_STEP_SUMMARY - fi + echo "- Digest: \`${DIGEST}\`" >> $GITHUB_STEP_SUMMARY - name: Install cosign uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 - name: Sign Docker images (keyless) run: | - PRIMARY_TAG="${{ steps.meta.outputs.primary-tag }}" - IS_RELEASE="${{ steps.meta.outputs.is-release }}" - IS_STABLE="${{ steps.meta.outputs.is-stable }}" - - echo "=== Signing ${DOCKER_IMAGE}:${PRIMARY_TAG} ===" - cosign sign --yes ${DOCKER_IMAGE}:${PRIMARY_TAG} - - if [[ "$IS_STABLE" == "true" ]]; then - echo "=== Signing semver aliases ===" - cosign sign --yes ${DOCKER_IMAGE}:${{ steps.meta.outputs.minor-tag }} - cosign sign --yes ${DOCKER_IMAGE}:${{ steps.meta.outputs.major-tag }} - fi - - if [[ "$IS_RELEASE" == "true" ]]; then - echo "=== Signing latest ===" - cosign sign --yes ${DOCKER_IMAGE}:latest - fi + DIGEST="${{ steps.push.outputs.digest }}" + echo "=== Signing ${DOCKER_IMAGE}@${DIGEST} ===" + cosign sign --yes ${DOCKER_IMAGE}@${DIGEST}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/ci.yml around lines 487 - 537, The workflow signs images by tag (cosign sign ${DOCKER_IMAGE}:${PRIMARY_TAG}) which can race if tags move; instead use the captured DIGEST and sign the immutable manifest: after computing DIGEST (variable DIGEST from the "Push to Docker Hub" step) call cosign sign against ${DOCKER_IMAGE}@${DIGEST} (use that single sign invocation and remove per-tag signing of ${PRIMARY_TAG}, minor/major aliases, and latest), and update the verification/help text to reference the image@digest form so signatures are cryptographically bound to the pushed manifest.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 549-556: The cosign verify invocation using
--certificate-identity-regexp currently passes an unescaped, unanchored Go
regex; change the regexp passed to --certificate-identity-regexp in the cosign
verify step so all literal dots are escaped, the pattern is anchored (start and
end) and it optionally allows the GitHub Actions subject suffix (an `@ref` tail),
then update the same pattern in the related docs/snippets (SECURITY.md,
docs/release-signing.md and the sign step summary) so they match the hardened,
anchored regexp; the change should be made at the cosign verify command that
contains --certificate-oidc-issuer and --certificate-identity-regexp in the
workflow.
In `@docs/release-signing.md`:
- Around line 68-76: Replace the misleading Linux section that currently
recommends "go install github.com/sigstore/cosign/v2/cmd/cosign@latest" under
the "# Linux" heading with instructions that point users to download the
official release binary or use a distro package if available; specifically,
remove the Go-based install suggestion and instead mention the GitHub releases
page for prebuilt Linux binaries and note package manager options (e.g.,
apt/yum/homebrew on Linux) as alternatives, plus a short note that "go install"
requires a Go toolchain and is not Linux-specific.
- Around line 115-121: The Rekor search example is incorrect for GitHub Actions
keyless signatures because the certificate SAN uses a URI, not an email; update
the "Inspect the Transparency Log" section to remove or replace the email-based
URL (https://search.sigstore.dev/?email=github.com/labsai/EDDI) and either (a)
provide a URI-based Rekor Search query if supported (matching the Fulcio SAN
format like https://github.com/labsai/EDDI/.github/workflows/ci.yml@refs/tags/…)
or (b) drop the web-search example and instead show the direct retrieval
commands using cosign (e.g., reference the cosign verify --output-file and
cosign tree commands) so readers can reliably locate the Rekor entry for GitHub
Actions keyless signatures.
---
Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 487-537: The workflow signs images by tag (cosign sign
${DOCKER_IMAGE}:${PRIMARY_TAG}) which can race if tags move; instead use the
captured DIGEST and sign the immutable manifest: after computing DIGEST
(variable DIGEST from the "Push to Docker Hub" step) call cosign sign against
${DOCKER_IMAGE}@${DIGEST} (use that single sign invocation and remove per-tag
signing of ${PRIMARY_TAG}, minor/major aliases, and latest), and update the
verification/help text to reference the image@digest form so signatures are
cryptographically bound to the pushed manifest.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: ea1477ea-607c-4f77-855c-383a317a67b2
📒 Files selected for processing (5)
.github/workflows/ci.ymlSECURITY.mddocs/SUMMARY.mddocs/release-signing.mddocs/release-versioning.md
0cc0dec to
33a9d1f
Compare
- Add cosign sign step to docker job (keyless via GitHub OIDC) - Add cosign verify step to smoke-test as regression gate - Scope id-token:write to docker job only (least privilege) - Pin cosign-installer to v4.1.1 by SHA - Strict anchored regexp for certificate identity verification - Add docs/release-signing.md with user verification guide - Update SECURITY.md, release-versioning.md, SUMMARY.md - Satisfies OpenSSF Silver signed_releases + version_tags_signed
33a9d1f to
764bf47
Compare
…WireMock 3.13.2 - Dockerfile.jvm: update ubi9/openjdk-25-runtime digest to fix HIGH CVE-2026-4424 (libarchive heap OOB read in RAR processing) - pom.xml: Quarkus 3.34.3 -> 3.34.5, WireMock 3.13.0 -> 3.13.2 - AGENTS.md: add Docker & Container Security section with Trivy CVE remediation procedure, add Dockerfile.jvm to Key Files table - README.md: update test badge to 5,100+
- pom.xml, application.properties, Dockerfile.jvm - README.md, Helm Chart, K8s manifests - Agent Father ZIP renamed to 6.0.2
This pull request introduces cryptographic signing of Docker images using Sigstore cosign with keyless OIDC signing, enhancing the integrity and auditability of EDDI releases. The CI/CD pipeline is updated to sign all Docker images after pushing and to verify signatures as part of the smoke test. Comprehensive documentation is added to guide users on verifying image signatures and understanding the signing process.
CI/CD Pipeline Enhancements:
.github/workflows/ci.ymlto install cosign, sign Docker images after pushing to Docker Hub, and output the image digest for audit purposes. The workflow now grants the necessary OIDC permissions for keyless signing. [1] [2] [3]Documentation Updates:
docs/release-signing.mdfile detailing the release signing process, security properties, and verification instructions for users and auditors.SECURITY.mdwith a new section on Release Integrity, including a verification snippet and reference to the new documentation.docs/SUMMARY.mdand referenced it fromdocs/release-versioning.md. [1] [2]Summary by CodeRabbit
New Features
Documentation