Policy as code (PAC) is a software development approach that treats authorization policies as code. This means that policies are written in a programming language, such as Rego or Cedar, and are stored in a version control system alongside the rest of the code.
This blog discusses the benefits of PAC and dives deeper into the difference between two popular PAC languages: Rego, the language of Open Policy Engine (OPA), a CNCF project, and Cedar - the language used by Amazon Verified Permissions (AVP), an AWS-hosted service that provides fine-grained authorization for application-level resources.
The benefits of using PAC:
Decoupling policy from code: PAC allows you to decouple policy from code, which makes it easier to manage and update policies.
Increased flexibility: PAC gives you more flexibility in how you define policies, allowing you to use a variety of programming constructs to create complex policies.
Improved performance: PAC can improve performance by offloading policy evaluation from the application to a dedicated policy engine.
What do Rego and Cedar have in common?
Both are open-source.
Both are policy as code.
Both focus on decoupling policy from code.
Both are general-purpose languages and decision engines.
Both are focused on performance and auditability.
Both support compilation to WASM.
Both enable low latency by running the policy engine at or close to the consuming service.
Both are logical-programming languages.
Both can be managed at scale with OPAL.
What are the key differences?
Area of focus: OPA is a CNCF project, and is mostly used for infrastructure-level access control (service to service, admission control in K8s). Cedar is focused on application-level authorization.
The language:
Rego is a Datalog / Prolog derivative. While also having logical programming aspects , Cedar is a functional programming language, which opts to be less generic in favor of a more domain-specific focus. Cedar is more strict and structured - with emphasis on safety by default (i.e. deny by default), and more assurances on correctness / security thanks to verification-guided development.Readability and Analyzability:
Cedar is more readable than Rego. Cedar is more strictly typed, and has more focus on readability than Rego, with basic Cedar code more likely to be legible to a layman (Thanks to its clear opinionated structure), unlike Rego code, which can be extremely complex to read. Cedar's constructs are also designed to be amenable to automated reasoning.Tools and modules:
Rego has many built-in tools that can be used to do things like parsing GraphQL, JSON Web Tokens, searching a JSON graph, and more. Currently, Cedar doesn’t include such built-in tools, aiming for more of a pure language model.Underlying frameworks:
OPA and Rego are Go-based, while Cedar is Rust based. These are not dramatic differences, but they can be relevant if you’re looking to embed or extend the languages with other Go, or Rust code.Community and ecosystem:
OPA is a CNCF project, with a large community (though not very open - due to conflicts with Styra, the company behind OPA); Cedar has a small blooming community and the backing of AWS - known for its power to create cloud-native standards single-handedly.Running and testing:
Rego can be run as part of a Go SDK, CLI, as a daemon agent with OPA, and can be found embedded as a plugin in many common tools (e.g. Gatekeeper, Conftest, Envoy, Kong), Cedar can be run as a Rust SDK, CLI, and via Cedar-agent as a standalone daemon.Managing Data:
Baseline Policy data is mapped easily in both engines as part of the code and is somewhat more structured in Cedar. Both engines also support loading dynamic data. Rego works with generic JSON documents mapped under top-level arguments `input` (for incoming requests) and `data`(in memory store). Cedar also uses JSON-like documents, which are referred to as “entity slices”, for input. These are automatically mapped into entities (i.e. principals, resources, and groups) - as such Cedar, unlike Rego, expects a specific format for the inputted JSON.
In-memory / mem-cached data in Cedar is only supported as part of the Cedar agent.
Both engines are supported by OPAL which can manage both engines with policy and data in realtime (And even run them side by side)
Cedar / Rego Pros and Cons - A quick summary
Rego
Pros:
Widely used and supported
A mature ecosystem of tools and modules
Flexible and expressive language
Cons:
Can be complex and difficult to learn
Not as readable as Cedar (especially for non-technical team members)
General:
More infrastructure and K8s oriented
Cedar
Pros:
More readable than Rego
More structured language
Backed by AWS
Cons:
Currently, not as widely used or supported as Rego
A smaller ecosystem of tools and modules
General:
More application permissions oriented
Let’s look at some code
Below is a simple RBAC+ownership (aka light ABAC) in both languages.
Rego
package play
import future.keywords.if
default allow := false
allow if permit(input.principal, input.action, input.resource)
permit("alice", "read", "document") if input.resource_owner == input.principal
Cedar
permit(
principal == User::"alice",
action == Action::"read",
resource == Document::"document"
) when {
resource.owner == principal
}
As you can see, the two policies are very similar, and both languages can be considered declarative. The main difference is that the Rego policy uses a more loose and generic syntax, while the Cedar policy uses a more strict syntax - which adds clarity for even non-technical readers (with its “permit / when, unless” structure, and keywords (e.g. principal, action, resource))
Bottomline: Which one to choose?
In summary, Rego and Cedar are powerful policy-as-code languages and engines with distinct characteristics. While they share common features, such as being open-source, decoupling policy from code, and focusing on performance and auditability, they differ in their area of focus, language design, available tools and modules, and underlying infrastructure.
Both languages have a non-trivial learning curve and complexity associated with them (but as stated Ceder does have better readability) . To simplify the initial adoption process, tools like Permit.io can be useful. Permit.io offers a low-code UI solution to generate Rego or Cedar code, enabling developers (and nontechnical stakeholders) to get started more quickly and overcome the initial challenges of these languages.
Ultimately, the choice between Rego and Cedar depends on the specific use case and requirements, while using code generation tools can enable faster adoption and easier flexibility in switching or mixing the two. So perhaps you don’t have to choose.
Further learning:
Written by
Or Weis
Co-Founder / CEO at Permit.io