Kubernetes Security Blog | RAD Security

How to Create a Kubernetes Admission Controller

Written by Jimmy Mesta | Nov 28, 2022 2:00:00 PM

There are several components trying to interact with a Kubernetes API. From users to engineers to other applications, the list can be large and multi-tenancy is in full swing.

With so many factors (people, apps, etc.) attempting to access a Kubernetes API, how can you control who (or what) can do what? How can you ultimately define what’s allowed to run in a cluster?

In this blog post, you’re going to learn about admission controllers, what they are, how they’re created, and how to think about another type of controller via a policy-based system.

 

What Are Admission Controllers

Have you ever looked at a Kubernetes Manifest or something that was installed/configured on a Kubernetes cluster and thought to yourself, "This isn’t a good practice. I wish I could block it”? That’s where admission controllers come into play.

Admissions controllers are a way for you to create policies, best practices, and standards across your Kubernetes clusters. Admission controllers intercept API requests before they get passed to the API server so the request can be blocked or modified. For example, let’s say that you want to create a best practice that blocks all container images in a Kubernetes Manifest from being able to use the latest tag, which is an overall bad practice. You can create a policy inside of an admission controller that blocks all requests to use the latest tag. If you have a Kubernetes Manifest that’s using a latest tag, when you try to run kubectl apply -f against the Kubernetes Manifest, the policy won’t allow the resource to run on Kubernetes.

For controllers to work and to be created, there must be some type of standard in how they work. That’s where the controller-runtime comes into play. The controller-runtime is a set of Go libraries used to build controllers.

Controllers also have the ability to utilize mutating webhooks, which can configure the Kubernetes API server to send requests to external webhooks and receive decisions based on the destination. One big way that engineers use webhooks is to call out to systems external to Kubernetes to make policy decisions instead of managing policy decisions only inside of the cluster itself.

Creating An Admission Controller

When you decide that you want to create an admission controller, the goal is to do it in as much of an automated way as possible. That’s where certain tools come in to help you do the job.

The most popular controller creation tool right now is Kubebuilder. Kubebuilder is a framework that allows you to:

  • Semi-automate the creation of controllers
  • Contains libraries to help you easily build controllers
  • Built on top of the controller runtime, so you don’t have to worry about the manual implementation of the runtime
  • Allows you to build a controller using CRDs

If you’re familiar with Ruby On Rails, the framework for providing default database structures, the idea is similar to Kubebuilder. Like Ruby On Rails, Kubebuilder isn’t meant to be a solution that “just works” out of the box. Instead, it’s meant to give you a starting point instead of having to manually start from scratch.

You can get started with a few simple commands. The first command is to install Kubebuilder and the second is to use the Kubebuilder CLI.

# download kubebuilder and install locally.curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH) chmod +x kubebuilder && mv kubebuilder /usr/local/bin/
kubebuilder init --domain my.domain --repo my.domain/guestbook --plugins=go/v4-alpha

For more information, check out these docs: https://book.kubebuilder.io/quick-start.html

Policy Systems Instead Of Admission Controllers

Admission controllers are a great way to implement enforcement in your environment. They work great, are completely customizable, and can be implemented in any way you desire. However, the reality is that admission controllers aren’t the easiest thing to create or manage. Unless you’re a Kubernetes Controller, as in, an engineer that’s writing Controllers all day long, chances are you’ve probably never created a Controller before. Typically, Controllers are created to enhance API functionality, so a lot of platforms will have Controllers. That way, their platform can interact with Kubernetes. Even in that instance, a fair amount of organizations just end up creating CRD’s so they don’t have to worry about a full-blown Controller.

Because of what admission controllers give you out of the box, a way more straightforward way to do the same exact thing is with a policy system.

The most popular policy system right now is Open Policy Agent (OPA). It allows you to enforce policy management for anything and everything running on your Kubernetes cluster. With OPA, there’s a tool called Gatekeeper which essentially connects a Kubernetes cluster to OPA.

To use OPA, you’ll have to use a configuration language (which sort of looks like Go) called Rego. Although you’ll have to learn Rego, it’s definitely easier to learn Rego than it is to write an admission controller.

Wrapping Up

Whether you decide to write your own admission controller or go with OPA, there’s no right or wrong answer. When you look underneath the hood, they’re both effectively doing the same thing. Writing your own admission controller will definitely be a bit more customizable, but it comes at the cost of having engineers that know how to write controllers. The best approach is to always confirm that there isn’t “something” out there that already exists prior to writing your own controller.

KSOC helps customers gain realtime visibility into the security of their Kubernetes clusters and provides fixes for vulnerabilities and misconfigurations. To get in touch with our team, get a demo.