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.
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) }
Create the constraint template:
kubectl create -f template.yaml
Expected output:
constrainttemplate.templates.gatekeeper.sh/k8spspallowprivilegeescalationcontainer created
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"]
Create the constraint:
kubectl create -f constraint.yaml
Expected output:
k8spspallowprivilegeescalationcontainer.constraints.gatekeeper.sh/psp-allow-privilege-escalation-container created
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
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
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
Create the Pod:
kubectl create -f allowed-pod.yaml
Expected output:
pod/nginx-privilege-escalation-allowed created