Enforce Organizational Policies and Security Best Practices to your Kubernetes Clusters By Using OPA Gatekeeper

developer-guy
Trendyol Tech
Published in
9 min readJan 24, 2021

--

Let’s assume that we are a small organization, and at this organization, we want to migrate our workloads onto Kubernetes, but security is our primary concern and not an afterthought. So, we have already set up our clusters by following the security best practices provided by the Kubernetes official documentation. But when our organization starts to grow, we had to make some decisions to protect our Kubernetes environment and control what end-users can do on the cluster. Firstly, we followed some built-in security features provided by Kubernetes, such as Role-based access control (RBAC), Pod Security Policies and Network Policies, Secrets Management, etc.

But at some point, we might want to do some more specific things, for example, reject pod deployment If the image is coming from the untrusted registry. So, these built-in security features are not enough for us at this point. Then, we started to think and define our organizational policies. We can ensure that everything we expected in the environment and applies some best practices that we defined.

Here is the question, we defined our policies, but how can we enforce them on Kubernetes environment easily and quickly!? 🤔

In this guide, we are going to try to answer some questions around the
following agenda.

Agenda

What is the OPA Gatekeeper? 🐣

OPA Gatekeeper is the policy controller for Kubernetes. More technically, it is a customizable Kubernetes Admission Webhook that helps enforce policies and strengthen governance. You might notice that we are using an “OPA” word in front of the Gatekeeper because the Gatekeeper project is served under the Open Policy Agent organization in Github.

Let’s clarify OPA first. OPA stands for “Open Policy Agent,” so what is Open Policy Agent then? OPA is a general-purpose policy engine. It has several use cases like API Authorization, SSH, Docker, and more. OPA uses Rego as a domain-specific language. Policies that OPA uses to review resources are written in Rego and usually saved as *.rego files.

The important thing that we notice is the use of OPA is not tied to Kubernetes alone. Gatekeeper, on the other hand, is specifically built for Kubernetes Admission Control use case of OPA.

If you want to look at more detail of OPA, you can take a look at my previous post “First look to OPA(Open Policy Agent)”.

https://kubernetes.io/blog/2019/08/06/opa-gatekeeper-policy-and-governance-for-kubernetes/

What kind of problems does it try to solve? 📚

This project's main goal is to help organizations apply policies and security best practices to the Kubernetes environments quickly and more straightforward because it is doing that in a Kubernetes Native way.

Before going furthermore, first, we need to understand what is the mean of policy for organizations.

In simplest terms, policies define what end-users can do on the cluster and possible ways to ensure that clusters are in compliance with organization policies.

Policies could be of type Governance, for example, to meet some of the organizational conventions or it could be to meet legal requirements or to enforce best practices.

For example, we can define some policies like the following for our environment:

  • All images must be from approved repositories
  • All pods must-have resource limits
  • None of the pod must run as root
  • None of the pod must have a privileged container

Using Gatekeeper, we will be able to enforce these policies that consist of best practices and security measures very quickly on our environment without any development effort with the help of Custom Resource Definitions, which we’ll describe later and Rego.

If you are curious about what is the difference between OPA and Gatekeeper project, you can follow the link.

How does it solve these kinds of problems? 🧬

Let’s look at the DNA of the Gatekeeper.

There is a concept in Kubernetes called “Dynamic Admission Controllers,” which are the webhooks (HTTP Callbacks) to intercept requests before they are persisted to the etcd. Gatekeeper functions as a “Validating Admission Webhook” on top of an OPA engine. Gatekeeper uses the OPA Constraint Framework to describe and enforce the policy. Once we configure OPA policies dynamically using Gatekeeper’s Custom Resource Definitions (CRDs), Gatekeeper will use the policies to reject or accept requests.

https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/

In Gatekeeper, we define our policies as Constraints. Constrains are written in Rego, but before we can define our Constraint, we need something called “ConstraintTemplate” that allows people to declare new Constraints because each template describes both the Rego logic enforces the Constraint and the schema for the Constraint.

Basically, we can think of this Constraint as our CRD that is going to be created by the ConstraintTemplate. So, we should say that Gatekeeper will create a new CRD’s to describe each policy that we defined.

We can think of ConstraintTemplate as a function itself and the Constraint as a function call.

Hands-on 🚀

Before moving on to the demo, you might think of where to start first, what we should learn to work with Gatekeeper because we said we would use Rego to author our policies. Then we also said we are going to use Rego policies within the ConstraintTemplate to create our Constraints. 🤯

