Skip to content

Commit 44ad328

Browse files
committed
Improve provenance signing: add GPG agent setup, smoke test, and docs
- Add gpgconf --launch gpg-agent before GPG key import in CI - Fix provenance separator format to match Helm parser (\n...\n -> ...\n) - Add provenance-smoke-test job that validates signing with disposable key - Add workflow_dispatch trigger for manual testing - Document required GPG secrets and key rotation in workflow header - Update README with public key import guidance for Helm 4 users Signed-off-by: yxxhero <aiopsclub@163.com>
1 parent b7db1ed commit 44ad328

3 files changed

Lines changed: 78 additions & 3 deletions

File tree

.github/workflows/release.yaml

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# Release workflow
2+
#
3+
# Prerequisites (configure in Settings > Secrets and variables > Actions):
4+
# - GPG_PRIVATE_KEY: base64-encoded GPG private key for signing release artifacts
5+
# - GPG_FINGERPRINT: Fingerprint of the GPG key
6+
# - GPG_PASSPHRASE: Passphrase for the GPG private key
7+
#
8+
# Key management notes:
9+
# - Use a key with no expiration or set a calendar reminder before expiry
10+
# - To rotate: generate a new keypair, update all three secrets, and verify
11+
# with a test release (see the test-provenance-sign-dry job)
12+
113
name: Release
214

315
on:
@@ -11,6 +23,7 @@ on:
1123
branches:
1224
- 'main'
1325
- 'master'
26+
workflow_dispatch:
1427

1528
permissions:
1629
contents: write
@@ -35,7 +48,9 @@ jobs:
3548
-
3649
name: Import GPG key
3750
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
38-
run: echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode | gpg --batch --import
51+
run: |
52+
gpgconf --launch gpg-agent
53+
echo "${{ secrets.GPG_PRIVATE_KEY }}" | base64 --decode | gpg --batch --import
3954
-
4055
name: Set GPG environment for signing
4156
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
@@ -51,3 +66,63 @@ jobs:
5166
args: release --clean ${{ env.flags }}
5267
env:
5368
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
69+
70+
provenance-smoke-test:
71+
runs-on: ubuntu-latest
72+
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
73+
steps:
74+
-
75+
name: Checkout
76+
uses: actions/checkout@v6
77+
-
78+
name: Test provenance signing with disposable key
79+
run: |
80+
export GNUPGHOME="$(mktemp -d)"
81+
chmod 700 "$GNUPGHOME"
82+
trap 'rm -rf "$GNUPGHOME"' EXIT
83+
84+
GPG_FINGERPRINT=$(gpg --batch --passphrase '' --quick-generate-key \
85+
"helm-diff-test" ed25519 sign 0 2>&1 \
86+
| grep -o '[A-F0-9]\{40\}' | head -1)
87+
export GPG_FINGERPRINT
88+
export GPG_PASSPHRASE=""
89+
90+
tmpdir="$(mktemp -d)"
91+
echo "dummy binary" > "$tmpdir/bin"
92+
tar czf "$tmpdir/helm-diff-linux-amd64.tgz" -C "$tmpdir" bin
93+
94+
artifact="$tmpdir/helm-diff-linux-amd64.tgz"
95+
signature="${artifact}.prov"
96+
filename="$(basename "$artifact")"
97+
digest="$(sha256sum "$artifact" | cut -d' ' -f1)"
98+
passphrase_file="$(mktemp)"
99+
trap 'rm -f "$passphrase_file"' EXIT
100+
printf '%s' "${GPG_PASSPHRASE:-}" > "$passphrase_file"
101+
chmod 600 "$passphrase_file"
102+
{
103+
cat plugin.yaml
104+
printf '...\n'
105+
printf 'files:\n %s: "sha256:%s"\n' "$filename" "$digest"
106+
} | gpg --batch --yes --armor --pinentry-mode loopback \
107+
--passphrase-file "$passphrase_file" \
108+
--local-user "$GPG_FINGERPRINT" \
109+
--clearsign --output "$signature"
110+
111+
if [ ! -f "$signature" ]; then
112+
echo "ERROR: provenance file was not created"
113+
exit 1
114+
fi
115+
116+
echo "=== gpg --verify ==="
117+
gpg --verify "$signature"
118+
119+
echo ""
120+
echo "=== Signed .prov content ==="
121+
cat "$signature"
122+
123+
echo ""
124+
echo "=== Parsed provenance block ==="
125+
gpg --batch --output - "$signature" 2>/dev/null
126+
127+
echo ""
128+
echo "Provenance signing dry-run test passed"

.goreleaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ signs:
7171
chmod 600 "$passphrase_file"
7272
{
7373
cat plugin.yaml
74-
printf '\n...\n'
74+
printf '...\n'
7575
printf 'files:\n %s: "sha256:%s"\n' "$filename" "$digest"
7676
} | gpg --batch --yes --armor --pinentry-mode loopback --passphrase-file "$passphrase_file" --local-user "$GPG_FINGERPRINT" --clearsign --output "$signature"
7777
- --

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ The install script will skip the GitHub download and instead install from the `.
4343

4444
**For Helm 4 users:**
4545

46-
Helm 4 verifies plugin provenance by default. This project publishes release provenance artifacts (`.prov`) alongside release tarballs to support verification.
46+
Helm 4 verifies plugin provenance by default. This project publishes GPG-signed provenance artifacts (`.prov`) alongside release tarballs. To verify, import the project's public key into your keyring before running `helm plugin install`.
4747
4848
For more information about Helm 4's plugin verification, see:
4949
- [Helm 4 Overview](https://helm.sh/docs/overview)

0 commit comments

Comments
 (0)