Introduction to Open Policy Agent (OPA)

by Bill Doerrfeld

Recent decades have seen organizations adopt various types of software applications along the road to digitalization. Some of these applications face end users and others are used by internal operators. And, more than likely, each software component was acquired at various times using different frameworks and languages.

Disparate systems also require a unique set of privileges, and each piece of software may be implementing authorization in its own way. This fragmented state becomes difficult to scale and maintain. Ideally, common policies should follow the user journey, from the app code to the underlying libraries down to the OS and connecting services. Yet, every language has its own semantics, meaning it’s challenging to apply authorization across every component and encourage interoperability between components.

Enter Open Policy Agent (OPA). OPA is a relatively new standard method for applying policies universally. Adopting such a common layer could help unite the authorization model across a fragmented cloud-native ecosystem.

I recently met with Tim Hinrichs, CTO of Styra, to explore OPA, its purpose and ways to deploy it in cloud-native architecture. Below, we’ll introduce OPA and see what it’s trying to solve. According to Hinrichs, the ultimate benefit of adopting OPA is making policy unification simple for developers to implement across the board. “People like using OPA because it gives them a single tool to put guardrails on their platform,” he says.

What is Open Policy Agent (OPA)?

OPA’s goal is to provide an open source unified solution for authorization and policies across the cloud-native stack. It provides one common language for expressing authorization policies and defines a file format for real-world rules and regulations in a form that machines can understand.

Techstrong Con 2024

Cloud Native Now 2024

Cloud Native Now 2024

AWS

OPA decouples the application or service, the policy decision-making and the policies themselves. This decoupled nature makes it portable across nearly any environment. In this architecture, you write the model in Rego, define role mappings in JSON and denote user privileges in JSON, as well. You make calls to OPA using JSON inputs and the output responds with a Boolean result of either false or true .

The easiest way to wrap your head around OPA is to experiment with different policy creation using the Rego Playground. A straightforward example is the role-based access control (RBAC) scenario for a pet store API.

< "user": "bob", "action": "update", "object": "id123", "type": "dog" > 
< "allow": true, "user_is_granted": [ < "action": "read", "type": "cat" >, < "action": "read", "type": "dog" >, < "action": "read", "type": "finance" >, < "action": "update", "type": "cat" >, < "action": "update", "type": "dog" >, < "action": "update", "type": "finance" > ] > 

The actual policies are written in Rego, a language that fits cloud-native policy design quite well. It’s a purpose-built policy language using conditional statements and which supports JSON. This makes it easy for policy authors to write and maintain policies, says Hinrichs. For example, this policy prevents Kubernetes pods from using containers from untrusted image registries:

deny[msg] < some i input.request.kind.kind == "Pod" image := input.request.object.spec.containers[i].image not startswith(image, "hooli.com/") msg := sprintf("Image '%v' comes from untrusted registry", [image]) > 

OPA is more than just the policies themselves; it also provides a policy engine, which acts as a proxy to help make authorization decisions given different input. OPA also consists of tooling around the format to unit test policies and plugins to write policies in all major IDEs.

Common Types of Policies and Deployment

So, what are some specific use cases for OPA? Hinrichs shares some other examples of common policies:

In terms of deployment architecture, OPA is designed to host a local cache for policy data, Hinrichs explains. But it’s pretty flexible in terms of how you run the policy engine, he says. For example, Netflix, Atlassian and Yelp all run OPA as a sidecar or daemon next to each microservice to decouple authorization. Similarly, service mesh is another popular use case for OPA. “It’s more expressive than what service mesh naturally supports,” Hinrichs says. In service mesh, OPA can be run next to the Envoy proxy as an external authorization filter.

You could also configure OPA to run independently on every microservice, requiring no network hop-in to make authorization decisions; for instance, you may be running OPA as a little service on Kubernetes. “The trend through cloud-native is a movement toward external authorization hooks,” Hinrichs says. “K8s is a great example of much more modular developments.” To enable this, OPA provides hooks to download policies and external data periodically. However, retaining control over the various services using OPA, as well as ensuring availability and performance results across the stack, may require a centralized control plane, Hinrichs says.

OPA

Benefits and Caveats

OPA brings many benefits. Namely, it brings a unified authorization method for many use cases, from Kubernetes to Terraform and CI/CD pipelines. It’s expressive enough to dig into minute details but an easy framework to onboard new engineers. “OPA goes hand-in-hand with the DevOps cloud-native approach to software involving rapid development,” Hinrichs says. “It embodies policy-as-code.” A standard authorization layer could increase developer experience for inserting security and make logging and security reviews more consistent.

However, implementing OPA doesn’t come without its caveats. Hinrichs notes three common roadblocks to a successful OPA configuration:

For example, perhaps you want to build a context-aware policy that provides access to production Kubernetes clusters only to engineers currently on-call. If this data is stored in PagerDuty, for example, it will require integration, and there are several different ways to inject external data into OPA. While OPA provides mechanisms to inject data from any HTTP source, it’s important not to get carried away. It’s best to keep the OPA project very small to avoid bloat, Hinrichs stresses, especially if it’s being replicated across each microservice.

Future of OPA

OPA is just one tactic in the broader identity space, which Hinrichs generally describes as encompassing authentication, authorization and audit. In terms of future evolution, OPA maintainers appear to be listening to the developer community’s needs to inspire new development. As such, new language features will be designed to aid policy creation as well as debugging. For example, project maintainers aim to provide simple printOut statements to assist the debugging process.

While a policy marketplace does not exist at this time, Hinrichs foresees that more open shared policy libraries, as well as standards for sharing policies, could emerge. “We would love to see more of that,” he says. “We finally have that ability to build out those common libraries with OPA.”

Other experts in the containers and distributed systems space foresee 2022 as being a big year for OPA. “I predict OPA will have a breakout year in the enterprise as it will be leveraged for more and more use cases,” says Reza Shafii, VP of product, Kong. “We’ll also start to see new technology solutions come to market that natively integrate with OPA.”