Rego is very simple and very well documented, we should learn a little bit about Rego first to author our policies, but I promise this process will be straightforward and quick. Here is the documentation for Rego. We need to learn how to use these Rego policies within the ConstraintTemplate to create our Constraints, which is very simple. Then, we are ready to go now. 👏

Let’s look at the basic ConstraintTemplate that we can define.

k8srequiredlabels-constrainttemplate.yaml

You’ll notice that we are using our Rego policies within the “.targets” section of the ConstraintTemplate. A quick reminder here, this is the first thing that we need to do to prepare the schema for the Constraint itself. You’ll also notice that the resource kind is “ConstraintTemplate,” this CRD is part of the Gatekeeper installation. But where is the Constraint? If you look at the “.spec.crd.spec.names.kind” field of the ConstraintTemplate, you will see “K8SRequiredLabels,” which is our Constraint. So, there is no CRD called Constraint like ConstraintTemplate. Constraint itself is a CRD that is going to be created by the ConstraintTemplate, in this case, “K8SRequiredLabels”. You’ll also notice that we are waiting for some inputs for our Constraint because we should specify some required labels that we want to enforce and we’ll use these inputs in our Rego policy as “input.parameters”.

Let’s dive into the demo. In this demo, we are going to install Gatekeeper to our local minikube cluster using Helm. Then we are going to demonstrate how we can prevent our cluster from privileged containers. You’ll also see a little trick. We are going to use “Docker Context” to be able to reach the docker daemon, which is running on Minikube VM, instead of just using the
“eval $(minikube docker-env)” command. You can take a look at what the docker context actually is in more detail in this documentation.

Let’s start our local Kubernetes cluster using minikube.

minikube-start.png

Configure docker context to use docker daemon, which is running on Minikube VM.

docker-context.png

There are many ways to install OPA Gatekeeper, Helm is one of them, and we prefer to use Helm to install it in this demo. You can see the full list of available installation methods in the documentation.

helm-gatekeeper.png

Please note that this chart is compatible with Helm v3 starting with Gatekeeper v3.1.1. When using Helm v3, it is expected to see warnings regarding to crd-install hook. This is due to maintaining backwards compatibility with Helm v2 and should not impact the chart deployment.
https://github.com/open-policy-agent/gatekeeper#deploying-via-helm

Let’s look at what CRD’s are created for us with the installation of the Gatekeeper. You’ll notice that there is no CRD called “Constraint,” but there is a CRD called “ConstraintTemplate.”

Let’s define our first ConstraintTemplate to prevent the cluster from privileged containers.

privileged-constrainttemplate.yaml

Here, as you can see, we will define the “PriviligedContainer” Constraint. This constraint will use a Rego policy defined in the “.targets” section within the ConstraintTemplate body. After you apply this YAML manifest, you will notice that a new CRD called “PrivilegedContainer” is created.

privileged-container-crd.png

The most important question here is, how can we define the “PriviligedContainer” Constraint in the cluster. Let’s look at it then. The important thing that we need to note here is that there is no prevention until you apply the constraint to the cluster. You are going to start to prevent your cluster from privileged containers.

priviliged-container-constraint.yaml

You defined that you want to intercept the Pod requests and apply the policy on top of them with this Constraint. Let’s apply this and then test it.

apply-privileged-constraint.png

Let’s test it. First, we will create a normal Pod, and we expect this will work. Then, we apply a Pod that contains a privileged container, and we expect it will fail.

apply-privileged-pod.png

Tadaaa, it worked 🎊🎉. We prevent our cluster from privileged containers just applying YAML manifests. Also, I should say you don’t need to write your policies at the beginning. An official library available by the same organization consists of many policies that might cover your needs. Here is the link that you can look at.

Conclusion 📃

OPA Gatekeeper is a powerful engine to describe and define our policies to the Kubernetes clusters very quickly and easily. It is worth learning such a promising technology. Also, we don’t cover all the features that OPA Gatekeeper has in this demo. You will see if you look at it in more detail to the OPA Gatekeeper, there is a lot of excellent and useful features that you might interest in.

BONUS: There is also another project available called “Kyverno.” It has similar things that OPA Gatekeeper provides, but Kyverno can mutate or generate resources. It is not using a Rego to author policies either.

References 🙉

--

--

developer-guy
Trendyol Tech

🇹🇷KCD Turkey Organizer🎖Best Sigstore Evangelist🐦SSCS Twitter Community Admin✍️@chainguard_dev Fan📦Container Addict📅Organizer at @cloudnativetr•@devopstr