In correlation with the end of life (EOL) for MKE 3.6.x, maintenance of this documentation set was discontinued as of 2024-OCT-13. Click here for the latest MKE 3.x version documentation.

Use OPA Gatekeeper

To guide you in the creation of OPA Gatekeeper policies, as an example this topic illustrates how to generate a policy for restricting escalation to root privileges.

Note

Gatekeeper provides a library of commonly used policies, including replacements for familiar PodSecurityPolicies.

Important

For users who are new to Gatekeeper, Mirantis recommends performing a dry run on potential policies prior to production deployment. Such an approach, by only auditing violations, will prevent potential cluster disruption. To perform a dry run, set spec.enforcementAction to dryrun in the constraint.yaml detailed herein.

  1. Create a YAML file called template.yaml and place the following code in that file:

    apiVersion: templates.gatekeeper.sh/v1
    kind: ConstraintTemplate
    metadata:
      name: k8spspallowprivilegeescalationcontainer
      annotations:
        description: >-
          Controls restricting escalation to root privileges. Corresponds to the
          `allowPrivilegeEscalation` field in a PodSecurityPolicy. For more
          information, see
          https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privilege-escalation
    spec:
      crd:
        spec:
          names:
            kind: K8sPSPAllowPrivilegeEscalationContainer
          validation:
            openAPIV3Schema:
              type: object
              description: >-
                Controls restricting escalation to root privileges. Corresponds to the
                `allowPrivilegeEscalation` field in a PodSecurityPolicy. For more
                information, see
                https://kubernetes.io/docs/concepts/policy/pod-security-policy/#privilege-escalation
              properties:
                exemptImages:
                  description: >-
                    Any container that uses an image that matches an entry in this list will be excluded
                    from enforcement. Prefix-matching can be signified with `*`. For example: `my-image-*`.
    
                    It is recommended that users use the fully-qualified Docker image name (e.g. start with a domain name)
                    in order to avoid unexpectedly exempting images from an untrusted repository.
                  type: array
                  items:
                    type: string
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package k8spspallowprivilegeescalationcontainer
    
            import data.lib.exempt_container.is_exempt
    
            violation[{"msg": msg, "details": {}}] {
                c := input_containers[_]
                not is_exempt(c)
                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[_]
            }
            input_containers[c] {
                c := input.review.object.spec.ephemeralContainers[_]
            }
            # has_field returns whether an object has a field
            has_field(object, field) = true {
                object[field]
            }
          libs:
            - |
              package lib.exempt_container
    
              is_exempt(container) {
                  exempt_images := object.get(object.get(input, "parameters", {}), "exemptImages", [])
                  img := container.image
                  exemption := exempt_images[_]
                  _matches_exemption(img, exemption)
              }
    
              _matches_exemption(img, exemption) {
                  not endswith(exemption, "*")
                  exemption == img
              }
    
              _matches_exemption(img, exemption) {
                  endswith(exemption, "*")
                  prefix := trim_suffix(exemption, "*")
                  startswith(img, prefix)
              }
    
  2. Create the constraint template:

    kubectl create -f template.yaml
    

    Expected output:

    constrainttemplate.templates.gatekeeper.sh/k8spspallowprivilegeescalationcontainer created
    
  3. Create a YAML file called constraint.yaml and place the following code in that file:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPAllowPrivilegeEscalationContainer
    metadata:
      name: psp-allow-privilege-escalation-container
    spec:
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pod"]
    
  4. Create the constraint:

    kubectl create -f constraint.yaml
    

    Expected output:

    k8spspallowprivilegeescalationcontainer.constraints.gatekeeper.sh/psp-allow-privilege-escalation-container created
    
  5. Create a YAML file called disallowed-pod.yaml and place the following code in that file:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-privilege-escalation-disallowed
      labels:
        app: nginx-privilege-escalation
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          allowPrivilegeEscalation: true
    
  6. Create the Pod:

    kubectl create -f disallowed-pod.yaml
    

    Expected output:

    Error from server (Forbidden): error when creating "disallowed.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [psp-allow-privilege-escalation-container] Privilege escalation container is not allowed: nginx
    
  7. Create a YAML file called allowed-pod.yaml and place the following code in that file:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-privilege-escalation-allowed
      labels:
        app: nginx-privilege-escalation
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          allowPrivilegeEscalation: false
    
  8. Create the Pod:

    kubectl create -f allowed-pod.yaml
    

    Expected output:

    pod/nginx-privilege-escalation-allowed created