OPA, Cedar, OpenFGA: Why are Policy Languages Trending Right Now?

- Share:





2938 Members
You might have noticed a rising trend lately - Policy languages like OPA, Cedar, and OpenFGA are being increasingly used in Identity and Access Management (IAM) to manage complex authorization requirements. Join us as we explore the challenges faced in authorization, the solutions provided by policy languages, and the benefits of using them.
Domain-specific declarative languages have been a huge part of software development since its early days. They were created to tackle the complexities and requirements general-purpose programming languages struggled to manage and are now a part of every developer's toolkit.
In Identity and Access Management (IAM), authorization is becoming increasingly challenging in recent years - apps are getting more complex, as are user requirements. The result? a huge surge in domain-specific declarative languages focused on authorization. Older languages, such as Open Policy Agent’s Rego, are getting a facelift with their upcoming V1, and new languages and platforms like OpenFGA and, more recently, AWS’ Cedar, are being created.
It’s quite clear that significant steps are being made to tackle authorization’s ever-growing complexity. In this blog, we’ll talk about why these policy languages are rising in popularity, and how you can use them to your advantage to build better, more secure applications.
There’s a new problem in the software development world: the problem of decisions. Decisions are obviously not a new issue - it’s one of the most basic aspects of software development, and simple ‘if’ statements are at the very foundation of any programming language out there. But in the vast majority of cases, that’s not enough.

Many modern applications require extremely fine-grained decisions to be made, especially regarding security matters in authorization (handling what a user or service can or cannot do in your application). Let’s briefly go over these challenges:
Working as a developer back in 2010, you could easily imagine having one server, one programming language, one database, and one application. Today, even the most basic apps start tons of services from the get-go, yet we still don’t want users to access data that they're not supposed to. This means all of these services need to have one concrete source of truth for their decision-making, and these decisions have to be streamlined across the entire stack.
In LAMP or older architectures, we used to have one SQL database. Even the simplest apps today use multiple data sources, which are only growing more complex by the minute. All of this data still needs to adhere to the same level of security when in comes to making decisions. That means the way of making these decisions is also growing increasingly complex.
The more data we have, the more decisions we need to make, and the more data needs to be included in that decision-making process. At some point, it gets too complex, and we can’t keep supporting more and more granularity.
We’re delivering more software. That means more endpoints and more production environments that just keep growing. This creates the need for a layer we can trust to always make the right decision when it comes to access.
Users of modern-day applications are significantly more security aware. They want to own their data and manage its privacy, and you need to support that. That means supporting very fine-grained ownership, temporary data access functions, location-based access policies; you name it. On the other hand, app users are not really users in the classic sense anymore. Think DevOps, RevOps, and AppSec - they all want access to the code, and they affect the way that software should be delivered. Above all else, they affect how access decisions should be made.
And all of that complexity doesn't include the newest player on the block - AI Agents and LLMs. These create a problem of unstructured decisions, as they want unstructured access to our data - how do we provide them with the right access
This long list of challenges requires more complex solutions than what can be achieved with ‘if’ statements hard coded into your application. That’s where policy engines and policy languages come in.
Now that wev’e gained a better understanding of the problem, - let’s talk solutions.
The first step to solving this challenge is understanding where all these complex decisions should be made. This can be achieved by mapping out our application into a few authorization layers:

With a clear structure of where authorization decisions should be made, it’s easier for us to design a solution that can actually handle them. To do that, we can use two important architectural principles:
This plane needs to be decentralized for several reasons: First, it has to react super fast, and second, we want every part of our stack to be able to communicate with this plane directly and enforce permissions based on these decisions.
Now that we've identified the need for using a decentralized authorization engine let’s dive deeper into the language these engines utilize to process and handle authorization queries - Policy Languages.
A policy language is a formal and structured way of defining rules, conditions, and logic for specifying policies. It provides a standardized syntax and semantics for expressing authorization rules and access control requirements, making it easier to manage and enforce security policies. There are many different policy languages, such as OPA’s Rego, AWS’ Cedar, OSO’s Polar, and more.
The benefits of using Domain-Specific Declarative languages can help us overcome these challenges thanks to the benefits of having policy as code -
Not only that - defining policies using code provides you with the ability to ensure policies are consistently enforced across different systems and environments, which can help prevent policy violations and reduce the risk of unauthorized access. It allows you to easily manage and update policies, as you do that with the same tools and processes used to manage and deploy software. This makes it easier to track changes to policies over time, roll back changes if necessary, and in general, enjoy the well-thought-through best practices of the code world (e.g., GitOps).
There are many policy languages available to choose from, each more fit to handle different scenarios:

allow {
input.user.role == "viewer"
validate_department(input.user, input.document)
validate_classification(input.user.role, input.document.classification)
validate_dynamic_rules(input.user, input.document)
}
validate_department(user, document) {
user.department == document.department
}
validate_classification(user_role, doc_classification) {
role_permissions[user_role][_] == doc_classification
}
validate_dynamic_rules(user, document) {
dynamic_rules[_](user, document)
}
OPA started out as a multi-purpose policy engine, and that’s where its power comes from. It’s an extremely flexible language that can help you model any type of decision you want. The thing is, Rego can get quite complicated - it's not the perfect example of a declarative language being simple and intuitive, but it does provide you with the ability to handle extremely complex decisions on any layer.

If you have the ability to learn this new language, and you want to have one agent with one policy language across the stack, Open Policy Agent is a great choice.
Read more about it here: RBAC with Open Policy Agent (OPA)
permit (
principal == PhotoApp::User::"stacey",
action == PhotoApp::Action::"viewPhoto",
resource
)
when { resource in PhotoApp::Account::"stacey" };
Launched by AWS just one year ago, Cedar’s started as a language dedicated language for application-level authorization. Unlike AWS IAM, it's a language that can be used in any application. Cedar uses the Dafny language to provide scientific proof of correctness and performance, yet it is still challenging to use it when dealing with unstructured data, and it lacks ReBAC support. It’s a great option to use for fast ABAC based decisions, with auditing, static analysis, and partial evaluation supported out of the box.
Read more about it here: RBAC With AWS’ Cedar
Not a policy language per-se, but more of an authorization platform based on Google’s Zanzibar white paper, OpenFGA is a great choice when it comes to handling ReBAC. Backed and maintained by Auth0 and used by them for authorization, with a graph-based engine built-in, it is the perfect solution for large-scale authorization implementations. OpenFGA is less suitable when it comes to RBAC and ABAC.
You can learn more about how it compares with Cedar here: OpenFGA
A broader overview and comparison of all three languages can be found here: How Open Policy Agent compares to AWS Cedar and Google Zanzibar
While policy languages and engines provide us with a great basis for creating a separate microservice for authorization, both OPA and Cedar lack several key abilities. Let’s look at an example -
Say our policy requires a user to be a subscriber to see parts of our site. To make a policy decision, we need to know the user’s subscription status from our billing service (e.g. PayPal or Stripe) and be immediately aware of any changes to it: a new subscriber expects immediate access to our site, and a churned user should lose access on the spot.
That means our policy engine needs to be updated in real time, from outside data sources, while all of our decentralized policy engines are in sync with each other.
Open Policy Administration Layer (OPAL) is an OSS project created to aid with Policy Engine management, which keeps them updated in real-time with data and policy updates. Supporting both OPA and AWS’ Cedar, OPAL offers two important features:\
Using these capabilities allows you to take advantage of the full benefits of policy languages by keeping your policy engines up to date with all the relevant policies and data in real time.
Please consider supporting this open-source project by giving OPAL a star on GitHub.
Domain-specific declarative languages are proving to be crucial tools in managing complex tasks in software development. They help us build systems that are high-performing, secure, and user-friendly. Whether it's managing fine-grained access controls or adapting to the demands of AI agents, these languages are keeping us ahead of the curve.
Authorization is a critical component of any modern application, and we can see the tremendous benefit brought to this space with domain-specific declarative languages. Open Policy Agent (OPA), AWS' Cedar, and OpenFGA allow us to tackle the challenges that come with the modern state of IAM, while OPAL (Open Policy Administration Layer) enhances their functionality by automating the synchronization between the policy store and the real-time data required for decision-making, ensuring that policies are consistently applied with the latest relevant data. This integration enables us to create secure, reliable, and dynamic authorization systems that can adapt to changing conditions and requirements.

Application authorization enthusiast with years of experience as a customer engineer, technical writing, and open-source community advocacy. Comunity Manager, Dev. Convention Extrovert and Meme Enthusiast.