---
title: Enforcing Policies with Gatekeeper in Kubernetes
description: How to use Gatekeeper to protect the control plane resources, prevent permission escalation problems on pods and enforce policies
image: https://blog.container-solutions.com/hubfs/blog%20hero%20images/Enforcing%20policies%20with%20Gatekeeper%20social-100-2.jpg
---

Check out our **[Cloud Native Services](https://www.container-solutions.com/services) **and** **book a call with one of our experts today! 

[![Container Solutions](https://blog.container-solutions.com/hubfs/CS_blog/logo-main.svg "Container Solutions")](http://container-solutions.com)

- share:
- [**](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fblog.container-solutions.com%2Fenforcing-policies-with-gatekeeper-in-kubernetes)
- [**](https://www.twitter.com/share?url=https%3A%2F%2Fblog.container-solutions.com%2Fenforcing-policies-with-gatekeeper-in-kubernetes)
- [**](http://www.linkedin.com/shareArticle?mini=true&url=https://blog.container-solutions.com/enforcing-policies-with-gatekeeper-in-kubernetes)
- [**](https://blog.container-solutions.com/enforcing-policies-with-gatekeeper-in-kubernetes#)

[![](https://blog.container-solutions.com/hubfs/blog%20hero%20images/Enforcing%20policies%20with%20Gatekeeper%20hero-100.jpg) ](https://blog.container-solutions.com/enforcing-policies-with-gatekeeper-in-kubernetes)

[Kubernetes](https://blog.container-solutions.com/tag/kubernetes), [WTF Is Cloud Native](https://blog.container-solutions.com/tag/wtf-is-cloud-native)

# Enforcing Policies with Gatekeeper in Kubernetes

[Cameron Wood, Elieser Pereira, Rodrigo Martinez](https://blog.container-solutions.com/author/cameron-wood-elieser-pereira-rodrigo-martinez)

 June 30, 2022

 14 minutes Read

When managing Kubernetes clusters, cluster administrators need to ensure the overall stability of the system. To accomplish this it is necessary to avoid disruptions to the control plane, and also avoid any risks of users being able to escalate their privileges thus causing further problems. With this in mind, protecting the `kube-system` namespace and enforcing pod security policies to run payloads with just the necessary access is a must.

To accomplish our objective we took a look at the Kubernetes native way to do it, but found that RBAC is not enough to cover some use cases. Ultimately we decided to use Gatekeeper because it allows us to add “deny” rules for authorisation and also allows us to enforce pod security policies for payloads in the cluster. Gatekeeper really shines for enforcing best practices, making it a natural fit for what we wanted to achieve.

This post explains the arguments that make Gatekeeper a good option to work alongside RBAC to improve the Kubernetes authorisation process using validating webhooks. We also show a couple of examples on how to protect the `kube-system` namespace and how to enforce some pod security policies.

## The problem

When providing Kubernetes clusters, it is important to ensure stability. Often you want to grant users enough permissions to have freedom, but you also want to protect clusters from unexpected changes and outages. To achieve that, unnecessary interactions with the `kube-system` namespace should be blocked in order to protect that namespace from both user error and malicious actors.

It is also necessary to enforce pod security policies for payloads in the cluster.

Kubernetes provides tools like RBAC to handle access to clusters through Roles and ClusterRoles. The problem with that approach is that RBAC is purely additive, so cluster administrators need to define a detailed list of permissions an end-user can access. In this case, we want to provide access to the whole cluster except for the `kube-system`—this wouldn’t be possible using RBAC because it doesn’t have a “deny” option.

Kubernetes used to provide Pod Security Policies to help enforce security best practices for pods in the cluster, but these are deprecated in v1.21. Fortunately we have [Open Policy Agent](https://www.openpolicyagent.org) (OPA), an open source general purpose policy engine with a Kubernetes specific implementation called Gatekeeper. This works as a perfect replacement for Pod Security Policies.

[Gatekeeper provides a library](https://github.com/open-policy-agent/gatekeeper-library) with common policies. The library helped us to avoid reinventing the wheel constantly, but if you have very specific requirements it is also possible to create custom policies.

To solve the access limitations inherent in RBAC, OPA/Gatekeeper is a good option. It can enforce different types of access in a more configurable way, and allows the enforcing of multiple types of pod security policies to prevent permission escalation problems.

### Authentication and authorisation

Whilst it is an important part of cluster administration, authentication is outside of the scope of this post. We assume that every request is authenticated from now on.

Providing access to users for different resources in the cluster is one of the main concerns for cluster administrators. In this case, users should have full access to the cluster and just be excluded from using the `kube-system` namespace. This is usually a complex task in practice because cluster administrators need to keep track of permissions for each user or group of users.

Using RBAC, users can be provided with `cluster-admin` access which gives them enough flexibility to use the cluster. The problem is that this provides access to the `kube-system` namespace meaning they could break the cluster.

### Protect the control plane

To avoid unnecessary disruptions in the control plane, access to the `kube-system` namespace should be blocked. Only users that are part of the `system:*` group or any user that is used by a cloud provider to manage control plane resources, should have access to the `kube-system` namespace and its resources.

Restricting access to the `kube-system` namespace is a delicate task because inadvertently blocking users that manage the control plane could cause unexpected failures in the cluster. If for some reason any of the control plane controllers stop having access to that namespace it would end up breaking the cluster, instead of protecting it.

Cluster users should be allowed to deploy anything on the Kubernetes cluster, but cluster administrators need to ensure they follow good practices by enforcing policies.

## The solution — Validating Admission Webhooks

Admission Controllers seem like a natural way of solving all the problems mentioned before because authentication and authorisation are already handled when the request reaches the Admission Webhook. When looking for a compatible implementation, the tool that stands out is again Gatekeeper.

Validating Admission webhooks are part of the Admission Controllers implemented in Kubernetes. These are responsible for intercepting requests to the `kube-api` and can allow or deny access to the request based on its content.

To have a working [Validating Admission Webhook](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#validatingadmissionwebhook) it is necessary to also have an [Admission webhook server](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#write-an-admission-webhook-server). In this case, the server is Gatekeeper, and Kubernetes is informed of it through the use of a `ValidatingWebhookConfiguration` object, which is created when [installing Gatekeeper](https://open-policy-agent.github.io/gatekeeper/website/docs/install/#installation).

The `ValidatingWebhookConfiguration` object has a field called `rules`, which is used to define which requests should be validated with the webhook. These rules can match apiGroups, apiVersions, resources, or operations. Read more about [ValidatingWebhookConfiguration](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#webhook-configuration) to understand how to customise its behaviour.

To make sense of how Validating Webhooks interacts with OPA take a look at the architecture presented [in this blog post](https://itnext.io/kubernetes-authorization-via-open-policy-agent-a9455d9d5ceb).

One thing to notice is that the request goes through the Validating Webhook only if it’s authenticated and the request was previously authorised by RBAC.

 

![Enforcing policies with Gatekeeper diagram 1-100](https://blog.container-solutions.com/hs-fs/hubfs/WTF%20blog%20diagrams/Enforcing%20policies%20with%20Gatekeeper%20diagram%201-100.jpg?width=1851&name=Enforcing%20policies%20with%20Gatekeeper%20diagram%201-100.jpg)

### Open Policy Agent

Open Policy Agent (OPA) is an open-source, platform-agnostic, policy engine that enables users to create policies as code using [OPA’s policy language Rego](https://www.openpolicyagent.org/docs/latest/#rego). In combination with admission controllers in Kubernetes, OPA gives cluster administrators multiple configuration options to create custom policies.

Gatekeeper Iis the OPA implementation that integrates with Kubernetes. It allows users to create and enforce policies by introducing a custom resource called `ConstraintTemplate`, which allows cluster administrators to extend the Kubernetes API by creating custom resources to enforce custom policies.

### Constraint templates and Constraints

In order to enforce a new policy, it is first necessary to define it using a `ConstraintTemplate` containing the `rego` code that validates the constraint.

To enforce the policy, create a custom resource based on the `ConstraintTemplate` previously created—this is also known as a “Constraint”. The creation of the constraint informs Gatekeeper that it needs to be enforced.

In the constraint, define a `match` field, which is composed of a Kubernetes selector that helps to define elements to which a given constraint is applied, including `kinds`, `namespace`, `labelSelector`, and others.

### Considerations

While the described scenario requires enforcing multiple policies on the `kube-system` namespace, usually Gatekeeper is used for other purposes and the general recommendation is to avoid adding restrictions to the `kube-system` namespace because these can cause control plane disruptions.

As a rule of thumb always ensure that the policies enforced don’t block the deployments of critical workloads or dependencies in the clusters. Similarly, if there are third-party controllers interacting with the cluster, ensure access to the resources they need to work as expected.

### How to use Gatekeeper

Let’s go through an example of policy enforcement in Kubernetes. For this, the only requirement is a healthy Kubernetes cluster.

#### Install Gatekeeper

To deploy gatekeeper 3.4

```
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.4/deploy/gatekeeper.yaml
```

#### Create a Constraint Template with Rego

```
cat <<EOF | kubectl create -f -
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: denyrestrictednamespaceaccess
spec:
  crd:
    spec:
      names:
        kind: DenyRestrictedNamespaceAccess
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package DenyNamespace

        violation[{"msg": msg}] {
          not startswith(input.review.userInfo.username, "system:")
          msg := sprintf("you cant use namespace: %v", [input.review.object.metadata.namespace])
        }
EOF
```

This creates a Custom Resource Definition (CRD) called `DenyRestrictedNamespaceAccess` that allows us to enforce the policy. The policy says it’s a violation only if the user making the request doesn’t have the `system:` prefix.

Policies get to review an `AdmissionReview` object and return a similar object containing a field “allowed” that could be set to true or false. [Read more about admission controllers](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/).

#### Create a constraint

```
cat <<EOF | kubectl create -f -
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: DenyRestrictedNamespaceAccess
metadata:
  name: denyrestrictednamespaceaccess
spec:
  match:
    namespaces:
      - kube-system
  rules:
  - operations: ["*"]
EOF
```

The `match` field specifies that the `kube-system` namespace is the one on which to enforce this policy.

The `operations` field indicates that it enforces the policy for every operation to the namespace, i.e. CREATE, UPDATE, DELETE. Remember that this kind of webhook doesn't allow filtering of GET requests.

To check if the policy is enforced run the following command:

```
kubectl create serviceaccount testsa -n kube-system
```

Which should return:

```
[denyrestrictednamespaceaccess] you cant use namespace: kube-system
```

### Create a Pod Security Policy Constraint Template with Rego

This is an example from a [library](https://github.com/open-policy-agent/gatekeeper-library) of commonly used policies from Gatekeeper.

```
cat <<EOF | kubectl create -f -
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8spspallowprivilegeescalationcontainer
  annotations:
    description: Controls restricting escalation to root privileges.
spec:
  crd:
    spec:
      names:
        kind: K8sPSPAllowPrivilegeEscalationContainer
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8spspallowprivilegeescalationcontainer

        violation[{"msg": msg, "details": {}}] {
            c := input_containers[_]
            input_allow_privilege_escalation(c)
            msg := sprintf("Privilege escalation container is not allowed: %v", [c.name])
        }

        input_allow_privilege_escalation(c) {
            not has_field(c, "securityContext")
        }
        input_allow_privilege_escalation(c) {
            not c.securityContext.allowPrivilegeEscalation == false
        }
        input_containers[c] {
            c := input.review.object.spec.containers[_]
        }
        input_containers[c] {
            c := input.review.object.spec.initContainers[_]
        }
        # has_field returns whether an object has a field
        has_field(object, field) = true {
            object[field]
        }
EOF
```

The policy reviews containers to see if these containers don’t have a security context or if the security context is set to true.

### Create a violation pod

```
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: static-web-without-security-context-0
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
EOF
```

Before actually enforcing the policy, let’s create a pod without a security context, to illustrate how policies are applied and how audit features work.

### Create Pod Security Policy (PSP) constraint

```
cat <<EOF | kubectl create -f -
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPAllowPrivilegeEscalationContainer
metadata:
  name: psp-allow-privilege-escalation-container
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system"]
EOF
```

The constraint enforces that the policy is applied to all pods. It also excludes any pod running in the `kube-system` namespace.

### Validating the policy

```
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: Pod
metadata:
  name: static-web-without-security-context-1
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
EOF
```

Trying to create the above pod should return the following result. This pod is the same as the one already created, but this time it is blocked by the webhook:

```
[psp-allow-privilege-escalation-container] Privilege escalation container is not allowed: web
```

In order to successfully create the pod, update the manifest to add a security context to the container.

```
     securityContext:
        allowPrivilegeEscalation: false
```

### Audit

Gatekeeper allows users to see pre-existing resources that violate any existing policy. In this case, this cluster was previously running a pod without a `securityContext`, meaning any user could see the policy violation triggered before, using the following command:

```
kubectl get constraint -o json | jq '.items[].status.violations'

[
  {
    "enforcementAction": "deny",
    "kind": "Pod",
    "message": "Privilege escalation container is not allowed: web",
    "name": "static-web-without-security-context-0",
    "namespace": "default"
  },
]
```

## Conclusion

Providing a flexible, secure and highly-available Kubernetes cluster is a hard task, involving many challenges. We’ve looked at how to protect the control plane resources, and how to prevent permission escalation problems on pods.

In the process we found some of the limitations RBAC has for Kubernetes and addressed them by using Gatekeeper to add “deny” rules based on custom requirements. Please keep in mind that cluster administrators should review in detail which users should, or should not, have access to the `kube-system`.

Limiting access to the `kube-system` is a really specific requirement, and it is generally recommended to avoid adding constraints to the `kube-system` namespace. The post shows how to do this as a reference but keep in mind that this could lead to control plane disruptions. Make sure any control plane user can work as expected.

The two examples provided allow cluster administrators to deny access to a namespace and to prevent `privilege-escalation` for the containers. These examples are enough to illustrate the idea and should give cluster administrators a starting point to create custom policies.

It is important to keep in mind that when the `AdmissionReview` arrives at Gatekeeper the request has already been authenticated and authorised, so those topics are out of scope in this post.

OPA/Gatekeeper is a great option to handle multiple kinds of policies in a Kubernetes cluster. Using Constraint Templates and Constraints cluster administrators can define which resources the constraints are applied to. Official documentation about [Rego](https://www.openpolicyagent.org/docs/latest/#rego) and [Gatekeeper](https://open-policy-agent.github.io/gatekeeper/website/docs/howto/) definitely helps to better understand and create custom policies.

[![hiring.png](https://no-cache.hubspot.com/cta/default/2252258/e04cb4d2-0ea4-4180-abb3-3765a07b31c5.png)](https://cta-redirect.hubspot.com/cta/redirect/2252258/e04cb4d2-0ea4-4180-abb3-3765a07b31c5)

[### Tackling Supply-Chain Security in Regulated Industries

](https://blog.container-solutions.com/tackling-supply-chain-security-in-regulated-industries)

[![prev-arrow](https://cdn2.hubspot.net/hubfs/3842749/Wow%202019/Images/left-arrow.png) Previous article](https://blog.container-solutions.com/tackling-supply-chain-security-in-regulated-industries)

[ Next article ![next-arrow](https://cdn2.hubspot.net/hubfs/3842749/Wow%202019/Images/right-arrow.png) ](https://blog.container-solutions.com/engineer-retention)

[

### Business Value, Soccer Canteens, Engineer Retention, and the...

](https://blog.container-solutions.com/engineer-retention)

Comments

Leave your Comment

![cs-logo-white](https://blog.container-solutions.com/hs-fs/hubfs/cs-logo-white.png?width=150&height=61&name=cs-logo-white.png "cs-logo-white")

#### **Talk to sales**

[info@container-solutions.com](mailto:info@container-Solutions.com)

#### Stay In Touch

- [**](https://www.linkedin.com/company/container-solutions/)
- [**](https://twitter.com/containersoluti)

© 2024 Container Solutions