Lab: Signed Artifacts and Verification Policy Rollout (Advanced)
Goal
Run a complete non-production supply-chain flow:
- produce SBOM evidence for one artifact
- sign and attest the artifact
- validate evidence with
cosign verify* - test verification policy in
Audit, thenEnforce
Prerequisites
cosignandsyftinstalled- access to a test image in your registry
- access to
developnamespace - Kyverno engine running
- starter policy templates available:
flux/infrastructure/policy/packs/chapter-14-supply-chain/verify-images.example.yamlflux/infrastructure/policy/packs/chapter-14-supply-chain/verify-attestations.example.yaml
Quick checks:
command -v cosign
command -v syft
kubectl -n kyverno get pods
kubectl get ns develop
Step 1: Select Immutable Artifact
Use digest form whenever possible:
export IMAGE_REF="ghcr.io/<org>/<app>@sha256:<digest>"
echo "$IMAGE_REF"
Hard stop:
- do not use mutable
:latestfor this lab.
Step 2: Generate SBOM and Sign/Attest
syft "$IMAGE_REF" -o spdx-json > sbom.spdx.json
cosign sign --yes "$IMAGE_REF"
cosign attest --yes --predicate sbom.spdx.json --type spdx "$IMAGE_REF"
Step 3: Verify Artifact Evidence
cosign verify "$IMAGE_REF"
cosign verify-attestation --type spdx "$IMAGE_REF"
Capture command output as lab evidence.
Step 4: Apply Chapter 14 Policies in Audit Mode
Use template policies as baseline (keep validationFailureAction: Audit):
kubectl apply -f flux/infrastructure/policy/packs/chapter-14-supply-chain/verify-images.example.yaml
kubectl apply -f flux/infrastructure/policy/packs/chapter-14-supply-chain/verify-attestations.example.yaml
kubectl get cpol | rg "verify|attestation"
Step 5: Trigger Audit Events
Apply one workload with untrusted/unsigned artifact (expected audit signal), then one trusted artifact.
kubectl -n develop apply -f <unsigned-or-untrusted-workload>.yaml
kubectl -n develop apply -f <trusted-workload>.yaml
Inspect reports/events:
kubectl -n develop get events --sort-by=.lastTimestamp | tail -n 30
kubectl get policyreport -A | rg develop
Step 6: Promote One Policy to Enforce
Switch one policy to Enforce in non-production only:
kubectl patch cpol verify-signed-images-example \
--type merge \
-p '{"spec":{"validationFailureAction":"Enforce"}}'
Re-apply untrusted workload and confirm deny.
Step 7: Roll Back to Audit (Cleanup)
kubectl patch cpol verify-signed-images-example \
--type merge \
-p '{"spec":{"validationFailureAction":"Audit"}}'
Optional cleanup:
kubectl delete cpol verify-signed-images-example require-sbom-attestation-example --ignore-not-found=true
rm -f sbom.spdx.json
Evidence to Capture
- immutable image reference used
cosign verifysummarycosign verify-attestationsummary- policyreport/event line for failed verification
- deny output after
Enforcechange
Hard Stop Conditions
- disabling verification policy globally to unblock release
- enforcing in production before stable audit data in non-production
- rebuilding production artifact instead of promoting verified artifact
Done When
- learner demonstrates
Audit -> Enforce -> Auditrollout safely - learner can explain deny reason and remediation path