Skip to content
Notifications
Clear all

Guide: Setting up OPA Gatekeeper for pod security policies in under 30 minutes

2 Posts
2 Users
0 Reactions
1 Views
(@jamesw)
Trusted Member
Joined: 7 days ago
Posts: 48
Topic starter   [#17179]

Most guides for OPA Gatekeeper are either vendor marketing or academic deep dives. I needed to get pod security policies enforced on a new cluster, fast. Here's the stripped-down, working procedure I used, clocked at 28 minutes from zero to blocking a privileged pod.

First, deploy Gatekeeper. The latest stable Helm chart is fine. No need for custom values yet.

```bash
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper gatekeeper/gatekeeper --namespace gatekeeper-system --create-namespace
```

While that settles, define your ConstraintTemplate. This is the reusable policy logic. We'll start with a basic "no privileged pods" template.

```yaml
apiVersion: templates.gatekeeper.io/v1
kind: ConstraintTemplate
metadata:
name: k8spspprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPSPPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspprivilegedcontainer
violation[{"msg": msg, "details": {}}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged
msg := sprintf("Privileged container is not allowed: %v", [container.name])
}
```

Apply that, then create the actual Constraint that enforces it across your chosen scope (e.g., all namespaces except `kube-system`).

```yaml
apiVersion: constraints.gatekeeper.io/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
name: psp-no-privileged
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
excludedNamespaces: ["kube-system"]
```

Test it by trying to launch a pod with `privileged: true`. You should get a clear rejection message. This is your foundation. From here, you can build out more constraints for host namespaces, capabilities, or volume types using the same pattern.

Key things I learned the hard way:
* The ConstraintTemplate defines the *rule*. The Constraint defines the *scope*.
* Audit functionality (checking existing resources) kicks in after a minute or two. Don't panic if it's not instant.
* Keep your Rego simple in these templates. This isn't the place for complex logic.

Total time spent: about 20 minutes for setup, 8 minutes for testing and refining the match/exclude clauses. It's a solid, auditable replacement for the deprecated PSP.

—JW


—JW


   
Quote
(@benchmark_bob_42)
Reputable Member
Joined: 3 months ago
Posts: 151
 

That's a solid start for getting something deployed quickly, but you're missing a critical step. After defining your ConstraintTemplate, you must create a Constraint object that actually applies it to the cluster. The template is just the rule definition; the Constraint is the enforcement.

Your rego snippet also cuts off. The full violation block needs to check both initContainers and containers, or you'll have a policy gap. Here's the complete block you'd want:

```rego
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged
msg := sprintf("Privileged container is not allowed: %v", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.initContainers[_]
container.securityContext.privileged
msg := sprintf("Privileged initContainer is not allowed: %v", [container.name])
}
```

Then you'd `kubectl apply` a Constraint of kind `K8sPSPPrivilegedContainer` to make it active. Without that, your 28-minute claim is for deployment only, not for a working policy.


-- bb42


   
ReplyQuote