High-profile attacks like SolarWinds and Log4j have proven that the software supply chain is a primary target for adversaries. Securing your own code is no longer enough; you must also secure the entire lifecycle of dependencies, build processes, and deployment pipelines that bring your software to production.
Policy as Code provides the automated, enforceable guardrails necessary to secure this complex chain of trust. This guide will show you how to apply policies at each stage to create a verifiably secure software supply chain.
The Four Pillars of Supply Chain Security (Based on SLSA)
We can frame our policy enforcement around the core principles of the SLSA framework (Supply-chain Levels for Software Artifacts), which focuses on ensuring the integrity of your software at every step.
1οΈβ£ Source Integrity
Ensuring the source code you write is authentic, unmodified, and reviewed. Policies can enforce branch protection, signed commits, and required code reviews.
2οΈβ£ Build Integrity
Ensuring the build process is secure, reproducible, and isolated. Policies can mandate specific, hardened build platforms and verify the provenance of build artifacts.
3οΈβ£ Dependency Integrity
Ensuring all third-party libraries and packages are vetted and free from known vulnerabilities. Policies can analyze a Software Bill of Materials (SBOM) to enforce these checks.
4οΈβ£ Deployment Integrity
Ensuring only verified, untampered artifacts are deployed into production. Policies can check for cryptographic signatures (like those from Sigstore) before allowing a deployment.
Practical Policies for Each Pillar
Pillar 1: Source Integrity Policy
You can enforce source integrity rules directly in your version control system. This example uses a GitHub Actions workflow to check for signed commits.
π‘οΈ GitHub Actions: Enforce Signed Commits
name: Source Integrity Check
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
verify-commit-signatures:
runs-on: ubuntu-latest
steps:
- name: Verify all commits are signed
uses: a-b-r-o-w-n/verify-commit-signatures@v1
with:
token: {${ secrets.GITHUB_TOKEN }} Pillar 2: Build Integrity Policy
This OPA/Rego policy ensures that a CI/CD pipeline definition only uses approved, hardened build runners.
ποΈ Rego: Secure Builder Policy
package cicd.build_integrity
# Deny if the build job is not using an approved runner
deny[msg] {
job := input.jobs[_]
not startswith(job.runner, "secure-hardened-runner-")
msg := sprintf("Job '%v' is using an insecure runner '%v'. Only 'secure-hardened-runner-*' is allowed.", [
job.name,
job.runner
])
} Pillar 3: Dependency Integrity Policy
This policy inspects a CycloneDX Software Bill of Materials (SBOM) to block any dependencies with `Critical` or `High` severity vulnerabilities.
π¦ Rego: SBOM Vulnerability Check
package sbom.vulnerability_check
# Deny if any component has a critical or high severity vulnerability
deny[msg] {
component := input.sbom.components[_]
vulnerability := component.vulnerabilities[_]
is_severe_vulnerability(vulnerability)
msg := sprintf("Blocked dependency '%v': Contains a '%v' severity vulnerability (%v).", [
component.name,
vulnerability.severity,
vulnerability.id
])
}
is_severe_vulnerability(vulnerability) {
vulnerability.severity == "Critical"
}
is_severe_vulnerability(vulnerability) {
vulnerability.severity == "High"
} Pillar 4: Deployment Integrity Policy
This Kyverno policy, for Kubernetes, ensures that no container image can be deployed unless it has been cryptographically signed by your trusted CI/CD system using Cosign/Sigstore.
βοΈ Kyverno: Enforce Signed Images Policy
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: enforce-signed-images
spec:
validationFailureAction: Enforce
background: false
rules:
- name: check-image-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/your-org/*" # Match all images from your container registry
attestors:
- count: 1
entries:
- keys:
# The public key of your CI/CD pipeline's signing identity
publicKey: |
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY----- Conclusion: Building a Verifiable Chain of Trust
Securing the software supply chain requires a defense-in-depth approach. By using Policy as Code to enforce integrity checks at every stageβsource, build, dependencies, and deploymentβyou move from a model of implicit trust to one of explicit, automated verification. This not only enhances your security posture but also creates an auditable, compliant, and trustworthy path from code to cloud.