mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-13 00:48:55 +00:00
ci(release): add CLI/MCP binaries, checksums, SBOM, Cosign, SLSA provenance (M-3)
This commit is contained in:
+272
-43
@@ -7,40 +7,30 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: ghcr.io
|
REGISTRY: ghcr.io
|
||||||
GO_VERSION: '1.22'
|
# Keep in lock-step with .github/workflows/ci.yml (M-3).
|
||||||
|
GO_VERSION: '1.25.9'
|
||||||
|
IMAGE_NAMESPACE: shankar0123
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Cross-compile agent and server binaries for multiple platforms
|
# ----------------------------------------------------------------------
|
||||||
|
# build-binaries (M-3): matrix build every (binary × OS × arch) tuple.
|
||||||
|
# For each tuple we produce: the binary, a SPDX-JSON SBOM, a keyless
|
||||||
|
# Cosign signature + certificate bundle, and a single-line sha256sum
|
||||||
|
# file. All artefacts are uploaded to a workflow-scoped artifact; the
|
||||||
|
# aggregate-checksums job fans them back in for release upload.
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
build-binaries:
|
build-binaries:
|
||||||
name: Build Cross-Platform Binaries
|
name: Build ${{ matrix.binary }} (${{ matrix.os }}/${{ matrix.arch }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: read
|
||||||
|
id-token: write # Cosign keyless OIDC identity token
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
binary: [agent, server, cli, mcp-server]
|
||||||
# Agent binaries (4 platforms)
|
os: [linux, darwin]
|
||||||
- os: linux
|
arch: [amd64, arm64]
|
||||||
arch: amd64
|
|
||||||
binary: agent
|
|
||||||
- os: linux
|
|
||||||
arch: arm64
|
|
||||||
binary: agent
|
|
||||||
- os: darwin
|
|
||||||
arch: amd64
|
|
||||||
binary: agent
|
|
||||||
- os: darwin
|
|
||||||
arch: arm64
|
|
||||||
binary: agent
|
|
||||||
# Server binaries (2 platforms)
|
|
||||||
- os: linux
|
|
||||||
arch: amd64
|
|
||||||
binary: server
|
|
||||||
- os: linux
|
|
||||||
arch: arm64
|
|
||||||
binary: server
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -51,35 +41,171 @@ jobs:
|
|||||||
|
|
||||||
- name: Extract version from tag
|
- name: Extract version from tag
|
||||||
id: version
|
id: version
|
||||||
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Build ${{ matrix.binary }} binary (${{ matrix.os }}-${{ matrix.arch }})
|
- name: Build binary
|
||||||
|
id: build
|
||||||
env:
|
env:
|
||||||
GOOS: ${{ matrix.os }}
|
GOOS: ${{ matrix.os }}
|
||||||
GOARCH: ${{ matrix.arch }}
|
GOARCH: ${{ matrix.arch }}
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: '0'
|
||||||
|
VERSION: ${{ steps.version.outputs.VERSION }}
|
||||||
run: |
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
OUTPUT_NAME="certctl-${{ matrix.binary }}-${{ matrix.os }}-${{ matrix.arch }}"
|
OUTPUT_NAME="certctl-${{ matrix.binary }}-${{ matrix.os }}-${{ matrix.arch }}"
|
||||||
go build -ldflags="-w -s -X main.Version=${{ steps.version.outputs.VERSION }}" \
|
mkdir -p dist
|
||||||
|
go build \
|
||||||
|
-trimpath \
|
||||||
|
-ldflags="-w -s -X main.Version=${VERSION}" \
|
||||||
-o "dist/${OUTPUT_NAME}" \
|
-o "dist/${OUTPUT_NAME}" \
|
||||||
"./cmd/${{ matrix.binary }}"
|
"./cmd/${{ matrix.binary }}"
|
||||||
ls -lh "dist/${OUTPUT_NAME}"
|
ls -lh "dist/${OUTPUT_NAME}"
|
||||||
|
echo "output_name=${OUTPUT_NAME}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Upload binaries to release
|
- name: Generate SBOM (SPDX-JSON)
|
||||||
|
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
|
||||||
|
with:
|
||||||
|
file: dist/${{ steps.build.outputs.output_name }}
|
||||||
|
format: spdx-json
|
||||||
|
output-file: dist/${{ steps.build.outputs.output_name }}.sbom.spdx.json
|
||||||
|
upload-artifact: false
|
||||||
|
upload-release-assets: false
|
||||||
|
|
||||||
|
- name: Install Cosign
|
||||||
|
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||||
|
|
||||||
|
- name: Keyless-sign binary with Cosign
|
||||||
|
env:
|
||||||
|
OUTPUT_NAME: ${{ steps.build.outputs.output_name }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cosign sign-blob \
|
||||||
|
--yes \
|
||||||
|
--output-signature "dist/${OUTPUT_NAME}.sig" \
|
||||||
|
--output-certificate "dist/${OUTPUT_NAME}.pem" \
|
||||||
|
"dist/${OUTPUT_NAME}"
|
||||||
|
|
||||||
|
- name: Compute SHA-256 sidecar
|
||||||
|
env:
|
||||||
|
OUTPUT_NAME: ${{ steps.build.outputs.output_name }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd dist
|
||||||
|
sha256sum "${OUTPUT_NAME}" > "${OUTPUT_NAME}.sha256"
|
||||||
|
cat "${OUTPUT_NAME}.sha256"
|
||||||
|
|
||||||
|
- name: Upload build artefacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: binary-${{ steps.build.outputs.output_name }}
|
||||||
|
path: |
|
||||||
|
dist/${{ steps.build.outputs.output_name }}
|
||||||
|
dist/${{ steps.build.outputs.output_name }}.sig
|
||||||
|
dist/${{ steps.build.outputs.output_name }}.pem
|
||||||
|
dist/${{ steps.build.outputs.output_name }}.sbom.spdx.json
|
||||||
|
dist/${{ steps.build.outputs.output_name }}.sha256
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# aggregate-checksums (M-3): fan in every matrix artefact, produce a
|
||||||
|
# single checksums.txt (sha256sum format, compatible with `sha256sum
|
||||||
|
# -c`), sign it with Cosign, upload everything to the GitHub Release,
|
||||||
|
# and emit a base64-encoded hash manifest for the SLSA generator.
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
aggregate-checksums:
|
||||||
|
name: Aggregate checksums & sign
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build-binaries]
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write # Cosign keyless OIDC identity token
|
||||||
|
outputs:
|
||||||
|
hashes: ${{ steps.hashes.outputs.hashes }}
|
||||||
|
steps:
|
||||||
|
- name: Download binary artefacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
pattern: binary-*
|
||||||
|
path: artifacts
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Aggregate SHA-256 sums
|
||||||
|
id: hashes
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd artifacts
|
||||||
|
: > checksums.txt
|
||||||
|
for f in certctl-*; do
|
||||||
|
case "$f" in
|
||||||
|
*.sig|*.pem|*.sbom.spdx.json|*.sha256|checksums.txt)
|
||||||
|
continue ;;
|
||||||
|
esac
|
||||||
|
sha256sum "$f" >> checksums.txt
|
||||||
|
done
|
||||||
|
echo "=== checksums.txt ==="
|
||||||
|
cat checksums.txt
|
||||||
|
# base64 hashes (single line, no wrapping) for SLSA generator.
|
||||||
|
HASHES=$(base64 -w0 < checksums.txt)
|
||||||
|
echo "hashes=${HASHES}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Install Cosign
|
||||||
|
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||||
|
|
||||||
|
- name: Keyless-sign checksums.txt
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd artifacts
|
||||||
|
cosign sign-blob \
|
||||||
|
--yes \
|
||||||
|
--output-signature checksums.txt.sig \
|
||||||
|
--output-certificate checksums.txt.pem \
|
||||||
|
checksums.txt
|
||||||
|
|
||||||
|
- name: Upload artefacts to GitHub Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
dist/certctl-agent-*
|
artifacts/certctl-*
|
||||||
dist/certctl-server-*
|
artifacts/checksums.txt
|
||||||
|
artifacts/checksums.txt.sig
|
||||||
|
artifacts/checksums.txt.pem
|
||||||
|
|
||||||
# Build and push Docker images
|
# ----------------------------------------------------------------------
|
||||||
|
# provenance-binaries (M-3): SLSA Level 3 provenance for every binary.
|
||||||
|
# The SLSA generic generator reusable workflow runs in a hermetic
|
||||||
|
# workflow run, producing multiple.intoto.jsonl from the base64 hash
|
||||||
|
# manifest and uploading it as a release asset.
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
provenance-binaries:
|
||||||
|
name: SLSA provenance (binaries)
|
||||||
|
needs: [aggregate-checksums]
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
|
||||||
|
with:
|
||||||
|
base64-subjects: "${{ needs.aggregate-checksums.outputs.hashes }}"
|
||||||
|
upload-assets: true
|
||||||
|
provenance-name: multiple.intoto.jsonl
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# build-and-push-docker: push container images to GHCR with native
|
||||||
|
# SLSA L3 provenance (mode=max) and SBOM attestations emitted by
|
||||||
|
# docker/build-push-action@v6, plus a keyless Cosign signature on the
|
||||||
|
# image digest for identity-bound verification. The M-4 proxy-propagation
|
||||||
|
# build-args block is retained verbatim — M-3 only adds supply-chain
|
||||||
|
# steps; it never touches M-4 wiring.
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
build-and-push-docker:
|
build-and-push-docker:
|
||||||
name: Build & Push Docker Images
|
name: Build & Push Docker Images
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
packages: write
|
packages: write
|
||||||
|
id-token: write # Cosign keyless OIDC identity token
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -93,20 +219,24 @@ jobs:
|
|||||||
|
|
||||||
- name: Extract version from tag
|
- name: Extract version from tag
|
||||||
id: version
|
id: version
|
||||||
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Install Cosign
|
||||||
|
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||||
|
|
||||||
- name: Build and push server image
|
- name: Build and push server image
|
||||||
|
id: server-push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-server:${{ steps.version.outputs.VERSION }}
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-server:${{ steps.version.outputs.VERSION }}
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-server:latest
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-server:latest
|
||||||
# Proxy propagation (M-4, Issue #9) — forwards runner-level proxy
|
# Proxy propagation (M-4, Issue #9) — forwards runner-level proxy
|
||||||
# secrets into the Docker build so self-hosted runners behind
|
# secrets into the Docker build so self-hosted runners behind
|
||||||
# corporate proxies can reach public registries. GitHub-hosted
|
# corporate proxies can reach public registries. GitHub-hosted
|
||||||
@@ -117,18 +247,31 @@ jobs:
|
|||||||
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
||||||
HTTPS_PROXY=${{ secrets.HTTPS_PROXY }}
|
HTTPS_PROXY=${{ secrets.HTTPS_PROXY }}
|
||||||
NO_PROXY=${{ secrets.NO_PROXY }}
|
NO_PROXY=${{ secrets.NO_PROXY }}
|
||||||
|
# Supply-chain hardening (M-3): emit native SLSA L3 provenance
|
||||||
|
# and SBOM attestations bound to the image manifest.
|
||||||
|
provenance: mode=max
|
||||||
|
sbom: true
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Keyless-sign server image with Cosign
|
||||||
|
env:
|
||||||
|
DIGEST: ${{ steps.server-push.outputs.digest }}
|
||||||
|
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-server
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cosign sign --yes "${IMAGE}@${DIGEST}"
|
||||||
|
|
||||||
- name: Build and push agent image
|
- name: Build and push agent image
|
||||||
|
id: agent-push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./Dockerfile.agent
|
file: ./Dockerfile.agent
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-agent:${{ steps.version.outputs.VERSION }}
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-agent:${{ steps.version.outputs.VERSION }}
|
||||||
${{ env.REGISTRY }}/shankar0123/certctl-agent:latest
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-agent:latest
|
||||||
# Proxy propagation (M-4, Issue #9) — see server-image step for
|
# Proxy propagation (M-4, Issue #9) — see server-image step for
|
||||||
# rationale. Empty secrets resolve to empty build args, leaving
|
# rationale. Empty secrets resolve to empty build args, leaving
|
||||||
# the un-proxied code path byte-identical to the pre-fix tree.
|
# the un-proxied code path byte-identical to the pre-fix tree.
|
||||||
@@ -136,14 +279,30 @@ jobs:
|
|||||||
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
||||||
HTTPS_PROXY=${{ secrets.HTTPS_PROXY }}
|
HTTPS_PROXY=${{ secrets.HTTPS_PROXY }}
|
||||||
NO_PROXY=${{ secrets.NO_PROXY }}
|
NO_PROXY=${{ secrets.NO_PROXY }}
|
||||||
|
# Supply-chain hardening (M-3): emit native SLSA L3 provenance
|
||||||
|
# and SBOM attestations bound to the image manifest.
|
||||||
|
provenance: mode=max
|
||||||
|
sbom: true
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
# Create release notes with all artifacts
|
- name: Keyless-sign agent image with Cosign
|
||||||
|
env:
|
||||||
|
DIGEST: ${{ steps.agent-push.outputs.digest }}
|
||||||
|
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-agent
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cosign sign --yes "${IMAGE}@${DIGEST}"
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# create-release: stamp the release body. The actual asset uploads are
|
||||||
|
# handled by aggregate-checksums (binaries, SBOMs, sigs, certs,
|
||||||
|
# checksums.txt + signature) and the SLSA generator (multiple.intoto.jsonl).
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
create-release:
|
create-release:
|
||||||
name: Create Release Notes
|
name: Create Release Notes
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [build-binaries, build-and-push-docker]
|
needs: [build-binaries, aggregate-checksums, provenance-binaries, build-and-push-docker]
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
@@ -152,7 +311,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Extract version from tag
|
- name: Extract version from tag
|
||||||
id: version
|
id: version
|
||||||
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Create release with notes
|
- name: Create release with notes
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
@@ -214,6 +373,76 @@ jobs:
|
|||||||
|
|
||||||
- **Linux x86_64**: `certctl-server-linux-amd64`
|
- **Linux x86_64**: `certctl-server-linux-amd64`
|
||||||
- **Linux ARM64**: `certctl-server-linux-arm64`
|
- **Linux ARM64**: `certctl-server-linux-arm64`
|
||||||
|
- **macOS x86_64**: `certctl-server-darwin-amd64`
|
||||||
|
- **macOS ARM64 (Apple Silicon)**: `certctl-server-darwin-arm64`
|
||||||
|
|
||||||
|
## CLI & MCP Server Binaries
|
||||||
|
|
||||||
|
The `certctl-cli` (REST API wrapper) and `certctl-mcp-server` (Model Context
|
||||||
|
Protocol bridge) binaries ship for all four platforms as well:
|
||||||
|
|
||||||
|
- `certctl-cli-{linux,darwin}-{amd64,arm64}`
|
||||||
|
- `certctl-mcp-server-{linux,darwin}-{amd64,arm64}`
|
||||||
|
|
||||||
|
## Verifying this release
|
||||||
|
|
||||||
|
Every binary, `checksums.txt`, and container image is signed with Cosign
|
||||||
|
keyless OIDC. Each binary ships with a SPDX-JSON SBOM. Binaries are covered
|
||||||
|
by SLSA Level 3 provenance; container images carry native SLSA L3 provenance
|
||||||
|
and SBOM attestations (docker/build-push-action `provenance: mode=max`,
|
||||||
|
`sbom: true`) in addition to a Cosign signature on the digest.
|
||||||
|
|
||||||
|
**1. Verify SHA-256 checksums:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sha256sum -c checksums.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Verify the Cosign signature on checksums.txt (keyless OIDC):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cosign verify-blob \
|
||||||
|
--certificate checksums.txt.pem \
|
||||||
|
--signature checksums.txt.sig \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/\.github/workflows/release\.yml@refs/tags/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
checksums.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `checksums.txt` with any individual binary name to verify that
|
||||||
|
artefact directly (each binary ships with its own `.sig` + `.pem` sidecar).
|
||||||
|
|
||||||
|
**3. Verify SLSA Level 3 provenance (binaries):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
slsa-verifier verify-artifact \
|
||||||
|
--provenance-path multiple.intoto.jsonl \
|
||||||
|
--source-uri github.com/shankar0123/certctl \
|
||||||
|
--source-tag ${{ steps.version.outputs.VERSION }} \
|
||||||
|
certctl-agent-linux-amd64
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Verify container image signature and attestations:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
IMAGE=ghcr.io/shankar0123/certctl-server:${{ steps.version.outputs.VERSION }}
|
||||||
|
cosign verify \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/\.github/workflows/release\.yml@refs/tags/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
"$IMAGE"
|
||||||
|
|
||||||
|
# SBOM attestation (SPDX-JSON) emitted by docker/build-push-action
|
||||||
|
cosign verify-attestation --type spdxjson \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
"$IMAGE"
|
||||||
|
|
||||||
|
# SLSA provenance attestation (mode=max)
|
||||||
|
cosign verify-attestation --type slsaprovenance \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
"$IMAGE"
|
||||||
|
```
|
||||||
|
|
||||||
## Helm Chart
|
## Helm Chart
|
||||||
|
|
||||||
|
|||||||
@@ -237,6 +237,72 @@ docker pull shankar0123.docker.scarf.sh/certctl-server
|
|||||||
docker pull shankar0123.docker.scarf.sh/certctl-agent
|
docker pull shankar0123.docker.scarf.sh/certctl-agent
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Verifying this release
|
||||||
|
|
||||||
|
Every `v*` tag publishes signed, attested release artefacts. Binaries
|
||||||
|
(`certctl-agent`, `certctl-server`, `certctl-cli`, `certctl-mcp-server` for
|
||||||
|
`linux|darwin × amd64|arm64`) ship alongside a `checksums.txt`, per-binary
|
||||||
|
SPDX-JSON SBOMs, Cosign signatures, and SLSA Level 3 provenance. Container
|
||||||
|
images on `ghcr.io/shankar0123/certctl-{server,agent}` are built with
|
||||||
|
`docker/build-push-action` `provenance: mode=max` + `sbom: true` and are
|
||||||
|
additionally signed with Cosign at the image digest.
|
||||||
|
|
||||||
|
All signatures use Cosign keyless OIDC; the signing identity is the
|
||||||
|
release workflow running on a signed tag.
|
||||||
|
|
||||||
|
**1. Verify SHA-256 checksums:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sha256sum -c checksums.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Verify the Cosign signature on `checksums.txt`:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cosign verify-blob \
|
||||||
|
--certificate checksums.txt.pem \
|
||||||
|
--signature checksums.txt.sig \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/\.github/workflows/release\.yml@refs/tags/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
checksums.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Every individual binary has its own `.sig` + `.pem` sidecar; swap
|
||||||
|
`checksums.txt` for any binary name to verify it directly.
|
||||||
|
|
||||||
|
**3. Verify SLSA Level 3 provenance on a binary:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
slsa-verifier verify-artifact \
|
||||||
|
--provenance-path multiple.intoto.jsonl \
|
||||||
|
--source-uri github.com/shankar0123/certctl \
|
||||||
|
--source-tag v2.1.0 \
|
||||||
|
certctl-agent-linux-amd64
|
||||||
|
```
|
||||||
|
|
||||||
|
**4. Verify a container image signature and its SBOM / provenance attestations:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
IMAGE=ghcr.io/shankar0123/certctl-server:v2.1.0
|
||||||
|
|
||||||
|
cosign verify \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/\.github/workflows/release\.yml@refs/tags/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
"$IMAGE"
|
||||||
|
|
||||||
|
# SBOM attestation (SPDX-JSON, emitted by docker/build-push-action)
|
||||||
|
cosign verify-attestation --type spdxjson \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
"$IMAGE"
|
||||||
|
|
||||||
|
# SLSA provenance attestation (docker/build-push-action `provenance: mode=max`)
|
||||||
|
cosign verify-attestation --type slsaprovenance \
|
||||||
|
--certificate-identity-regexp '^https://github\.com/shankar0123/certctl/' \
|
||||||
|
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||||
|
"$IMAGE"
|
||||||
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
Pick the scenario closest to your setup and have it running in 2 minutes.
|
Pick the scenario closest to your setup and have it running in 2 minutes.
|
||||||
|
|||||||
Reference in New Issue
Block a user