Exploring How Policy-as-Code and OPA Fit into the K8s World
![](https://cdn.prod.website-files.com/66180915331413723d2ca037/6655b1b97c1f9a50596a52dd_Policy-as-Code-Banner-Alberto-01.png)
In this blog post, we’ll explore how to tackle these challenges using OPA and its integration with Kubernetes.
What Is Policy-as-Code?
Policy-as-Code (PaC) is similar to Infrastructure as Code (IaC). But, whereas in IaC you need to codify your infrastructure, in PaC, the main idea is to enforce standards and rules for specific clusters or across the entire organisation.
These rules, or policies, result from technical or legal requirements, as well as architectural decisions, and are created by various stakeholders like security engineers, product owners, developers, etc. A well-automated policy reduces the maintenance cost and attack surface. It also prevents any bad setup and configuration from being pushed to the production environment.
Once we have a policy in place, the next challenge is how to enforce it, and this is where Open Policy Agent (OPA) comes into play.
What Is Open Policy Agent (OPA)?
Open Policy Agent (OPA) is a generic policy engine used to enforce policies on various types of software systems (microservices, CI/CD pipelines, Kubernetes, etc.) and which decouples policy decision-making from the business logic. In simple terms, if you want to offload the policy decision from your service, then you can implement OPA. OPA supports Policy-as-Code using the declarative Rego language.
To understand how this whole process works, let’s see how OPA handles a request.
- The request comes to your service, which then needs to decide whether to allow or deny the request.
- OPA processes this request and executes the policy (written in Rego).
- OPA validates the query attributes against the policy data.
- OPA executes the rego code for the specific data inputted and returns the result in the form of allowing or denying.
![](https://cdn.prod.website-files.com/66180915331413723d2ca037/664487cddcea392fcdb2797a_Screenshot-2021-09-24-at-13.04.04.png)
Figure 1: OPA architecture (Source: Open Policy Agent)
PaC’s Main Advantages and Uses
Using Policy-as-Code has some significant advantages:
- You can version-control the code and keep track of all the changes.
- Since the code is in version control, you can easily review and share it with a team member.
- The policy is expressed in a single unified language rather than having a separate business logic for each application.
- You can update policy code separately and dynamically without making any change in the business logic.
Organisations can use policies to:
- Enforce deployment to have a minimum X replica count.
- Determine which user can perform which operation on specific resources.
- Label a namespace when needed.
- Allow traffic only from particular subnets.
- Allow downloading of container images only from a specific registry.
Integrating OPA with Kubernetes to Address Authorisation Challenges
To integrate OPA with Kubernetes, we will use OPA Gatekeeper as an admission controller, but before that, let’s understand two types of admission controllers.
![](https://cdn.prod.website-files.com/66180915331413723d2ca037/664487cddcea392fcdb27972_image-1.png)
Figure 2: Kubernetes admission controller (Source: Kubernetes)
- MutatingAdmissionWebhook: Used to modify or reject the request if it doesn’t meet the security requirements, e.g., modifying a pod to use a specific scheduler
- ValidatingAdmissionWebhook: Used to validate the request against specific data
There are several use cases for deploying OPA as an admission controller:
- To prohibit containers from running as a root user or checking that the root file system is mounted in read-only mode
- So that only specific users can access resources in certain namespaces
- So that containers can only pull images from a particular registry
- To let you enforce OPA policies such as resource limits or labels
Open Policy Agent Gatekeeper
You can use Gatekeeper to integrate OPA into Kubernetes. Gatekeeper starts out as a Pod, and you then register it as an admission controller using an API server.
![](https://cdn.prod.website-files.com/66180915331413723d2ca037/664487cddcea392fcdb27977_Screenshot-2021-09-24-at-13.04.17.png)
Figure 3: Admission control flow (Source: Open Policy Agent)
When a user sends a request for a resource, for example, via kubectl to the API server, after authentication and authorisation, it will send it to the admission controller. The AdmissionReview is then passed to the Gatekeeper. Now, depending on the policy configured in the form of a Custom Resource Definition (CRD), Gatekeeper will decide on and send a response to the API server.
Gatekeeper has the following CRDs:
- ConstraintTemplate is used to enforce the constraint and scheme of the constraint using Rego logic.
- Constraint defines to which resources the policies should be applied.
Let’s now see an example on how to get Gatekeeper installed and enabled on a Kubernetes cluster.
Prerequisites
Before installing the OPA Gatekeeper CRD, you must have:
- A Kubernetes cluster up and running
- Kubernetes version 1.14 or later
Installing the OPA Gatekeeper CRD
To deploy the OPA Gatekeeper in your environment, run the command:
The above command will create a new namespace, gatekeeper-system:
Now, let’s verify that the Gatekeeper CRD has been successfully installed:
Next, verify it created a pod and service in the gatekeeper-system namespace:
Now that we have the Gatekeeper pod and service up and running, the next step is to define the policy.
How Do We Define Policies?
To explain how to define a policy, we will use an example policy to enforce the definition of a label team on namespace creation.First, define ConstraintTemplate and Constraint CRD by using Rego and saving it to the template.yaml file:
In the rego code above, violation [{"msg": msg, "details": {"missing_labels": missing}}]
is the message displayed to the user when the policy is violated.
provided assignment collects the labels assigned to the input object’s metadata, required assignment collects the required labels from the input and missing assignment collects the difference between the two previous assignments. If the missing assignment has any elements, then a message is created msg:= sprintf(“you must provide labels: %v”, [missing])
with the message returned to the client in the case of a violation.
Now, create the template:
Check the constraint template is created
Verify the CRD:
Now, it’s time to create the constraint that will use the above constraint template:
Note: Make sure kind matches the kind defined in the constraint template.
Next, create the constraint:
Check the constraint has been created:
Let’s verify if the policy is working as expected by creating a namespace without a team label saving it to file ns-example.yml:
Note: OPA policy will only have an impact if you try to create a new pod, it will not impact the existing pod.
If you want to look at some more policies, please check the official GitHub repo.
You can also check the Rego Playground for policy debugging. For example, in the case below, if the image is coming from an untrusted registry (other than hooli.com), it should be denied. Using Rego Playground, it’s easier to test and debug your policy online:
![](https://cdn.prod.website-files.com/66180915331413723d2ca037/664487cddcea392fcdb2798a_image-e1635950807178.png)
Figure 4: The Rego Playground (Source: Open Policy Agent)
Alternative to OPA in the Kubernetes Space
An alternative to OPA, or specifically Gatekeeper in the Kubernetes space is Kyverno which is written specifically for Kubernetes, whereas you can use Gatekeeper with other services like Linux PAM, Envoy Proxy, etc.
As we’ve seen in the example above, Gatekeeper requires the user to make use of Rego programming language for the policies definition which could become cumbersome to manage Kubernetes policies. As a tradeoff, a dedicated programming language, enables very powerful policies definitions.
Kyverno is seen as a direct reaction to these technical demands and, because it was built specifically for Kubernetes and expresses policies declaratively, its mental model is identical to the way Kubernetes objects are described and reconciled which makes policies definition easier.
Conclusion
Using OPA, you can offload the policy decision from your service. And with OPA Gatekeeper, you can define policies to your Kubernetes cluster easily and quickly. For implementing policies in OPA, you need to learn a new language, Rego. Other open-source projects, like Kyverno, don't use Rego and work similarly to OPA Gatekeeper. Overall, they both are promising technologies, and it's worth learning both and make the most informed decision given the use cases.
This blog is written exclusively by the OpenCredo team. We do not accept external contributions.
Related articles
Stay up to date with our latest blogs posts.
Looking for a hands-on software delivery partner?
Book in a quick 20 minute chat with our consultants to explore your specific project and objectives.
![OpenCredo-Graphic Illustration: Brainstorm](https://cdn.prod.website-files.com/65f178221acfb3ab01f09d6a/662a7985f55d5237a3bfa26d_OpenCredo_Brand_Assets_Illustrations_Graphics%202.png)
![OpenCredo-Graphic Illustration: RocketShip](https://cdn.prod.website-files.com/65f178221acfb3ab01f09d6a/662a79ed591e0633a7a17c1e_Rocket.png)