Introduction

So far, we have seen about two OPA use cases and their importance. Today, we’re going to look at a policy used to deny unauthorized configmap volumes from being mounted.

What is a ConfigMap?

Configmaps are similar to Kubernetes Secrets but are used to store non confidential configurations that an application requires like environmental variables that need to be set or command line arguments that have to be run. An application often requires multiple configmaps. So the common practice is to have a separate volume to store all the configmaps and then access them by mounting them.

Why do we need this policy?

As configmaps contain configurations needed for a particular service, we always want the correct configurations to be used. Not restricting the configmaps that can be used by a pod, an attacker, after compromising a pod, might use his own configmap with some malicious configurations rather than using the intended configmap.

Deny Unauthorized ConfigMap Volumes

template.yaml

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyconfigmap
  annotations:
    description: Blocks unauthorized configmaps.
spec:
  crd:
    spec:
      names:
        kind: K8sDenyConfigMap
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            paths:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenyconfigmap

        violation[{"msg": msg, "details": {}}] {
        input.review.object.kind == "Pod"
        allowedconfigmaps := input.parameters.configmaps
        configmap := input.review.object.spec.volumes[_].configMap.name
        not contains(allowedconfigmaps,configmap)
        msg := sprintf("%v - configmap not allowed",[configmap])
        }

        contains(allowedconfigmaps,configmap) {
        configmap == allowedconfigmaps[_]
        }

Rego Policy explained:

  1. Check if the kind is “Pod”
  2. Store the allowed configmap names from parameter in the “allowedconfigmaps” variable.
  3. Store the name of the configmap used in the deployment file in the “configmap” variable.
  4. Since we need to deny if the “configmap” is not in “allowedconfigmaps”, we check if it’s in “allowedconfigmaps” by calling the “contains” and then use “not”. So it will return true only if the path in “configmap” is not in “allowedconfigmaps”.
  5. The message gets printed if all the above returns true.

constraint.yaml

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyConfigMap
metadata:
  name: deny-config-map
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    allowed: ["mysql", "es"]

We have allowed the configmaps with the names “mysql” and “es”.

deployment-non-violation.yaml

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: alpine
      volumeMounts:
      - name: config
        mountPath: "/config"
        readOnly: true
  volumes:
    - name: mysql
      configMap:
        name: demo

This file will get created without any issues as the configmap “mysql” is allowed and can be used by a pod.

deployment-violation.yaml

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: alpine
      volumeMounts:
      - name: config
        mountPath: "/root"
        readOnly: true
  volumes:
    - name: configdata
      configMap:
        name: demo

This will not get created as the configmap named “configdata” is not allowed.

Conclusion

This use case is very important as every application needs configmaps and we might end up not restricting the paths that can be mounted. The takeaways are:

  • We should always remember to prohibit unauthorized configmap volumes that can be used.
  • Another important thing to keep in mind though it’s not related to OPA policy is that we should never store confidential information in configmaps as it’s not meant for that purpose.

Other related articles:

Practice here:

https://www.katacoda.com/cloudsecops/courses/opagatekeeper-policy/configmap

References:

Thank you for reading! – Vishal Pranav and Setu Parimi

Sign up for the blog directly here.

Check out our professional services here.

Feedback is welcome! For professional services, fan mail, hate mail, or whatever else, contact [email protected]


0 Comments

Leave a Reply

%d bloggers like this: