Production-grade platform engineering handbook — Kubernetes, Terraform, Flux CD, GitHub Actions, AWS, and more.
67
84%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Secure the software supply chain — from the build pipeline to running containers.
When invoked with no arguments, ask before proceeding:
Q1 — Mode?
What do you need?
1. audit — review an existing CI/CD pipeline for supply chain security gaps
2. sign — set up keyless image signing with Cosign (Sigstore/Rekor, no key management)
3. sbom — generate and attest an SBOM with Syft
4. scan — add a CVE vulnerability gate with Trivy or Grype
5. enforce — write a Kyverno policy to block unsigned images at admission
6. slsa — generate a SLSA Level 2 provenance workflow
Enter 1–6 or mode name:Q2 — Context (after mode selected, one at a time):
Paste your GitHub Actions workflow file(s) or describe your current CI/CD pipeline:Which container registry? (ECR / GHCR / Docker Hub / other):Which image and registry? (e.g. ghcr.io/org/image):Which scanner preference? Trivy (recommended) or Grype — or no preference:Which registry or image prefix should the policy cover? (e.g. ghcr.io/myorg/*):Which registry and repo? (e.g. ghcr.io/org/image from github.com/org/repo):Then proceed into the relevant mode below.
Review an existing CI/CD pipeline and cluster admission configuration for supply chain security gaps.
Steps:
[CRITICAL] No image signing — any image can be admitted to the cluster
[CRITICAL] No CVE severity gate — vulnerable images pass CI
[HIGH] No SBOM attestation — cannot audit what is running
[MEDIUM] Action versions pinned to tag, not SHAReference: references/supply-chain.md → Gap classification, Fix order
Set up keyless image signing with Cosign using Sigstore/Rekor (no key management required).
Steps:
- name: Install Cosign
uses: sigstore/cosign-installer@11086d9f32b178aa24e93c2b86eba3ef4b16b68a # v3.8.1
- name: Sign image
run: |
cosign sign --yes \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}cosign verify \
--certificate-identity-regexp="https://github.com/<org>/<repo>/.github/workflows/.*" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
ghcr.io/<org>/<image>@<digest>@sha256:…), never the tag — tags are mutableKey rules:
cosign-installer to a full SHA, e.g.: sigstore/cosign-installer@11086d9f32b178aa24e93c2b86eba3ef4b16b68aReference: references/supply-chain.md → Keyless signing, Rekor transparency log
Generate a Software Bill of Materials with Syft and attest it as an OCI artifact alongside the image.
Steps:
- name: Generate SBOM
uses: anchore/sbom-action@61119d458adab75f756bc0b9e4bde25725f86a7a # v0.20.0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
format: spdx-json
output-file: sbom.spdx.json
- name: Attest SBOM
run: |
cosign attest --yes \
--predicate sbom.spdx.json \
--type spdxjson \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}cosign download attestation \
--predicate-type https://spdx.dev/Document \
ghcr.io/<org>/<image>@<digest> | jq '.payload | @base64d | fromjson'spdx-json format for broadest tooling compatibility; cyclonedx-json is an alternativeReference: references/supply-chain.md → SBOM formats, Syft, Attestation
Add a CVE vulnerability scan with a configurable severity gate that fails the build.
Steps:
- name: Scan image for vulnerabilities
uses: aquasecurity/trivy-action@18f2135c0b15d26b3a4c2efded75e06b6f0e4884 # v0.30.0
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
format: table
exit-code: '1'
ignore-unfixed: true
vuln-type: os,library
severity: CRITICAL,HIGHignore-unfixed: true — skip CVEs with no fix available (reduces noise without reducing security)- name: Scan with Grype
uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7.4.0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
fail-build: true
severity-cutoff: highReference: references/supply-chain.md → Trivy vs Grype, Severity gates
Generate a Kyverno ImageValidatingPolicy that blocks unsigned or unverified images at admission time.
Steps:
apiVersion: policies.kyverno.io/v1
kind: ImageValidatingPolicy
metadata:
name: require-signed-images
spec:
validationActions: [Audit] # switch to [Deny] after all images are signing
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
matchImageReferences:
- glob: "ghcr.io/<org>/*"
validations:
- expression: >
images.containers.map(image, verifyImageSignatures(image, [{"keyless": {
"url": "https://fulcio.sigstore.dev",
"rekor": {"url": "https://rekor.sigstore.dev"},
"identities": [{"issuer": "https://token.actions.githubusercontent.com",
"subjectRegExp": "https://github.com/<org>/.*"}]
}}])).all(e, e > 0)
message: "Image must be signed via Sigstore keyless signing from GitHub Actions"spec:
validationActions: [Audit] # start here, switch to [Deny] after validation/platform-skills:kyverno for full ImageValidatingPolicy guidanceReference: references/supply-chain.md → Kyverno enforcement, references/kyverno.md → ImageValidatingPolicy
Generate a GitHub Actions workflow for SLSA Level 2 provenance using slsa-github-generator.
Steps:
jobs:
build:
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.build.outputs.digest }}
permissions:
contents: read
packages: write
steps:
- name: Build and push image
id: build
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0
with:
push: true
tags: ghcr.io/<org>/<image>:${{ github.sha }}
provenance:
needs: build
permissions:
actions: read
id-token: write
packages: write
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@5a775b367a56d5bd118a224a811bba288150a563 # v2.0.0
with:
image: ghcr.io/<org>/<image>
digest: ${{ needs.build.outputs.digest }}
registry-username: ${{ github.actor }}
secrets:
registry-password: ${{ secrets.GITHUB_TOKEN }}slsa-verifier verify-image \
ghcr.io/<org>/<image>@<digest> \
--source-uri github.com/<org>/<repo> \
--source-branch maingenerator_container_slsa3.yml produces L2 provenance by default; L3 requires hermetic builds not available on standard GitHub-hosted runnersReference: references/supply-chain.md → SLSA levels, slsa-github-generator
After completing any supply-chain mode, log findings while context is fresh:
ERR in .learnings/ERRORS.mdLRN in .learnings/LEARNINGS.mdUse /platform-skills:self-improve log for each entry. Do not defer to end of session.
.claude-plugin
.github
commands
docs
examples
agent-self-improve
argocd
awesome-docs
aws
cloudfront
functions
lambda-edge
functions
azure
compliance
conventional-commits
datadog
llm-observability
demo
documentation
dora
dynatrace
fluxcd
github-actions
composite-actions
configure-cloud
db-migrate
docker-build-push
k8s-deploy
notify-slack
pr-comment
release-tag
security-scan
setup-env
setup-terraform
terraform-plan
helm
web-service
templates
kubernetes
kyverno
mcp
observability
openshift
pr-review
ownership
runtime-security
supply-chain
terraform
references
scripts
skills
platform-skills
tests