Policy as code
A policy written in a document depends on someone remembering it. A policy written as code is enforced on every change, equally for everyone, and leaves a trail of what was decided.
What it is
means expressing the organization's rules ("no bucket is public", "containers do not run as root", "every resource has an owner") in a language a tool can automatically evaluate against an input: a Terraform plan, a Kubernetes manifest, an API request.
The gain is consistency and speed. The rule no longer depends on an attentive reviewer and becomes a gate that answers in seconds, with a clear message about why it blocked.
Example in Rego (OPA)
uses the Rego language. The policy below evaluates the Terraform plan and denies creating a bucket without public access blocking. With Conftest, the same file runs in CI against the plan exported as JSON.
package terraform.s3
import rego.v1
deny contains msg if {
r := input.resource_changes[_]
r.type == "aws_s3_bucket_public_access_block"
r.change.after.block_public_acls == false
msg := sprintf("%s allows public ACL", [r.address])
}
deny contains msg if {
r := input.resource_changes[_]
r.type == "aws_s3_bucket"
not r.change.after.tags.owner
msg := sprintf("%s has no 'owner' tag", [r.address])
}Where to apply it
- In the PR or in CI: evaluate the plan before merge (fast and cheap to fix).
- At cluster admission: a controller (Kyverno or OPA Gatekeeper) rejects objects that violate the policy the moment they reach the API.
- At runtime and in the cloud: managed rules and continuous checks catch what slipped through or changed afterward.
- The three layers complement each other: the CI gate gives early feedback; admission is the safety net nobody bypasses.
Test the policy as code
A policy without tests is an assumption. OPA supports unit tests in Rego with cases that must pass and cases that must be denied. Without them, a rule can silently stop catching anything or, at the other extreme, block legitimate changes and lead the team to turn it off.
Exceptions and gradual adoption
Exceptions exist, and what matters is that they are explicit, with an owner and an expiry, rather than informal loopholes. To adopt without blocking everyone, start in warning mode (the policy only reports), measure what would be blocked, fix the legacy, and only then start blocking: the same observe, shadow and enforce logic used with a .
connections on the map
- Secure infrastructure as codeis validated byPolicy as code
- Policy as codebecomes a gateCI/CD hardening
- Security as an internal productdelivers as a paved pathPolicy as code
updated on 14/10/2026 · sources to go deeper · report an error
in other domains
- Compliance in practice: controls, evidence and auditsgrcautomatic evidence comes from executable policy
- DevSecOpsappsecgates and policies, written as executable code
Study before
Unlocks
test what you learned
Loading questions…