Key points
- Decouples authorization decisions from application code: apps query a policy engine instead of embedding rules.
- Languages: Rego (Open Policy Agent), Cedar (AWS / Permit.io), HCL Sentinel (HashiCorp), Casbin DSL.
- Benefits: versioned in Git, peer-reviewed, unit-tested, deployable as a service, observable, auditable.
- Use cases: API authorization, Kubernetes admission, IaC scanning, cloud entitlements, data access (Snowflake, Databricks row/column policies).
- Maturity test: can a security engineer change a policy without redeploying the app? If no, you don't have policy as code.
What is Policy as Code?
Policy as Code (PaC) is the practice of writing authorization, compliance, and governance rules as declarative, version-controlled code, evaluated by a dedicated policy engine at decision time. Instead of if (user.role === 'admin' && resource.tenant === user.tenant) scattered across services, you author one policy in Rego or Cedar, deploy it like any other artifact, and apps query the engine for a decision.
Why it matters
- Auditability — every policy change is a Git commit.
- Testability — policies have unit tests; you can prove a change doesn't break least privilege.
- Reuse — one policy can govern an API, a Kubernetes admission webhook, and a Terraform plan.
- Separation of duties — security writes policy, developers write app code.
- Speed of change — change a rule without redeploying a service.
Where it shows up
- API authorization — services call OPA / Cedar / Oso at request time.
- Kubernetes admission — OPA Gatekeeper / Kyverno block non-compliant pods.
- Infrastructure as Code — Sentinel, OPA, Checkov scan Terraform plans for misconfigurations.
- Cloud entitlements — CIEM tools generate least-privilege policies.
- Data access — Snowflake masking policies, Databricks Unity Catalog row/column rules.
Picking an engine
| Engine | Language | Strength | | --- | --- | --- | | OPA | Rego | Mature, broad ecosystem, K8s default | | Cedar | Cedar | Analyzable, formal verification, AWS-aligned | | Oso | Polar | Application authorization, fine-grained | | Casbin | Domain-specific | Lightweight embedding | | Topaz | Rego + ReBAC | Combined ABAC + ReBAC |
Common mistakes
- Embedding policy decisions in app code anyway — defeats the purpose.
- One mega-policy — break by domain, version independently.
- No testing harness — every PaC project should ship with golden-file tests.
- No observability — log decisions (input + output + policy version) to a SIEM.
Editorial note
Policy as Code is a means, not an end. The point is externalized, auditable, testable authorization. Pick the engine that fits your stack; the bigger leverage is the workflow change.
