-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat(ci): add release artifact signing workflow #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,86 @@ | ||||||||||||||||||||||||||||||||
| name: Sign Release Artifacts | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||
| release: | ||||||||||||||||||||||||||||||||
| types: [published] | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||
| id-token: write | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||
| sign: | ||||||||||||||||||||||||||||||||
| name: Sign release artifacts with cosign | ||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||||||
| id-token: write | ||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||
| - name: Harden runner | ||||||||||||||||||||||||||||||||
| uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 | ||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||
| egress-policy: audit | ||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Upgrade
🔒 Proposed fix - name: Harden runner
uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
with:
- egress-policy: audit
+ egress-policy: block
+ allowed-endpoints: >
+ api.github.com:443
+ fulcio.sigstore.dev:443
+ rekor.sigstore.dev:443
+ tuf-repo-cdn.sigstore.dev:443
+ oauth2.sigstore.dev:443
+ uploads.github.com:443As per coding guidelines: "Security best practices (minimal permissions, pinned actions)" — restricting egress is a key hardening control for sensitive workflows. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - name: Checkout | ||||||||||||||||||||||||||||||||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||||||||||||||||||||||||||||||||
|
Comment on lines
+24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win The This workflow only downloads release assets from the GitHub API, signs them with cosign, and uploads the resulting signature files back. No repository source files are referenced at any point. Removing checkout eliminates one more action execution path from the signing environment. ♻️ Proposed fix- - name: Checkout
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - name: Install cosign | ||||||||||||||||||||||||||||||||
| uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0 | ||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Confirm the SHA pinned in the workflow matches the v3.7.0 tag on cosign-installer
git ls-remote https://github.com/sigstore/cosign-installer.git refs/tags/v3.7.0Repository: ByronWilliamsCPA/python-libs Length of output: 130 🌐 Web query:
💡 Result: cosign-installer v3.x is incompatible with cosign binary v3.x and later; it cannot install cosign v3.x and defaults to cosign v2.x versions (e.g., v2.6.1 in v3.10.1).[1][2][3] cosign-installer v4.x (starting v4.0.0) adds support for installing cosign v3.x and later, with defaults like v3.0.2 in v4.0.0 progressing to v3.0.5 in v4.1.1.[4][5][3][6] v4.x can still install cosign v2.x via the cosign-release input.[1][3] To use cosign v3+, upgrade to cosign-installer v4+; v3.x is limited to cosign v2.x.[1][2] Citations:
Fix SHA pinning mismatch for cosign-installer v3.7.0 The pinned SHA Additionally, cosign-installer v3.x installs cosign v2.x (not v3.x). If cosign v3+ is required for this workflow, upgrade to cosign-installer v4+, which supports cosign v3.x. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - name: Download release assets | ||||||||||||||||||||||||||||||||
| id: download | ||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||||
| RELEASE_TAG: ${{ github.event.release.tag_name }} | ||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||
| mkdir -p release-assets | ||||||||||||||||||||||||||||||||
| if ! gh release download "$RELEASE_TAG" --dir release-assets/; then | ||||||||||||||||||||||||||||||||
| asset_count=$(gh release view "$RELEASE_TAG" --json assets --jq '.assets | length' 2>/dev/null || echo "unknown") | ||||||||||||||||||||||||||||||||
| if [ "$asset_count" = "0" ]; then | ||||||||||||||||||||||||||||||||
| echo "No assets attached to release $RELEASE_TAG; skipping signing" >&2 | ||||||||||||||||||||||||||||||||
| echo "skip=true" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
| echo "Failed to download assets for release $RELEASE_TAG (asset count: $asset_count)" >&2 | ||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - name: Sign release artifacts | ||||||||||||||||||||||||||||||||
| if: steps.download.outputs.skip != 'true' | ||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||||
| RELEASE_TAG: ${{ github.event.release.tag_name }} | ||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||
| cd release-assets | ||||||||||||||||||||||||||||||||
| signed_count=0 | ||||||||||||||||||||||||||||||||
| for artifact in *.whl *.tar.gz; do | ||||||||||||||||||||||||||||||||
| [ -f "$artifact" ] || continue | ||||||||||||||||||||||||||||||||
| cosign sign-blob \ | ||||||||||||||||||||||||||||||||
| --yes \ | ||||||||||||||||||||||||||||||||
| --output-signature "${artifact}.sig" \ | ||||||||||||||||||||||||||||||||
| --output-certificate "${artifact}.pem" \ | ||||||||||||||||||||||||||||||||
| "$artifact" | ||||||||||||||||||||||||||||||||
|
Comment on lines
+58
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win 🧩 Analysis chain🌐 Web query:
💡 Result: Yes. Cosign v2’s Citations:
Switch from The ♻️ Proposed fix cosign sign-blob \
--yes \
- --output-signature "${artifact}.sig" \
- --output-certificate "${artifact}.pem" \
+ --bundle "${artifact}.sigstore.json" \
"$artifact"The upload step filter would also need updating: - for f in *.sig *.pem; do
+ for f in *.sigstore.json; do🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| signed_count=$((signed_count + 1)) | ||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||
| if [ "$signed_count" -eq 0 ]; then | ||||||||||||||||||||||||||||||||
| echo "No .whl or .tar.gz artifacts found in release-assets; expected at least one" >&2 | ||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| - name: Upload signatures | ||||||||||||||||||||||||||||||||
| if: steps.download.outputs.skip != 'true' | ||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||||||||||
| RELEASE_TAG: ${{ github.event.release.tag_name }} | ||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||
| cd release-assets | ||||||||||||||||||||||||||||||||
| sig_files=() | ||||||||||||||||||||||||||||||||
| for f in *.sig *.pem; do | ||||||||||||||||||||||||||||||||
| [ -f "$f" ] && sig_files+=("$f") | ||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||
| if [ "${#sig_files[@]}" -gt 0 ]; then | ||||||||||||||||||||||||||||||||
| gh release upload "$RELEASE_TAG" "${sig_files[@]}" --clobber | ||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||
| echo "No signature files found to upload; expected .sig and .pem from cosign" >&2 | ||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
id-token: writefrom the workflow-levelpermissionsblockThe job already declares its own
permissionsblock (lines 15–17), which completely replaces the workflow-level permissions for that job. The top-levelid-token: writehere has no effect on thesignjob but does become the default permission for any future job that is added without its ownpermissionsblock, silently granting OIDC token write access to unanticipated steps.🔒 Proposed fix
permissions: contents: read - id-token: write🤖 Prompt for AI Agents