SLSA Provenance Policy Templates¶
Enforce SLSA requirements through policy-as-code.
Prerequisites
These policies integrate with Verification Workflows and Advanced Verification Patterns. CI/CD must verify provenance and record results before policy enforcement.
Overview¶
Policy engines transform SLSA verification from optional checks to mandatory gates:
- Kyverno policies - Native Kubernetes policy engine with CEL expressions
- OPA Gatekeeper - Rego-based constraint framework for complex logic
- Admission control - Block non-compliant deployments at API level
- Audit mode - Identify violations without blocking (adoption phase)
Architecture pattern: CI/CD verifies provenance → Updates verification registry → Policy enforces at deployment time.
Policy Enforcement Architecture¶
graph TD
A[CI/CD Pipeline] -->|Generates| B[Artifact + Provenance]
B -->|slsa-verifier| C[Verification Job]
C -->|Success| D[Update Registry]
C -->|Failure| X[Block Release]
D -->|Records| E[ConfigMap/CRD]
E -->|Referenced by| F[Policy Engine]
F -->|Evaluates| G[Pod Creation]
G -->|Verified| H[✅ Allow]
G -->|Not Verified| I[❌ Deny]
%% Ghostty Hardcore Theme
style A fill:#65d9ef,color:#1b1d1e
style C fill:#a7e22e,color:#1b1d1e
style D fill:#ffd866,color:#1b1d1e
style F fill:#f92572,color:#1b1d1e
style H fill:#a9dc76,color:#1b1d1e
style I fill:#f92572,color:#1b1d1e
style X fill:#f92572,color:#1b1d1e
Critical insight: Policy engines don't verify provenance directly. They enforce that only verified images are deployed.
Kyverno Templates¶
Policy 1: Require SLSA Level 3 (Strict)¶
Block all pods using images without verified SLSA Level 3 provenance.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-slsa-level-3
annotations:
policies.kyverno.io/title: Require SLSA Level 3 Provenance
policies.kyverno.io/severity: high
policies.kyverno.io/description: >-
All container images must have verified SLSA Level 3 provenance.
Blocks deployment of images not in verified registry.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: verify-image-provenance
match:
any:
- resources:
kinds:
- Pod
context:
- name: verifiedImages
configMap:
name: slsa-verified-images
namespace: slsa-system
validate:
message: >-
Image {{ request.object.spec.containers[].image }} lacks verified SLSA Level 3 provenance.
Only images in slsa-verified-images ConfigMap are allowed.
foreach:
- list: "request.object.spec.containers[*]"
deny:
conditions:
all:
- key: "{{ element.image }}"
operator: AnyNotIn
value: "{{ verifiedImages.data.images }}"
Enforcement: Production-ready. Blocks all non-verified images.
Deployment: Deploy to slsa-system namespace. CI/CD updates ConfigMap on successful verification.
Policy 2: Audit Mode (Adoption Phase)¶
Identify violations without blocking deployments. Use during initial SLSA adoption.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: audit-slsa-provenance
annotations:
policies.kyverno.io/title: Audit SLSA Provenance Compliance
policies.kyverno.io/severity: medium
spec:
validationFailureAction: Audit
background: true
rules:
- name: audit-unverified-images
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production
- staging
context:
- name: verifiedImages
configMap:
name: slsa-verified-images
namespace: slsa-system
validate:
message: "Image {{ request.object.spec.containers[].image }} not in verified registry"
foreach:
- list: "request.object.spec.containers[*]"
deny:
conditions:
all:
- key: "{{ element.image }}"
operator: AnyNotIn
value: "{{ verifiedImages.data.images }}"
Usage: Run for 30 days. Collect metrics. Identify teams needing SLSA support.
Transition: Change validationFailureAction: Audit to Enforce when ready.
Policy 3: Namespace-Specific Enforcement¶
Enforce SLSA only in production, allow flexibility in development.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: production-slsa-enforcement
spec:
validationFailureAction: Enforce
background: true
rules:
- name: production-requires-slsa-3
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production
- production-*
context:
- name: verifiedImages
configMap:
name: slsa-verified-images
namespace: slsa-system
validate:
message: "Production namespace requires SLSA Level 3 verified images"
foreach:
- list: "request.object.spec.containers[*]"
deny:
conditions:
all:
- key: "{{ element.image }}"
operator: AnyNotIn
value: "{{ verifiedImages.data.images }}"
Pattern: Progressive enforcement. Production first, expand to staging, then development.
OPA Gatekeeper Templates¶
ConstraintTemplate: SLSA Level Enforcement¶
Define reusable constraint for SLSA level enforcement.
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: slsaprovenance
spec:
crd:
spec:
names:
kind: SLSAProvenance
validation:
openAPIV3Schema:
type: object
properties:
minimumLevel:
type: integer
minimum: 1
maximum: 4
description: "Minimum SLSA level required (1-4)"
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package slsa.provenance
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not is_verified(container.image)
msg := sprintf("Image %v lacks verified SLSA provenance", [container.image])
}
is_verified(image) {
verified_images := data.inventory.cluster["v1"]["ConfigMap"]["slsa-system"]["slsa-verified-images"].data.images
contains(verified_images, image)
}
Apply constraint:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: SLSAProvenance
metadata:
name: require-slsa-level-3
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- production
parameters:
minimumLevel: 3
Verification Registry Setup¶
ConfigMap: Verified Images Registry¶
CI/CD updates this ConfigMap after successful provenance verification.
apiVersion: v1
kind: ConfigMap
metadata:
name: slsa-verified-images
namespace: slsa-system
data:
images: |
ghcr.io/adaptive-enforcement-lab/app:v1.2.0
ghcr.io/adaptive-enforcement-lab/app:v1.2.1
ghcr.io/adaptive-enforcement-lab/api:v2.0.0
Update script (run in CI/CD after verification):
#!/usr/bin/env bash
IMAGE="$1"
kubectl patch configmap slsa-verified-images \
--namespace slsa-system \
--type merge \
-p "{\"data\":{\"images\":\"$(kubectl get configmap slsa-verified-images -n slsa-system -o jsonpath='{.data.images}')\n$IMAGE\"}}"
Workflow integration:
- name: Update verified registry
if: steps.verify.outcome == 'success'
run: |
IMAGE="${{ env.REGISTRY }}/${{ github.repository }}:${{ github.sha }}"
./scripts/update-verified-registry.sh "$IMAGE"
FAQ¶
Can I enforce different SLSA levels per namespace? Yes. Use namespace-specific policies with different minimumLevel parameters in OPA or separate Kyverno policies per namespace.
What if CI/CD verification fails but artifact is safe? Use exception annotation with approval ticket. Time-bound exceptions only. Audit exception usage.
How do I test policies before enforcement? Use audit mode first (validationFailureAction: Audit). Test in non-production cluster. Validate with kubectl --dry-run=server.
What happens if ConfigMap is deleted? All deployments blocked. Treat ConfigMap as critical infrastructure. Backup and monitor with alerts.
Can I integrate with external verification services? Yes. Use OPA Gatekeeper with external data source. Call verification API in Rego policy using http.send.
Related Content¶
- Verification Workflows: CI/CD verification patterns
- Advanced Verification Patterns: Policy engine integration architecture
- SLSA Implementation Playbook: Complete adoption guide
- SLSA Levels: Understand SLSA level requirements
Verification proves integrity. Policy enforces compliance. Automation scales trust.