
Ryan Aebi
Senior Consultant
Auhtor: Ryan Aebi
In modern microservice and zero-trust architectures, access decisions are made on the go on each component independently. This presents a very significant challenge:
The Open Policy Agent (OPA) serves as a policy engine for this purpose:
Several (logical) components are involved in an authorization decision for an API call.These components can be roughly described by the following diagram and text:
New trends deal with Zero-Trust [2], there is no central security anymore which controls everything.
The goal here is to look at each API call / request separately and thus perform authorization in each component and therefore in each access.
This requires that each component implements a PEP and can independently allow or deny a corresponding API call.
The fact that each component must itself check whether an API call should be allowed or not means that each component must also be capable of making this decision.
As a micro-service developer, this means that in addition to the PEP task ("I must be able to allow or block access"), a PDP ("I must be able to decide whether access is allowed") must also be implemented. This should be done within the same microservices.
As a rule, this leads to each microservice implementing its PDP differently and, in particular, using different rules and policies as a basis for decision-making. In other words, there is no central PIP, policies are distributed everywhere and are formalized differently.
Besides a massive governance overhead to keep the situation under control, this also means that every informal policy change leads to a code change:
In the worst case it could look like shown below and this for each microservice.
In addition, there is the issue of service level/user level authorization. This is about which microservice is allowed to consume which API (what-can-do-what) and what a user is allowed to consume from a service/application (who-can-do-what). All these decisions need to be implemented per micro-service, more precisely per API.
Are you ready for this architectural decision, the additional costs as well as the resulting risk?
In many ways, it makes sense that in a zero-trust driven architecture, each component implements a PEP. Both the backend, the microservice, and even the database must be self-accountable to enforce a policy decision.
Imagine the following scenario:
The governance overhead is not in the PEP, but in the PDP, PIP and PAP. A possible solution to this is provided by the Open Policy Agent (OPA) [3].
The OPA project was launched by the Cloud Native Computing Foundation (CNCF) in April 2018 in the CNCF Sandbox and one year later in the incubation phase [11].
Finally, in February 2021, the OPA achieved 'graduated' status, a reserved term given by the CNCF to projects that have achieved a certain level of maturity in several areas [11].
The OPA allows policies to be managed as code. Thus, a Git repository (Github, Gitlab, Bitbucket, etc.) can be used to manage policies:
This means that each microservice no longer has to manage and edit its policies itself. Developers are even empowered to build their continuous deployment pipeline / rolling releases, while they can simply consume the OPA / PDP as a service to build / deploy and runtime. In this respect, the tasks of PIP (policies are managed centrally in a repo) and PAP (policies can be edited centrally in the repo) are eliminated for the microservices.
While the policies are written in Rego, the OPA handles the publication as a REST service. The OPA processes the request based on the stored Rego policy and then decides accordingly whether access should be allowed or not. The OPA thus assumes the role of the policy decision point (PDP) by providing information on whether a request is allowed. The enforcement of the policy decision (PEP) remains with the microservice.
One of the nicest features of OPA and Rego is that they are not limited to microservices. Rego can be used to model basically anything. For example, in a Kubernetes environment, it can be controlled that [6]:
Analogously, in a terraform environment, it can be enforced:
In many ways, it makes sense in modern microservice/devops architectures to implement layered security by having each component implement its own Policy Enforcement Point (PEP). The Open Policy Agent supports this by providing PDP, PIP and PAP via central policies.
Since the Open Policy Agent obtains its policies through a source code repository, there is a single source of truth. There is no delta because microservices implement their policies themselves, instead they can be viewed and edited centrally. This makes it possible to see at any time which policy was deployed/active, but also which changes were made last.
In summary, the advantages are:
The Open Policy Agent can be used wherever decisions need to be made based on a policy. The policy language Rego is universally defined and can therefore be used everywhere.
A central enabling of OPA is that policies can be managed centrally in a source code repository. In this way, policies are managed in a versionable and traceable manner. In combination with a clean deployment pipeline, it is possible to check at any time which policy was deployed to which OPA, how it looked configurationally, and thus also record policy decisions. This interplay of code-based policies and traceability through deployments is ideal for any audits.