In a previous blog post which you can find here, OPA was explained in the sense of why it’s important and how it changes the game for policy management in today’s world.
Now that you know the theory from that blog post, let’s talk about how to get hands-on.
In this blog post, you’ll learn about installing Gatekeeper and how to configure policies for your Kubernetes cluster.
Gatekeeper Install
First, you’ll need to install Gatekeeper on your Kubernetes cluster. To do that, you can use Helm.
Add the Gatekeeper repo.
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
Next, run the installation.
helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace
You should see an output similar to the one below.
NAME: gatekeeper
LAST DEPLOYED: Thu Sep 8 12:36:20 2022
NAMESPACE: gatekeeper-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
Config Implementation
Once Gatekeeper is installed, you’ll have to configure it. There are three types of configurations:
- The config for Gatekeeper itself
- The template
- The constraint implementation
Config
The config is your definition of what Gatekeeper is allowed to create policies for. For example, in the config.yaml
below, Gatekeeper knows that it can only specify Policies for Pods, but no other Kubernetes resources.
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
name: config
namespace: "gatekeeper-system"
spec:
sync:
syncOnly:
- group: ""
version: "v1"
kind: "Pod"
The config also ensures that the policy is set across clusters, not just the node where Gatekeeper was installed.
For example, if you have Pods running on multiple worker nodes, you'd need a Config so Gatekeeper can have access to the Pods across worker nodes.
Constraint Template
The Constraint Template is the rule/policy that you want to configure for your environment. It's a template, so you can use it across multiple constraints.
For example, there's a Rego policy in the constraint template in this directory that ensures no one can utilize the latest
tag of a container image.
Copy the below constraint template and add it to a YAML file. Once complete, run kubectl apply -f
on the YAML file.
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: blocklatesttag
annotations:
description: Blocks container images from using the latest tag
spec:
crd:
spec:
names:
kind: blocklatesttag # this must be the same name as the name on metadata.name (line 4)
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package blocklatesttag
violation[{"msg": msg, "details": {}}]{
input.review.object.kind == "Pod"
imagename := input.review.object.spec.containers[_].image
endswith(imagename,"latest")
msg := "Images with tag the tag \"latest\" is not allowed"
}
Constraint Config
The constraint itself is taking the template that you created above and bringing it to life. It allows you to utilize the template to create your own policy inside of a Kubernetes cluster.
Copy the below constraint template and add it to a YAML file. Once complete, run kubectl apply -f
on the YAML file.
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: blocklatesttag
metadata:
name: nolatestcontainerimage
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
annotation: "no-latest-tag-used"
Testing The Config
To confirm that the OPA policy that you implemented works, you can test it out with the two Kubernetes Manifests below.
The Manifest with the latest
tag won’t work because you created a policy in the previous step to ensure that latest
tags cannot be used. The deployment itself will deploy, but the Pods won’t come online.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginxdeployment
replicas: 2
template:
metadata:
labels:
app: nginxdeployment
spec:
containers:
- name: nginxdeployment
image: nginx:latest
ports:
- containerPort: 80
The Manifest below will work and the Pods will come online because a container image version number is specified.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginxdeployment
replicas: 2
template:
metadata:
labels:
app: nginxdeployment
spec:
containers:
- name: nginxdeployment
image: nginx:1.23.1
ports:
- containerPort: 80
Congrats! You have successfully set up a full OPA integration.