Software Supply Chain Security¶
This guide hardens the software lifecycle end to end: generating SBOMs, checking for vulnerabilities, signing and verifying images, and raising your SLSA assurance level.
Goals¶
- Generate reproducible SBOMs (Syft)
- Scan for vulnerabilities (Grype/Trivy)
- Sign and verify images (Sigstore/Cosign)
- Record verification evidence (Rekor)
- Raise assurance with SLSA (level 3 recommended)
SBOMs with Syft¶
# Generate an SBOM (CycloneDX or SPDX)
syft packages myapp:latest -o cyclonedx-json > sbom.json
# For repositories
syft dir:./ -o spdx-json > repo-sbom.json
Best practices: - Ship the SBOM as part of your release artifacts - Version SBOMs and publish them alongside the image - Validate the format with CycloneDX/SPDX tooling
Vulnerability Scanning¶
# Grype against an image
grype myregistry/myapp:1.2.3 --fail-on high
# Trivy against a Dockerfile and the filesystem
trivy image myregistry/myapp:1.2.3 --severity HIGH,CRITICAL
trivy fs . --security-checks vuln,secret,config
CI integration:
- Fail fast with --fail-on at high severities
- Export SARIF reports for GitHub Security
Signing and Verification with Cosign (Sigstore)¶
# OIDC login, keyless
cosign login myregistry.example.com
# Keyless signing with OIDC (GitHub/GitLab/Workload Identity)
COSIGN_EXPERIMENTAL=1 cosign sign myregistry/myapp:1.2.3
# Verification (checks identity and provenance)
COSIGN_EXPERIMENTAL=1 cosign verify myregistry/myapp:1.2.3 \
--certificate-identity "https://github.com/org/repo/.github/workflows/release.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
Recommendations: - Prefer keyless with OIDC (far less key management) - Enforce verification inside the cluster (Admission Controller)
Recording in Rekor¶
# Publish the signed artifact to the transparency log
cosign upload blob --yes --rekor-url https://rekor.sigstore.dev signed.json
# Look up the evidence
rekor-cli search --artifact myregistry/myapp:1.2.3
SLSA: Assurance Levels¶
- SLSA 1: Traceable provenance
- SLSA 2: Controlled build
- SLSA 3: Reproducible builds, isolated build environment
- SLSA 4: End-to-end hardened, independently verified
Practical guidance:
- Build in isolated environments (ephemeral runners)
- Generate provenance (attestations) and attach it to the image
- Validate provenance at deploy time (policy-as-code)
Admission Policies (Kubernetes)¶
An OPA Gatekeeper example that requires a verified signature:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sverifiedimages
spec:
crd:
spec:
names:
kind: K8sVerifiedImages
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sverifiedimages
violation[{
"msg": msg,
"details": {}}] {
input.review.kind.kind == "Pod"
some i
img := input.review.object.spec.containers[i].image
not startswith(img, "myregistry.example.com/")
msg := sprintf("Image not allowed or signature not verified: %s", [img])
}
Quick Checklist¶
- SBOM generated and published
- Automated scanning in CI/CD
- Image signing/verification enabled
- Admission policies blocking unverified images
- Evidence recorded in Rekor
- A documented SLSA ≥ 3 target