DEV Community

Gabriel L. Manor for Permit.io

Posted on • Originally published at permit.io on

Everything You Need to Know About the Difference Between OPA's Rego and AWS Cedar

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), a service that provides fine-grained authorization for AWS 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 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 a logical programming language, Cedar opts to be less generic in favor of a more domain-specific focus.

  • Readability:

    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.

  • 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, and natively support compilation to Web assembly, 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

Enter fullscreen mode Exit fullscreen mode

Cedar

permit(
  principal == User::"alice", 
  action    == Action::"read", 
  resource  == Document::"document"
) when {
  resource.owner == principal
}
Enter fullscreen mode Exit fullscreen mode

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 steep learning curve and complexity associated with them. 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.

Top comments (2)

Collapse
 
deanla profile image
Dean Langsam

Great post, Gabriel. I am curious about how the approach of policy as code and the languages you described (Rego and Cedar) handle error handling and testing. Specifically, how do developers get feedback about policy violations or errors? Are there built-in mechanisms for testing the policy code in both of these languages?

Collapse
 
gemanor profile image
Gabriel L. Manor

Thanks for the question, Dean.
Handling errors in Policy as Code happened in two phases, validation and audit.
For validation of your policy, both OPA and Cedar provide tools for linting and validation. There's +1 for Cedar, as they allow you to validate your data entities with the policy code you've created.
For auditing, both OPA and Cedar have nice audit logs out of the box that could help you audit. For more advanced auditing, handling, and just-in-time updates, you could use OPAL github.com/permitio/opal. If you are looking for even better error handling then you can use Permit.io which provides rich error-handling interfaces and alerting mechanism, you can read more on Permit.io's audit logs approach here permit.io/blog/audit-logs