Stage 7 · Master
Policy as Code & Security Guardrails
Supply Chain Security: SLSA & Sigstore
SLSA levels, provenance, cosign signing, Rekor transparency log. Verify in admission controller. SBOM generation with Syft.
SLSA Framework
SLSA (Supply Chain Levels for Software Artifacts) is a framework for securing software supply chains. Four levels of increasing assurance. Platform engineering should target SLSA Level 3 for golden path services.
| Level | Name | Requirements | Threats Mitigated |
|---|---|---|---|
| 1 | Documented Build | Build scripted, provenance generated | Tampering during build, lost history |
| 2 | Authenticated Build | Level 1 + signed provenance, hosted build service | Compromised build process, insider threat |
| 3 | Hardened Build | Level 2 + non-falsifiable provenance, isolated build | Compromised build platform, credential theft |
| 4 | Reproducible Build | Level 3 + hermetic, reproducible builds | All supply chain threats |
Sigstore: Cosign, Rekor, Fulcio
Sigstore provides free, keyless signing and transparency log for software artifacts. Cosign signs, Fulcio issues short-lived certificates, Rekor provides immutable transparency log.
- Cosign: CLI for signing/verifying containers, blobs, Git commits. Supports keyless (OIDC) and key-based signing
- Fulcio: Free CA issuing short-lived certificates bound to OIDC identity (GitHub, Google, Microsoft, SPIFFE)
- Rekor: Immutable transparency log. All signatures publicly auditable. Search by subject, issuer, time
- Policy Controller: Kyverno/Gatekeeper verify signatures at admission time
# Sign container image (keyless - uses OIDC)
cosign sign ghcr.io/myorg/payment-api:v1.2.3
# Verify signature
cosign verify ghcr.io/myorg/payment-api:v1.2.3 --certificate-identity-regexp "https://github.com/myorg/.*" --certificate-oidc-issuer "https://token.actions.githubusercontent.com"
# Sign with annotations (SBOM, SLSA)
cosign sign ghcr.io/myorg/payment-api:v1.2.3 -a "slsa-level=3" -a "sbom=spdx" -a "built-by=github-actions"
# Verify with policy
cosign verify ghcr.io/myorg/payment-api:v1.2.3 --certificate-identity-regexp "https://github.com/myorg/.*" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" --annotation slsa-level=3
Cosign keyless signing uses GitHub OIDC token. No long-lived keys. Verification checks identity + issuer + annotations.
Build Provenance
Provenance is cryptographically signed metadata about how an artifact was built: source repo, commit, build script, dependencies, builder identity. SLSA provenance format (in-toto).
name: Build and Sign
on:
push:
tags: ['v*']
workflow_dispatch:
permissions:
id-token: write
contents: read
attestations: write
jobs:
build:
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
with:
base64-subjects: ${{ hashFiles('**/Dockerfile') }}
provenance-name: provenance.intoto.jsonl
secrets:
registry-username: ${{ secrets.REGISTRY_USERNAME }}
registry-password: ${{ secrets.REGISTRY_PASSWORD }}
sign:
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write
packages: write
attestations: write
steps:
- uses: actions/download-artifact@v4
with:
name: provenance
- name: Sign with Cosign
uses: sigstore/cosign-installer@v3
- run: |
cosign sign --yes ghcr.io/myorg/payment-api:${{ github.ref_name }} --certificate-identity-regexp "https://github.com/myorg/.*" --certificate-oidc-issuer https://token.actions.githubusercontent.com --attachment sbom=spdx --attachment provenance=intoto.jsonl
SLSA Level 3 provenance generated by slsa-github-generator. Cosign signs image + attaches provenance + SBOM.
Admission Controller Verification
Kyverno/Gatekeeper verify cosign signatures at admission time. Only signed images from approved identities can deploy. Unsigned or tampered images rejected.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
background: true
rules:
- name: verify-cosign
match:
any:
- resources:
kinds: ["Pod", "Deployment", "StatefulSet", "DaemonSet", "Job", "CronJob"]
verifyImages:
- image: "ghcr.io/myorg/*"
key: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
# Or keyless verification
# certificates:
# - identity: https://github.com/myorg/*
# issuer: https://token.actions.githubusercontent.com
# extensions:
# - oid: 1.3.6.1.4.1.57264.1.1
# value: slsa-level-3
- image: "docker.io/library/*"
# Allow official images without signature (or use different key)
key: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----
exclude:
namespaces: ["kube-system", "monitoring", "ingress-nginx"]
images:
- "ghcr.io/myorg/*:dev-*"
- "ghcr.io/myorg/*:pr-*"
Verify images from ghcr.io/myorg/* signed by our key. Allow dev/pr images unsigned. Exclude system namespaces.
SBOM Generation with Syft
Software Bill of Materials (SBOM) lists all components in an artifact. SPDX and CycloneDX formats. Generated at build time, attached to image, queried for vulnerabilities.
# Install syft
brew install anchore/syft/syft
# Generate SBOM for local image
syft ghcr.io/myorg/payment-api:v1.2.3 -o spdx-json=sbom.spdx.json
# Generate SBOM for Dockerfile (without building)
syft dir:. -o spdx-json=sbom.spdx.json
# Generate SBOM in CI
syft ghcr.io/myorg/payment-api:${{ github.ref_name }} -o spdx-json=sbom.spdx.json -o cyclonedx-json=sbom.cdx.json
# Attach to image with cosign
cosign attach sbom --sbom sbom.spdx.json ghcr.io/myorg/payment-api:v1.2.3
# Verify SBOM attachment
cosign verify-attestation --type spdx ghcr.io/myorg/payment-api:v1.2.3
Syft generates SBOM in SPDX/CycloneDX. Cosign attaches as in-toto attestation. Verifiable at admission time.
Implementation Roadmap
| Phase | Actions | SLSA Level |
|---|---|---|
| 1. Foundation | Enable GitHub Actions OIDC, cosign keyless signing, generate provenance | 1 |
| 2. Signing | Sign all golden path images, attach SBOM, verify in CI | 2 |
| 3. Admission | Deploy Kyverno image verification, enforce signed images | 2-3 |
| 4. Attestations | Require SLSA provenance, SBOM, vulnerability scan attestations | 3 |
| 5. Hardening | Hermetic builds, reproducible builds, pinned dependencies | 4 |
Don't try to secure everything at once. Start with golden path templates: they generate signed images with provenance by default. Legacy services get exception with migration timeline. New services inherit security by default.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.