Claude
Skills
Sign in
Back

sigstore-cosign

Included with Lifetime
$97 forever

Sigstore — keyless signing for software artifacts using OIDC identities and short-lived certificates from Fulcio CA, with Rekor transparency log. Cosign is the CLI for signing/verifying containers, OCI artifacts, blobs, and attestations (SBOMs, provenance). Covers GitHub Actions OIDC integration, policy enforcement (cosign-policy-controller, Kyverno), Notary v2 vs Cosign, and supply-chain attestation patterns (SLSA). USE WHEN: user mentions "Sigstore", "Cosign", "Fulcio", "Rekor", "keyless signing", "OIDC signing", "cosign sign", "cosign verify", "SLSA provenance", "OCI artifact signing", "attestation cosign" DO NOT USE FOR: GPG-style signing - use GPG-specific docs DO NOT USE FOR: Code signing certificates (Apple Developer ID, Authenticode) - platform-specific DO NOT USE FOR: Reproducible builds spec - use `infrastructure/reproducible-builds`

Cloud & DevOps

What this skill does

# Sigstore + Cosign — Keyless Artifact Signing

> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `sigstore` or `cosign`.

## Why Sigstore

Traditional signing requires long-lived private keys: distribute, secure, rotate, audit. Sigstore replaces the model with **keyless signing**:

1. CI proves identity via OIDC (e.g., GitHub Actions has built-in OIDC token)
2. **Fulcio** issues short-lived (10 min) X.509 cert bound to that identity
3. Sign artifact, attach signature + cert to artifact
4. **Rekor** transparency log records the signing event (Merkle tree)
5. Verifier checks: cert chain is valid, identity matches expected, log entry exists

No keys to manage. Identity-based trust. Public auditability via Rekor.

