Kubernetes Cluster: Attack and Defense Perspective Part-4

Kyverno - Admission Controller

Posted by Utkarsh Agrawal on July 02, 2022 · 6 mins read

Hello all,

This is the fourth blog on the series, this post focuses on Adminission Controller. How it can be useful at cluster level? We will look into practicle examples and their respected results.

What is Admission Controller?

But before moving ahead, lets first understand what is Admission Controller

AC is a component in kubernetes which controls the resources at cluster level. Control the resources means, it allows what is allwoed to deploy and what is not. So whenever the developer trying to deploy the restricted configuration, the admission controller gets notified by using the webhook URL and validate or mutate the configurations.

Validate and Mutate?

These are two components that are very important to understand.

Validate: It checks wheather it validates the configuration is valid or invalid, if it is invalid, do not deploy.

Mutate: This checks if the configuration is valid, do Nothing. But if it is invalid, then mutate it to the default pre-defined settings. For ex: If hostPath set to '/' then we can mutate it to '/someotherpath/' so when any POD or Deployment contains hostPath value '/' will turns to '/someotherpath'

We can either create our own Admission Controller, where we can create webhooks where we can define the mutate and validate componets, but this will be a very time consuming but if you wanted to understand from its core, then create it manually. Otherwise we can use Kyverno or OPA.

Kyverno - Came to Rescue

Keyverno creates a Admission Controller which intercepts the requests coming from KubeAPI server, and then perform execution of mutate or/and validate policies against the requests. The whole process is automated, you do not need to add the webhooks manually, Kyverno create webhooks automatically.

Install Kyverno

helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno -n kyverno --create-namespace

Now we will look into practical examples

Example #1

We wanted to ensure that each and every ROLE we created must not contain super admin privileges.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
  namespace: default
  name: pod-reader
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]

So what we will create is a Policy, that will check if any of the misconfigurations are trying to deploy in the cluster, do not deploy them.

this is the example of Kyverno Policy

apiVersion: kyverno.io/v1
kind: ClusterPolicy
  name: validate-rbac-policies
  validationFailureAction: enforce
  background: true
  - name: validate-rbac-policies
      - resources:
            - Role
            - ClusterRole

      message: "Do not implement dangerous permissions"
            - key: ""
              operator: Equals
              value: true

what exactly this policy is doing is, it match the kind of the configuration, is it a Role or ClusterRole. Once it identified, it sends the validate request to admission controller via HTTP Webhook which validate the Kind against the policies that we defined. We defined deny if only the condiction applied. And the condition here is, it checks the resources if it is set to '*' if it is set to '*' deny the deployment of Role inside the cluster.

And as a result, we received an error

Example #2

In this example we will try to validate the POD Security Standards, if set insecurely, do not deploy.

This is the policy that we created

apiVersion: kyverno.io/v1
kind: ClusterPolicy
  name: validate-ns-permission
  validationFailureAction: enforce
  background: true
  - name: validate-ns-permission
      - resources:
            - Namespace

      message: "Privileged PSA Found"
            =(pod-security.kubernetes.io/enforce): "!privileged"
            =(pod-security.kubernetes.io/audit): "!privileged"
            =(pod-security.kubernetes.io/warn): "!privileged"

This Policy deny the deployment of Namespace if any Namespace configuration contains any lable set to privileged.

Now if we try to deploy Namespace (the configuration is on right side in image) with any of these lables, we received the error.

The error we received

Example #3

Now we will execute an exmaple of Mutation. Suppose we wanted to deploy the default configurations so whenever the developer applied the configurations that are not the default, the mutationwebhook will convert the configurations to default one. Lets see how

We wanted to change 'privileged' to 'restricted'. So we created a mutate policy.

In the left hand side, we can see that we added mutate instead of validate. And we defined 'restricted' for the lable 'pod-security.kubernetes.io/enforce'. In the right hand side we can see we are tyring to deploy 'privileged' permission to the namespace. We deployed namespace as below:

So after deploying the Namespace, we received no error, why? If you have remember we also had the validate policy which checks if 'privileged' is set then don't deploy. So why are not we receiving any error?

Because mutation webhooks always take preference first then validation webhooks. So once we apply the namespace, the mutation webhook called, it changes the 'privileged' value to 'restricted' and then validate webhook called, which checks no 'privileged' was used (as it turns to restricted by mutation webhook) and we recevied no errors. So we successfully mutate objects by using Kyverno.

This could help in securing Kubernetes Environment at the earliest stage. We can use automated tools after this, so if somehow we deployed vulnerable configuration, the automated tools could suggessfully caught the misconfiguration and notified the developer. We will talk these in later posts



That's all folks, I hope you find this useful. Let me know if you have anysuggestions.

Contact me on twitter- agrawalsmart7

Have a great weekend

Thanks for your time