Gatekeeper is the policy controller for Kubernetes, allowing organizations to enforce configurable policies using the Open Policy Agent, a policy engine for Cloud Native environments hosted by CNCF as an incubation-level project.
This tutorial demonstrates how to use Gatekeeper to enforce policies by rejecting non-compliant resources. Specifically, this tutorial will demonstrate two constraints as a way to show how to use Gatekeeper as an alternative to Pod Security Policies:
Before you begin
Before starting this tutorial, you should verify the following:
-
You must have access to a Linux, macOS, or Windows computer with a supported operating system version.
-
You must have a properly deployed and running cluster. For information about deploying Kubernetes with default settings, see the Quick start.
Deploy Gatekeeper
(Optional) Deploy Cert Manager using Helm
Deploying Cert Manager simplifies certificate generation in a Kubernetes cluster. While this tutorial will work without Cert Manager, it also integrates seamlessly with Cert Manager.
Follow the installation documentation to deploy Cert Manager using Helm.
(Optional) Deploy Gatekeeper using Helm
You might have already installed Gatekeeper as a Konvoy addon on your cluster. If that is the case, you can directly start using it.
-
Ensure that Gatekeeper is not already installed by checking the Helm releases running on your cluster:
helm list
Look for a release named
gatekeeper
orgatekeeper-kubeaddons
. If there is one, you do not need to redeploy Gatekeeper. -
Ensure you have added the Mesosphere Staging Helm chart repo with the following command:
helm repo add mesosphere-staging https://mesosphere.github.io/charts/staging
-
Install Gatekeeper using Helm by running the following command:
helm install mesosphere-staging/gatekeeper --name gatekeeper
Alternatively, if you want to integrate with Cert Manager and have installed Cert Manager, use the following command:
helm install mesosphere-staging/gatekeeper --name gatekeeper --set webhook.certManager.enabled=true
Use Gatekeeper
Gatekeeper uses the OPA Constraint Framework to describe and enforce policy. Before you can define a constraint, you must first define a ConstraintTemplate
, which describes both the Rego
(a powerful query language) that enforces the constraint and the schema of the constraint. The schema of the constraint allows an admin to fine-tune the behavior of a constraint, much like arguments to a function.
The Gatekeeper repository includes a [library of policies][gatekeeper-psp] to replace Pod Security Policies which we will use in the following tutorials.
Prevent privileged pods
Define the ConstraintTemplate
Create the privileged pod policy constraint template k8spspprivilegedcontainer
by running the following command:
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/library/pod-security-policy/privileged-containers/template.yaml
Define the Constraint
Constraints are then used to inform Gatekeeper that the admin wants a ConstraintTemplate to be enforced, and how.
Create the privileged pod policy constraint psp-privileged-container
by running the following command:
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/privileged-containers/samples/psp-privileged-container/constraint.yaml
Test that the constraint is enforced
Try to create a privileged pod by running the following command:
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/privileged-containers/samples/psp-privileged-container/example_disallowed.yaml
You should see the following output:
Error from server ([denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}): error when creating "https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/privileged-containers/samples/psp-privileged-container/example_disallowed.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [denied by psp-privileged-container] Privileged container is not allowed: nginx, securityContext: {"privileged": true}
Prevent host path volumes
Define the ConstraintTemplate
Create the host path volume policy constraint template k8spsphostfilesystem
by running the following command:
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/host-filesystem/template.yaml
Define the Constraint
Constraints are then used to inform Gatekeeper that the admin wants a ConstraintTemplate to be enforced, and how.
Create the host path volume policy constraint psp-host-filesystem
by running the following command to only allow /foo
to be mounted as a host path volume:
cat <<EOF | kubectl apply -f -
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPHostFilesystem
metadata:
name: psp-host-filesystem
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
allowedHostPaths:
- readOnly: true
pathPrefix: "/foo"
EOF
Test that the constraint is enforced
Try to create a pod that mounts a disallowed host path by running the following command:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-host-filesystem
labels:
app: nginx-host-filesystem
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /cache
name: cache-volume
readOnly: true
volumes:
- name: cache-volume
hostPath:
path: /tmp # directory location on host
EOF
You should see the following output:
Error from server ([denied by psp-host-filesystem] HostPath volume {"hostPath": {"path": "/tmp", "type": ""}, "name": "cache-volume"} is not allowed, pod: nginx-host-filesystem. Allowed path: [{"readOnly": true, "pathPrefix": "/foo"}]): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [denied by psp-host-filesystem] HostPath volume {"hostPath": {"path": "/tmp", "type": ""}, "name": "cache-volume"} is not allowed, pod: nginx-host-filesystem. Allowed path: [{"readOnly": true, "pathPrefix": "/foo"}]
Test that the constraint allows allowed host paths
Try to create a pod that mounts an allowed host path by running the following command:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: nginx-host-filesystem
labels:
app: nginx-host-filesystem
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /cache
name: cache-volume
readOnly: true
volumes:
- name: cache-volume
hostPath:
path: /foo # directory location on host
EOF
You should see the following output:
pod/nginx-host-filesystem created