mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 22:41:31 +00:00
7990b6fab7
Closes H-009 + L-001 + L-007 + L-008 + L-016 + L-017 + L-018 + M-027
from comprehensive-audit-2026-04-25.
H-009 — README JWT verified-already-clean
README has zero JWT mentions at audit time. docs/architecture.md
correctly documents JWT/OIDC integration via authenticating-gateway
pattern (line 905-912).
.github/workflows/ci.yml: new step
'Forbidden README JWT advertising regression guard (H-009)'
greps README for JWT-as-supported phrasing; passes verbatim
(gateway / pre-G-1) but fails build on net-new advertising.
L-001 (CWE-295) — InsecureSkipVerify per-site justification
Audit count was 8; recon found 13 production sites.
docs/tls.md: new 'InsecureSkipVerify justifications' table
enumerates each site by file:line with per-site rationale.
cmd/agent/verify.go:78, internal/tlsprobe/probe.go:54,
internal/service/network_scan.go:460: each previously-bare
InsecureSkipVerify: true now carries //nolint:gosec.
.github/workflows/ci.yml: new step
'Forbidden bare InsecureSkipVerify regression guard (L-001)'
fails build if any net-new ISV lands in non-test .go without
nolint:gosec on the same or preceding line.
L-007 — README dependency-audit commands
README.md: new Dependencies section with go list -m all | wc -l,
go mod why, govulncheck ./.... Honors operating-rules invariant.
L-008 — Release-time govulncheck gate
.github/workflows/release.yml: new 'Install govulncheck' +
'Run govulncheck (release gate)' steps in the matrix job.
Pinned to same install path as ci.yml. Default exit code
semantics (fail on called-vuln only, deferred-call advisories
tracked on master via L-021) keeps the gate appropriate.
L-016 — architecture.md drift fixes
docs/architecture.md: system-components diagram's '21 tables'
annotation removed (current 23; replaced with TEXT-keys
descriptor); connector-architecture '9 connectors' prose
replaced with grep ref + current 12-issuer list (added
Entrust/GlobalSign/EJBCA which were missing); API-design
'97 operations / 107 total' replaced with grep commands.
Connector subgraphs verified-current at 12/13/6.
L-017 — workspace CLAUDE.md verified-already-clean
Bundle B's pre-commit-gate refactor already converted current-
state numeric claims to grep commands. Phase 0 recon confirmed
zero remaining hardcoded counts.
L-018 — Defect age table
cowork/comprehensive-audit-2026-04-25/defect-age.md (NEW):
Tabulates all 9 High findings with first-mentioned commit,
closing bundle, days-open. Methodology snippet for re-running.
Key finding: 8 of 9 closed within 24h of audit publication.
M-027 — OpenAPI parity verified-already-clean
Audit's 'router 121 vs OpenAPI 125 — 4-op gap' was wrong
methodology. The 4-op 'gap' was exactly the 4 routes registered
via r.mux.Handle (auth-exempt allowlist) instead of r.Register.
When you count both dispatch shapes the totals match exactly.
internal/api/router/openapi_parity_test.go (NEW):
TestRouter_OpenAPIParity AST-walks router.go for both
Register and mux.Handle calls + walks api/openapi.yaml's
path/method nesting + asserts the sets match. Adding a route
without updating the spec fails CI permanently.
Audit deliverables:
audit-report.md: score 38/55 -> 46/55 closed
(High 7/9 -> 8/9; Medium 20/27 -> 21/27; Low 8/19 -> 14/19)
findings.yaml: 8 status flips open -> closed
defect-age.md: new file
certctl/CHANGELOG.md: Bundle D section
Verification:
TestRouter_OpenAPIParity PASS
L-001 grep guard self-test (after //nolint:gosec adds) PASS
H-009 grep guard self-test PASS
go test -count=1 -short on changed packages green
478 lines
18 KiB
YAML
478 lines
18 KiB
YAML
name: Release
|
||
|
||
on:
|
||
push:
|
||
tags:
|
||
- 'v*'
|
||
|
||
env:
|
||
REGISTRY: ghcr.io
|
||
# Keep in lock-step with .github/workflows/ci.yml (M-3).
|
||
GO_VERSION: '1.25.9'
|
||
IMAGE_NAMESPACE: shankar0123
|
||
|
||
jobs:
|
||
# ----------------------------------------------------------------------
|
||
# 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:
|
||
name: Build ${{ matrix.binary }} (${{ matrix.os }}/${{ matrix.arch }})
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: read
|
||
id-token: write # Cosign keyless OIDC identity token
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
binary: [agent, server, cli, mcp-server]
|
||
os: [linux, darwin]
|
||
arch: [amd64, arm64]
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Set up Go
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: ${{ env.GO_VERSION }}
|
||
|
||
- name: Extract version from tag
|
||
id: version
|
||
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||
|
||
- name: Install govulncheck
|
||
# Bundle D / Audit L-008: release.yml previously had no vulnerability
|
||
# scan, so a release tag could in principle ship a binary with a
|
||
# known CVE in transitive deps that ci.yml's govulncheck would have
|
||
# caught on master. Pre-build scan blocks the release if anything
|
||
# surfaced post-merge. Pinned to the same major as ci.yml.
|
||
run: go install golang.org/x/vuln/cmd/govulncheck@latest
|
||
|
||
- name: Run govulncheck (release gate)
|
||
# govulncheck distinguishes called-vs-uncalled vulnerable functions.
|
||
# Default exit code (0 unless an actual call site lands in a vuln
|
||
# function) is the right gate for release; deferred-call advisories
|
||
# are tracked separately on master via L-021. If a release-time
|
||
# scan surfaces a NEW called-vuln, the release is blocked until the
|
||
# bump lands on master and a new tag is cut.
|
||
run: govulncheck ./...
|
||
|
||
- name: Build binary
|
||
id: build
|
||
env:
|
||
GOOS: ${{ matrix.os }}
|
||
GOARCH: ${{ matrix.arch }}
|
||
CGO_ENABLED: '0'
|
||
VERSION: ${{ steps.version.outputs.VERSION }}
|
||
run: |
|
||
set -euo pipefail
|
||
OUTPUT_NAME="certctl-${{ matrix.binary }}-${{ matrix.os }}-${{ matrix.arch }}"
|
||
mkdir -p dist
|
||
go build \
|
||
-trimpath \
|
||
-ldflags="-w -s -X main.Version=${VERSION}" \
|
||
-o "dist/${OUTPUT_NAME}" \
|
||
"./cmd/${{ matrix.binary }}"
|
||
ls -lh "dist/${OUTPUT_NAME}"
|
||
echo "output_name=${OUTPUT_NAME}" >> "$GITHUB_OUTPUT"
|
||
|
||
- 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 v3.0 (shipped by cosign-installer@v4.1.1 default
|
||
# cosign-release=v3.0.5) removed --output-signature/--output-certificate
|
||
# on sign-blob. The replacement is --bundle, which emits a unified
|
||
# Sigstore bundle (signature + cert chain + Rekor inclusion proof) as
|
||
# a single .sigstore.json artefact. M-11.
|
||
cosign sign-blob \
|
||
--yes \
|
||
--bundle "dist/${OUTPUT_NAME}.sigstore.json" \
|
||
"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 }}.sigstore.json
|
||
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
|
||
*.sigstore.json|*.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 v3.0 --bundle replaces the removed v2 flag pair
|
||
# --output-signature / --output-certificate. See M-11.
|
||
cosign sign-blob \
|
||
--yes \
|
||
--bundle checksums.txt.sigstore.json \
|
||
checksums.txt
|
||
|
||
- name: Upload artefacts to GitHub Release
|
||
uses: softprops/action-gh-release@v2
|
||
if: startsWith(github.ref, 'refs/tags/')
|
||
with:
|
||
files: |
|
||
artifacts/certctl-*
|
||
artifacts/checksums.txt
|
||
artifacts/checksums.txt.sigstore.json
|
||
|
||
# ----------------------------------------------------------------------
|
||
# 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:
|
||
name: Build & Push Docker Images
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: write
|
||
packages: write
|
||
id-token: write # Cosign keyless OIDC identity token
|
||
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Log in to GitHub Container Registry
|
||
uses: docker/login-action@v3
|
||
with:
|
||
registry: ${{ env.REGISTRY }}
|
||
username: ${{ github.actor }}
|
||
password: ${{ secrets.GITHUB_TOKEN }}
|
||
|
||
- name: Extract version from tag
|
||
id: version
|
||
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||
|
||
- name: Set up Docker Buildx
|
||
uses: docker/setup-buildx-action@v3
|
||
|
||
- name: Install Cosign
|
||
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||
|
||
- name: Build and push server image
|
||
id: server-push
|
||
uses: docker/build-push-action@v6
|
||
with:
|
||
context: .
|
||
file: ./Dockerfile
|
||
push: true
|
||
tags: |
|
||
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-server:${{ steps.version.outputs.VERSION }}
|
||
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-server:latest
|
||
# Proxy propagation (M-4, Issue #9) — forwards runner-level proxy
|
||
# secrets into the Docker build so self-hosted runners behind
|
||
# corporate proxies can reach public registries. GitHub-hosted
|
||
# runners don't need proxies, so the secrets are optional and
|
||
# resolve to empty strings when unset — byte-identical to the
|
||
# pre-fix behaviour for the public-runner path.
|
||
build-args: |
|
||
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
||
HTTPS_PROXY=${{ secrets.HTTPS_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-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
|
||
id: agent-push
|
||
uses: docker/build-push-action@v6
|
||
with:
|
||
context: .
|
||
file: ./Dockerfile.agent
|
||
push: true
|
||
tags: |
|
||
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-agent:${{ steps.version.outputs.VERSION }}
|
||
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/certctl-agent:latest
|
||
# Proxy propagation (M-4, Issue #9) — see server-image step for
|
||
# rationale. Empty secrets resolve to empty build args, leaving
|
||
# the un-proxied code path byte-identical to the pre-fix tree.
|
||
build-args: |
|
||
HTTP_PROXY=${{ secrets.HTTP_PROXY }}
|
||
HTTPS_PROXY=${{ secrets.HTTPS_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-to: type=gha,mode=max
|
||
|
||
- 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:
|
||
name: Create Release Notes
|
||
runs-on: ubuntu-latest
|
||
needs: [build-binaries, aggregate-checksums, provenance-binaries, build-and-push-docker]
|
||
permissions:
|
||
contents: write
|
||
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: Extract version from tag
|
||
id: version
|
||
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
|
||
|
||
- name: Create release with notes
|
||
uses: softprops/action-gh-release@v2
|
||
with:
|
||
generate_release_notes: true
|
||
body: |
|
||
## Installation
|
||
|
||
### Quick Install (Linux/macOS)
|
||
|
||
```bash
|
||
curl -sSL https://raw.githubusercontent.com/shankar0123/certctl/master/install-agent.sh | bash
|
||
```
|
||
|
||
### Manual Binary Download
|
||
|
||
Download the appropriate binary for your OS and architecture:
|
||
|
||
- **Linux x86_64**: `certctl-agent-linux-amd64`
|
||
- **Linux ARM64**: `certctl-agent-linux-arm64`
|
||
- **macOS x86_64**: `certctl-agent-darwin-amd64`
|
||
- **macOS ARM64 (Apple Silicon)**: `certctl-agent-darwin-arm64`
|
||
|
||
Then make it executable and start the service:
|
||
|
||
```bash
|
||
chmod +x certctl-agent-linux-amd64
|
||
sudo mv certctl-agent-linux-amd64 /usr/local/bin/certctl-agent
|
||
```
|
||
|
||
## Docker Images
|
||
|
||
Pull pre-built Docker images for server and agent:
|
||
|
||
```bash
|
||
docker pull ghcr.io/shankar0123/certctl-server:${{ steps.version.outputs.VERSION }}
|
||
docker pull ghcr.io/shankar0123/certctl-agent:${{ steps.version.outputs.VERSION }}
|
||
```
|
||
|
||
Or use the latest tag:
|
||
|
||
```bash
|
||
docker pull ghcr.io/shankar0123/certctl-server:latest
|
||
docker pull ghcr.io/shankar0123/certctl-agent:latest
|
||
```
|
||
|
||
## Docker Compose Quick Start
|
||
|
||
```bash
|
||
git clone https://github.com/shankar0123/certctl.git
|
||
cd certctl
|
||
cp deploy/.env.example deploy/.env
|
||
docker compose -f deploy/docker-compose.yml up -d
|
||
```
|
||
|
||
## Server Binaries
|
||
|
||
Pre-compiled server binaries are also available for direct installation:
|
||
|
||
- **Linux x86_64**: `certctl-server-linux-amd64`
|
||
- **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 \
|
||
--bundle checksums.txt.sigstore.json \
|
||
--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 `.sigstore.json`
|
||
bundle, e.g. `cosign verify-blob --bundle certctl-agent-linux-amd64.sigstore.json …`).
|
||
|
||
**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
|
||
|
||
Deploy certctl to Kubernetes using Helm:
|
||
|
||
```bash
|
||
helm repo add certctl https://github.com/shankar0123/certctl/tree/master/deploy/helm
|
||
helm repo update
|
||
helm install certctl certctl/certctl
|
||
```
|
||
|
||
See `deploy/helm/certctl/` for values customization.
|