TL;DR: Policy as code turns least-privilege enforcement from a quarterly spreadsheet exercise into a versioned, tested, CI-gated artifact. OPA (Rego) is the general-purpose, cross-stack choice; Cedar is the narrower, faster, formally-verifiable choice purpose-built for principal-action-resource authorization. Automated access reviews built on either engine trade some operational velocity for security — the real engineering work is managing the false-positive rate so that trade-off doesn't quietly become "guardrails everyone routes around."

Why least-privilege IAM keeps failing as a manual process

Least-privilege access — granting exactly the permissions a principal needs, no more — is a security best practice nobody disputes and almost nobody fully achieves in practice. The reason is structural: manual permission reviews are periodic (quarterly, if you're disciplined), while permission requests are continuous. By the time a review catches an over-provisioned role, it's often been over-provisioned for months, and the person who requested it has usually forgotten why.

Policy as code addresses the structural mismatch, not just the tooling: permissions become declarative, version-controlled artifacts that can be tested, diffed, and gated in CI the same way application code is — closing the gap between when over-privilege is introduced and when it's caught.

OPA and Cedar: different tools for different layers

Open Policy Agent (OPA), using its Rego policy language, is a general-purpose policy engine. It isn't specific to IAM — the same engine can gate Kubernetes admission control, Terraform plan approval, CI/CD pipeline decisions, and application-level authorization, all with one policy language and one evaluation model. That breadth is OPA's core value proposition for platform teams that want a single policy plane across a heterogeneous stack (Envoy, Kubernetes, Terraform, custom services).

Cedar is narrower and more opinionated by design. Developed initially for Amazon Verified Permissions and AWS IAM Identity Center, Cedar is purpose-built for principal-action-resource authorization decisions — not a general query language. That narrowness is a deliberate trade for two real advantages:

  • Schema enforcement at write time. Cedar policies are checked against a typed schema when authored, catching attribute-access errors (referencing a field that doesn't exist on a given resource type) before the policy ever runs, where Rego's more dynamic approach defers those errors to evaluation time.
  • Formal verifiability. Cedar's design constraints — default-deny, an explicit forbid-always-wins-over-permit rule, order-independent evaluation, no side effects in policy logic — make policies compositionally easier to reason about, and enable SMT-solver-based formal verification: mathematically proving properties like "no combination of these policies can result in privilege escalation," rather than just testing for it empirically.

The performance profile differs too: compiled, schema-driven engines like Cedar generally evaluate faster than Rego for comparable checks, but OPA's more dynamic model is what makes its cross-stack versatility possible in the first place — the two properties trade against each other by design, not by implementation quality.

A decision framework

SignalFavors OPAFavors Cedar
Policy scopeMultiple systems (K8s, Terraform, CI/CD, apps) need one policy planeApplication-level principal-action-resource authorization specifically
Latency requirementTolerant of typical in-process Rego evaluationUltra-low-latency, in-process authorization checks
Verification needsEmpirical policy testing is sufficientNeed mathematical proof of properties like "escalation is impossible"
EcosystemAlready invested in CNCF tooling (Envoy, K8s admission control)Already on AWS with Verified Permissions, or building a bespoke authorization service from scratch
Team familiarityRego experience already in-houseComfortable adopting a newer, narrower DSL

A pattern that shows up repeatedly in production: OPA at the edge or gateway layer for broad, cross-cutting policy decisions, with Cedar (or a similar schema-driven engine) inside specific latency-sensitive services that need fast, provable authorization checks. These aren't mutually exclusive — they operate at different layers of the same system.

The automated access review trade-off

Once policy is code, the natural next step is automating access review, not just access decisions — periodically or continuously scanning granted permissions against actual usage and automatically revoking what's unused (access reclamation). This is where the real engineering trade-off lives, and it's not primarily a tooling problem:

Security vs. velocity. Tightly scoped, continuously-reclaimed permissions are strong security, but every reclamation is a bet that the permission really is unneeded — get that bet wrong and a developer's legitimate but infrequently-used access (a quarterly batch job, an incident-response runbook invoked twice a year) gets revoked, and they hit a wall exactly when they need it least: mid-incident. Overly aggressive automated reclamation converts a security tool into an availability risk.

False positives are the actual bottleneck, not the automation itself. Automated tools that flag or revoke "unused" access are only as good as their usage baseline. Poor baselining (too short a lookback window, not accounting for legitimately-infrequent access patterns, ignoring seasonal or incident-driven access spikes) produces false positives, and false positives are what erode trust in the system — once developers learn the automated reclamation tool wrongly revokes things, they start routing around it (requesting broader standing access "just in case," defeating the entire premise).

Governance overhead scales with automation, not against it. A counterintuitive finding worth internalizing: automating the decision to grant or revoke access doesn't reduce the need for review — it shifts review from "approve this specific request" to "audit whether the policy and its baseline are still correct," which is a different, ongoing governance task, not a one-time setup cost.

Failure modes and how to design against them

Policy sprawl with no ownership model. As policy-as-code adoption grows, the number of discrete policies grows with it. Without clear ownership (which team owns which policy file, who reviews changes to it), policies rot the same way undocumented infrastructure does — nobody's confident removing a rule because nobody's sure what depends on it.

Testing policies in isolation, not in combination. A single Cedar or Rego policy can pass its own unit tests while still combining with other active policies to produce an unintended permission (or an unintended denial). Policy test suites need combination-level tests — evaluate the full active policy set against representative principal-action-resource scenarios, not just each policy file alone.

Treating CI policy gates as advisory. A policy-as-code check that only warns rather than blocks a deploy or a Terraform apply will, over time, get ignored during time pressure — exactly when the discipline matters most. If a policy is important enough to write, it's usually important enough to be a hard gate, with an explicit, logged override path for genuine emergencies rather than a soft warning everyone learns to click through.

No baseline validation before automated reclamation goes live. Turning on automated access reclamation without first running it in shadow/audit mode (log what it would revoke, without revoking) skips the step that would surface baseline problems before they cause an incident. Shadow mode for at least one full business cycle (including any seasonal or quarterly-access patterns) is cheap insurance against the false-positive problem above.

Conflating authentication hardening with authorization hardening. Policy as code for IAM governs what an already-authenticated principal can do; it doesn't replace hardening how that principal authenticates in the first place. Short-lived, dynamically issued credentials and zero-trust service identity are complementary controls, not substitutes.


Sources: Policy as Code in 2026: OPA, Kyverno, Cedar and What's Next — Harness, Cedar Best Practices vs OPA Rego — CloudMatos, Policy Engine Showdown: OPA vs. OpenFGA vs. Cedar — Permit.io, Operationalizing least privilege — AWS Security Blog

Syslabs' engineering team implements policy-as-code IAM systems as part of our cybersecurity consulting work.