chore(release): signed releases for binaries and docker (#35)

* chore(release): signed releases for binaries and docker

* undo unneeded changes
This commit is contained in:
Cal Bera 2025-07-25 13:58:49 -07:00 committed by GitHub
parent 6a308e75b8
commit 688d070666
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 204 additions and 9 deletions

140
.github/workflows/RELEASE_SIGNING.md vendored Normal file
View file

@ -0,0 +1,140 @@
# Release Signing Setup
This document explains how release signing is implemented for bera-geth, including PGP signing for binaries and Cosign signing for Docker images.
## Overview
The bera-geth release process includes cryptographic signing for all release artifacts:
- **Binary releases**: Signed with PGP/GPG
- **Docker images**: Signed with Cosign (keyless signing via OIDC)
## Configuration
### Prerequisites for Release Managers
#### PGP Signing Setup
1. **Create the `LINUX_SIGNING_KEY` secret in GitHub**:
```bash
# Export your PGP private key
gpg --export-secret-keys --armor YOUR_KEY_ID > private.key
# Base64 encode it
cat private.key | base64 -w 0
# Copy the output and add it as the LINUX_SIGNING_KEY secret in GitHub repository settings
```
2. **Ensure the public key matches**: The public key at `.github/workflows/release.asc` should correspond to the private key used for signing.
#### Cosign Setup
Cosign uses keyless signing (no secret required). The workflow uses GitHub's OIDC provider to sign images, which means:
- No private keys to manage
- Signatures are tied to the GitHub Actions workflow identity
- Full transparency via Rekor transparency log
## Release Process
### Triggering a Release
Releases are triggered by:
- Pushing a tag matching `v1.*` (e.g., `v1.0.0`, `v1.0.0-rc1`)
- The workflow will automatically create a draft release with all signed artifacts
### What Gets Signed
1. **Binary Archives**:
- `bera-geth-linux-amd64-*.tar.gz``bera-geth-linux-amd64-*.tar.gz.asc`
- `bera-geth-linux-arm64-*.tar.gz``bera-geth-linux-arm64-*.tar.gz.asc`
- `bera-geth-alltools-linux-amd64-*.tar.gz``bera-geth-alltools-linux-amd64-*.tar.gz.asc`
- `bera-geth-alltools-linux-arm64-*.tar.gz``bera-geth-alltools-linux-arm64-*.tar.gz.asc`
2. **Docker Images**:
- Multi-arch images at `ghcr.io/berachain/bera-geth:VERSION`
- Signed with Cosign using keyless signing
## Verification Instructions
### Verifying Binary Signatures
Users can verify the PGP signatures of release binaries:
```bash
# Download and import the public key
curl -sSL https://raw.githubusercontent.com/berachain/bera-geth/main/.github/workflows/release.asc | gpg --import
# Download a release archive and its signature
wget https://github.com/berachain/bera-geth/releases/download/v1.0.0/bera-geth-linux-amd64-v1.0.0.tar.gz
wget https://github.com/berachain/bera-geth/releases/download/v1.0.0/bera-geth-linux-amd64-v1.0.0.tar.gz.asc
# Verify the signature
gpg --verify bera-geth-linux-amd64-v1.0.0.tar.gz.asc bera-geth-linux-amd64-v1.0.0.tar.gz
```
Expected output:
```
gpg: Signature made [date] using RSA key ID [key-id]
gpg: Good signature from "bera-geth-linux-signing-key"
```
### Verifying Docker Images
Docker images are signed with Cosign and can be verified:
```bash
# Install cosign if not already installed
brew install cosign # macOS
# or see https://docs.sigstore.dev/cosign/installation/
# Verify a specific version
cosign verify ghcr.io/berachain/bera-geth:v1.0.0
# Verify the latest image
cosign verify ghcr.io/berachain/bera-geth:latest
```
The verification will show:
- The GitHub Actions workflow that created the image
- The commit SHA
- The OIDC issuer (GitHub)
## Security Considerations
1. **PGP Key Security**:
- The PGP private key should be kept secure and only accessible to authorized release managers
- Regularly rotate keys and update the public key in the repository
- Use a strong passphrase for the private key
2. **Cosign Keyless Signing**:
- Signatures are tied to the GitHub Actions workflow identity
- Verification includes checking the workflow that signed the image
- All signatures are recorded in the Rekor transparency log
3. **Best Practices**:
- Always verify signatures before using release artifacts in production
- Check that the signing workflow matches the official repository
- Monitor the repository for any changes to signing keys or workflows
## Troubleshooting
### PGP Signing Issues
If PGP signing fails:
1. Check that the `LINUX_SIGNING_KEY` secret is properly set
2. Verify the key hasn't expired: `gpg --list-secret-keys`
3. Ensure the base64 encoding was done correctly
### Cosign Signing Issues
If Cosign signing fails:
1. Ensure the workflow has `id-token: write` permission
2. Check that the Docker image was successfully pushed before signing
3. Verify the image tag/digest is correct
### Release Draft Issues
If the release draft fails:
1. Ensure all artifacts were successfully uploaded
2. Check that the tag follows the correct format (`v1.*`)
3. Verify the workflow has `contents: write` permission

View file

@ -38,6 +38,36 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Build and push multi-arch images to GHCR
run: |
go run build/ci.go dockerx -platform linux/amd64,linux/arm64 -hub ghcr.io/berachain/bera-geth -upload
- name: Get image digest and version
id: image_info
run: |
# Extract version information
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION="${{ github.ref_name }}"
elif [[ "${{ github.ref }}" == refs/heads/main ]]; then
VERSION="latest"
else
VERSION="branch-${GITHUB_REF##*/}"
fi
# Get the digest of the pushed image
DIGEST=$(docker buildx imagetools inspect ghcr.io/berachain/bera-geth:${VERSION} --format "{{.Manifest.Digest}}")
echo "digest=${DIGEST}" >> $GITHUB_OUTPUT
echo "version=${VERSION}" >> $GITHUB_OUTPUT
- name: Sign Docker images with Cosign
env:
COSIGN_EXPERIMENTAL: true
run: |
# Sign the multi-arch manifest by digest
cosign sign --yes ghcr.io/berachain/bera-geth@${{ steps.image_info.outputs.digest }}
# Also sign the tagged version
cosign sign --yes ghcr.io/berachain/bera-geth:${{ steps.image_info.outputs.version }}

View file

@ -39,14 +39,18 @@ jobs:
- name: Create archive (amd64)
run: |
go run build/ci.go archive -arch amd64 -type tar
go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
- name: Upload artifacts (amd64)
uses: actions/upload-artifact@v4
with:
name: bera-geth-linux-amd64-archives
path: |
bera-geth-linux-amd64-*.tar.gz
bera-geth-linux-amd64-*.tar.gz.asc
bera-geth-alltools-linux-amd64-*.tar.gz
bera-geth-alltools-linux-amd64-*.tar.gz.asc
- name: Cleanup bin
run: rm -f build/bin/*
@ -74,14 +78,18 @@ jobs:
- name: Create archive (arm64)
run: |
go run build/ci.go archive -arch arm64 -type tar
go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY
env:
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
- name: Upload artifacts (arm64)
uses: actions/upload-artifact@v4
with:
name: bera-geth-linux-arm64-archives
path: |
bera-geth-linux-arm64-*.tar.gz
bera-geth-linux-arm64-*.tar.gz.asc
bera-geth-alltools-linux-arm64-*.tar.gz
bera-geth-alltools-linux-arm64-*.tar.gz.asc
- name: Cleanup bin
run: rm -fr build/bin/*
@ -176,15 +184,32 @@ jobs:
## Binaries
| System | Architecture | Binary | Notes |
|:---:|:---:|:---:|:---|
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | amd64 | [GETH_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER) | Most Linux systems |
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | arm64 | [GETH_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER) | 64-bit ARM systems |
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | amd64 | [GETH_ALLTOOLS_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER) | All tools bundle (amd64) |
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | arm64 | [GETH_ALLTOOLS_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER) | All tools bundle (arm64) |
| System | Architecture | Binary | PGP Signature | Notes |
|:---:|:---:|:---:|:---:|:---|
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | amd64 | [GETH_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER.asc) | Most Linux systems |
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | arm64 | [GETH_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER.asc) | 64-bit ARM systems |
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | amd64 | [GETH_ALLTOOLS_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER.asc) | All tools bundle (amd64) |
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | arm64 | [GETH_ALLTOOLS_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER.asc) | All tools bundle (arm64) |
| **System** | **Option** | - | **Resource** |
| <img src="https://simpleicons.org/icons/docker.svg" style="width: 32px;"/> | Docker | | [ghcr.io/berachain/bera-geth](https://ghcr.io/berachain/bera-geth) |
### Verifying Binary Signatures
All release binaries are signed with PGP. To verify:
1. Download the [public key](https://raw.githubusercontent.com/${{ github.repository }}/master/.github/workflows/release.asc)
2. Import the key: `gpg --import release.asc`
3. Verify the signature: `gpg --verify <filename>.asc <filename>`
### Docker Images
Docker images are available at `ghcr.io/berachain/bera-geth` and are signed with [Cosign](https://github.com/sigstore/cosign).
To verify Docker images:
```bash
cosign verify ghcr.io/berachain/bera-geth:RELEASE_TAG_PLACEHOLDER
```
### Installation
The archives contain the geth binary and license file. Extract and run: