What Is Open Policy Agent (OPA)
Access control is the bedrock of a system’s security, determining who gets to interact with what. As systems grow more complex, they require a framework that models theoretically how access works as well as a system to implement that framework.
A common permutation of this is ABAC (Attribute-Based Access Control), an access framework, and Open Policy Agent (OPA), a popular policy engine. Today, we’ll detail on how you can implement ABAC patterns with OPA to secure applications.
To begin, let’s start by defining ABAC and OPA.
Attribute-Based Access Control (ABAC) is a way of deciding who can access what in a system, but instead of relying only on fixed roles, it looks at a wide range of details (or “attributes”) to make smarter, more flexible decisions.
Think of it like a workplace badge system, but with extra intelligence. Instead of just checking whether someone has a generic “employee” badge, the system also looks at which department they’re in, what project they’re assigned to, what type of resource they’re trying to open, and even the time of day. For example, an engineer might be able to access design documents during work hours from the office network, but not from an unsecured device at midnight.
In ABAC, these attributes usually fall into three categories:
When an access request comes in, a policy engine evaluates the ABAC policies to determine an outcome based on the attributes present. This approach allows organizations to go beyond rigid, one-size-fits-all role-based rules. With ABAC, access decisions become dynamic, context-aware, and fine-grained, making it well-suited for large organizations, sensitive data, and compliance-heavy industries.
However, ABAC isn’t suitable for every circumstance. Compared to an access framework like RBAC, where explicit roles determine access, ABAC is more complex and can involve more rules when required permissions are otherwise simple. ABAC can also struggle with scalability if attributes aren’t cleanly defined; too many possible attributes leads to bloat in policies, especially if many access rules are relationship-driven in nature (e.g. an user owns an object).
Open Policy Agent (OPA) is an open-source tool that acts as a policy engine. A policy engine is a centralized hub that makes access decisions. In other words, it’s the brain that makes yes or no decisions about whether any arbitrary action is allowed. Instead of hardcoding rules into every system or service, OPA gives organizations a central way to write, manage, and enforce policies as code across all kinds of environments: microservices, Kubernetes clusters, CI/CD pipelines, and even older legacy applications.
Notably, OPA is not a purpose-built authorization tool. While OPA can definitely be used for authorization, it’s designed to be an un-opinionated policy engine first and foremost. It has the capacity to solve a majority of authorization problems, but it does require developers to build authorization constructs from scratch from its primitives.
At the core of OPA is a language called Rego, which allows teams to describe policies in a clear, declarative way. This separation of policy logic from application code makes it easier and safer to update rules without redeploying or rewriting software. For example, if compliance rules change, a team can update the OPA policy directly rather than altering dozens of apps individually.
OPA works through a simple three-step process:
This makes OPA incredibly versatile. It can handle API access control, enforce Kubernetes admission rules, validate infrastructure compliance, and provide authorization for sensitive resources.
What makes OPA especially relevant to ABAC is its ability to evaluate policies based on attributes and context. Instead of simple role checks, OPA can take into account user identity, resource details, action type, and environment conditions—making it a natural fit for ABAC-driven access control at scale. However, given OPA’s open-ended structure that isn’t specifically designed for authorization, it’s often used for more coarse-grained authorization strategies (unlike a more bespoke tool like Oso).
Attribute-Based Access Control (ABAC) is often implemented with Open Policy Agent (OPA) because OPA is configurable via Rego to create any policy paradigm, including one guided by attributes. Together, they give organizations a powerful way to manage authorization across modern, distributed systems. Here are a few key reasons explained as to why OPA is a good strategy for implementing ABAC:
ABAC allows policies to consider multiple attributes — the user, the resource, and the surrounding environment — before granting access. This makes security decisions much more dynamic than simply checking whether someone has a role.
OPA is particularly well-suited here because it was designed to work with structured data like JSON. That means it can easily evaluate complex ABAC policies that account for multiple conditions at once. For example, you might allow access only if a user is from the finance department, is logging in from a corporate device, and the request is made during business hours.
One of OPA’s core strengths is that it separates policy logic from application code, letting organizations manage policies centrally and apply them consistently across many systems. When combined with ABAC, this makes it much easier to scale access control as new users, resources, and attributes come into play — without rewriting everything from scratch.
ABAC policies can also be modular as they might be combined with each referring to discrete attributes. This fits perfectly with OPA’s design. Whether you’re working with microservices, Kubernetes, APIs, or cloud platforms, you can apply the same ABAC-driven policies everywhere.
For industries with strict regulations (think HIPAA, GDPR, or PCI DSS), ABAC makes it easy to map any arbitrary qualification (e.g. “HIPAA-certified”) to access. In other words, attributes could be form-fit around compliance requirements. OPA strengthens this by logging and explaining every access decision it makes — who accessed what, when, under what conditions, and why it was allowed or denied.
This combination ensures organizations not only enforce strong security but can also demonstrate compliance when audits come around.
This isn’t just theory — enterprises are already using OPA with ABAC in production. For example, Netflix uses OPA to manage fine-grained, context-aware access across its microservices ecosystem. This shows how the pairing implementing ABAC via OPA can handle enterprise scale while keeping policies consistent and manageable.
OPA’s integration model also makes it straightforward for developers: attributes can be pulled from authentication tokens, resource metadata, or environmental inputs, and then evaluated against ABAC policies to enforce authorization.
Most organizations start with Role-Based Access Control (RBAC) because it’s simple to understand: users are assigned roles (like “admin,” “editor,” or “viewer”), and those roles determine what they can do. RBAC is ideal for organizations with minimal permutations in access between individuals or services; for these, RBAC provides the most straightforward way to classify access. It’s predictable, easy to audit, and widely adopted.
Although RBAC poses ease with its simple approach, as organizations grow, it often runs into limits. Every new nuance in permissions tends to require a new role, leading to what’s known as “role explosion.” Suddenly, instead of a handful of clear roles, you’re managing dozens or even hundreds, each covering slightly different access needs. This creates administrative overhead and makes policy management cumbersome.
This is where ABAC shows its strength. By looking at multiple attributes — such as who the user is, what resource they're accessing, and even contextual details like time or device — ABAC makes it possible to define granular, context-aware policies without creating endless roles. For example, a policy might state that access to confidential reports is only allowed during business hours, from corporate devices, for employees in the finance department. That kind of condition is hard to capture in RBAC but natural in ABAC.
In other words, RBAC remains useful for straightforward environments, but when you add scale, complexity, or regulatory requirements, ABAC quickly becomes the more practical and future-proof choice. When enforced through OPA, ABAC policies can be managed centrally, audited effectively, and applied consistently across diverse systems.
Implementing ABAC with OPA comes down to expressing policies as code and evaluating them against attribute-rich data. OPA’s policy language, Rego, makes this possible by letting you define fine-grained rules that consider users, resources, and even environmental context.
Here are the steps to implement ABAC with OPA.
Deploy OPA as your policy decision point (PDP). In this role, OPA is responsible for evaluating access requests and returning decisions such as allow or deny. For scalability, OPA can be distributed as sidecars and agents close to your services, ensuring low-latency enforcement.
Identify the attributes that matter for your access control model. These usually include:
These attributes are supplied as structured data (commonly JSON) when sending access requests to OPA.
Policies in OPA are written in Rego, which expresses logic over the attributes you provide. For example:
package abac
default allow := false
allow if {
input.resource.price <= 1
input.action == "process"
}
allow if {
input.user.experience_years > 1
input.resource.price <= 10
input.action == "process"
}
Here, a cashier may process orders, but the conditions depend on both their experience and the price of the transaction.
Each authorization request is sent to OPA as a JSON object containing the relevant attributes. A typical request might look like this:
{
"user": {
"department": "engineering",
"experience_years": 5,
"role": "engineer"
},
"resource": {
"type": "document",
"sensitivity": "high",
"price": 5
},
"action": "process",
"context": {
"location": "England",
"time": "2025-08-22T12:00:00Z"
}
}
OPA evaluates this input against your Rego policies and responds with a decision (in this case, resolving to true
), which your application enforces. Meanwhile, imagine if the JSON object looked closer to the following:
{
"user": {
"department": "marketing",
"experience_years": 0,
"role": "marketer"
},
"resource": {
"type": "document",
"sensitivity": "high",
"price": 25
},
"action": "process",
"context": {
"location": "United States",
"time": "2025-09-22T12:00:00Z"
}
}
Then, it would resolve to false
due to mismatching price and experience years.
Logging every decision is critical for both compliance and debugging. OPA provides visibility into who accessed what, when, and why, making it easier to refine policies and satisfy audit requirements. Many teams also version-control their Rego policies and test them in CI/CD pipelines before deploying changes.
Oso is an alternative to OPA that ships with its own language Polar. Oso, like OPA, is able to work with RBAC, ABAC, ReBAC, or any permutations of these. However, Oso is strictly focused on authorization whereas OPA is a general-purpose policy engine; Oso is better suited for fine-grained authorization (including ABAC and ReBAC) than OPA; Oso simplifies authorization with Facts, a straightforward data struct for representing policies.
To learn more about the distinction between Oso and OPA, check out our side-by-side comparison by clicking here.