**Sigstore project includes**:
- **Cosign** — CLI for sign/verify (most-used component)
- **Fulcio** — Code-signing CA
- **Rekor** — Transparency log (https://search.sigstore.dev/)
- **Gitsign** — Sign git commits with sigstore (replaces GPG)

Adopted by Kubernetes, npm (since 2023), GitHub container registry, JFrog, Wolfi/Chainguard images.

## Install Cosign

```bash
# macOS
brew install cosign

# Linux
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign-linux-amd64 && sudo mv cosign-linux-amd64 /usr/local/bin/cosign

# Verify
cosign version
```

## Sign a Container Image (Keyless)

```bash
# Push image first
docker push ghcr.io/bhodl/api:1.0.0

# Sign with keyless OIDC (browser opens for OAuth)
cosign sign ghcr.io/bhodl/api:1.0.0

# In CI (no interactive auth — uses ambient OIDC):
COSIGN_EXPERIMENTAL=1 cosign sign --yes ghcr.io/bhodl/api:1.0.0
```

The signature is stored as a separate OCI artifact next to the image (`<image>:<digest>.sig`).

## Verify

```bash
cosign verify ghcr.io/bhodl/api:1.0.0 \
    --certificate-identity-regexp="^https://github\.com/bhodl/api/" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"
```

`--certificate-identity-regexp` constrains who could have signed (the workflow URL). `--certificate-oidc-issuer` constrains the OIDC provider.

For a specific workflow:

```bash
cosign verify ghcr.io/bhodl/api:1.0.0 \
    --certificate-identity="https://github.com/bhodl/api/.github/workflows/release.yml@refs/heads/main" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"
```

## Sign with a Key (Traditional)

If you must use a key (e.g., air-gapped CI):

```bash
# Generate keypair (encrypted private key)
cosign generate-key-pair
# → cosign.key, cosign.pub

# Sign
cosign sign --key cosign.key ghcr.io/bhodl/api:1.0.0

# Verify
cosign verify --key cosign.pub ghcr.io/bhodl/api:1.0.0
```

For HSM/KMS-backed keys:

```bash
cosign sign --key azurekms://my-vault.vault.azure.net/my-key ghcr.io/bhodl/api:1.0.0
cosign sign --key gcpkms://projects/PROJ/locations/LOC/keyRings/RING/cryptoKeys/KEY ...
cosign sign --key awskms://us-east-1/KEY-UUID ...
cosign sign --key hashivault://my-key ...
```

## Sign Blobs (Files, Not Containers)

```bash
# Sign a binary
cosign sign-blob --yes my-app.tar.gz \
    --output-signature my-app.tar.gz.sig \
    --output-certificate my-app.tar.gz.pem

# Verify
cosign verify-blob my-app.tar.gz \
    --signature my-app.tar.gz.sig \
    --certificate my-app.tar.gz.pem \
    --certificate-identity-regexp="^https://github\.com/bhodl/" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"
```

For a release: sign the SHA-256 of the artifact:

```bash
cosign sign-blob --yes <(sha256sum my-app.tar.gz | cut -d' ' -f1)
```

## Attestations (Verifiable Metadata)

Attach SBOM, provenance, or custom predicates to an artifact:

```bash
# Generate SBOM (e.g., with syft)
syft ghcr.io/bhodl/api:1.0.0 -o spdx-json > sbom.spdx.json

# Attach as attestation
cosign attest --yes \
    --predicate sbom.spdx.json \
    --type spdxjson \
    ghcr.io/bhodl/api:1.0.0

# Verify attestation
cosign verify-attestation \
    --type spdxjson \
    --certificate-identity-regexp="^https://github\.com/bhodl/" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
    ghcr.io/bhodl/api:1.0.0
```

Predicate types:
- `slsaprovenance` — build provenance (SLSA spec)
- `spdxjson`, `cyclonedx` — SBOM formats
- `vuln` — vulnerability scan
- `custom` — your own JSON schema

## SLSA Provenance

SLSA (Supply-chain Levels for Software Artifacts) — framework for build attestation. Generate provenance via SLSA GitHub action:

```yaml
# .github/workflows/release.yml
permissions:
  id-token: write
  contents: read
  packages: write

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      digest: ${{ steps.build.outputs.digest }}
    steps:
      - uses: actions/checkout@v4
      - id: build
        run: |
          docker buildx build --push --tag ghcr.io/bhodl/api:${{ github.sha }} . > digest.txt
          echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT

  provenance:
    needs: build
    permissions:
      actions: read
      id-token: write
      packages: write
    uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
    with:
      image: ghcr.io/bhodl/api
      digest: ${{ needs.build.outputs.digest }}
      registry-username: ${{ github.actor }}
    secrets:
      registry-password: ${{ secrets.GITHUB_TOKEN }}
```

Attestation auto-pushed alongside image, signed by Sigstore.

## GitHub Actions OIDC Setup

Cosign keyless requires GitHub's `id-token` permission:

```yaml
permissions:
  id-token: write          # required for OIDC
  contents: read
  packages: write          # if pushing to ghcr.io

jobs:
  sign:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build & push
        run: |
          docker build -t ghcr.io/bhodl/api:${{ github.sha }} .
          docker push ghcr.io/bhodl/api:${{ github.sha }}

      - name: Install cosign
        uses: sigstore/[email protected]

      - name: Sign image
        env:
          COSIGN_EXPERIMENTAL: "true"
        run: cosign sign --yes ghcr.io/bhodl/api:${{ github.sha }}
```

## Policy Enforcement (Kubernetes)

### Cosigned (deprecated) → policy-controller

```bash
helm install policy-controller \
    sigstore/policy-controller \
    --version 0.10.0 \
    -n cosign-system --create-namespace
```

Define policy:

```yaml
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: bhodl-images-must-be-signed
spec:
  images:
    - glob: ghcr.io/bhodl/**
  authorities:
    - keyless:
        url: https://fulcio.sigstore.dev
        identities:
          - issuer: https://token.actions.githubusercontent.com
            subjectRegExp: ^https://github\.com/bhodl/api/\.github/workflows/release\.yml@refs/heads/main$
```

Pods using `ghcr.io/bhodl/*` images that aren't signed by the right workflow → rejected.

### Kyverno Equivalent

```yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-signatures
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-image-signatures
      match:
        any:
        - resources:
            kinds: [Pod]
      verifyImages:
        - imageReferences:
            - "ghcr.io/bhodl/*"
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/bhodl/*"
                    issuer: "https://token.actions.githubusercontent.com"
```

## Sign Git Commits — Gitsign

Sigstore replacement for GPG commit signing.

```bash
brew install gitsign

git config --global commit.gpgsign true
git config --global tag.gpgsign true
git config --global gpg.x509.program gitsign
git config --global gpg.format x509

# Sign a commit (browser opens for OAuth)
git commit -m "feat: add wallet sync"

# View signature
git log --show-signature -1
```

## Inspect 

Related in Cloud & DevOps