Skip to content
Back to skills

Opa Policies

ASecurity

Write OPA/Gatekeeper and Kyverno admission policies for Kubernetes security guardrails.

  • 19 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
ai-agentsgobashreactexpressrailskubernetestestingdebuggingapisecurity

Works with

  • api

Security analysis

A100/100

Scanned October 19, 2026

npx -y skills add sawrus/agent-guides --skill opa-policies --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Opa Policies?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Opa Policies
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sawrus-opa-policies/badge)](https://www.skillsdirectory.com/skills/sawrus-opa-policies)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: opa-policies
type: skill
description: Write OPA/Gatekeeper and Kyverno admission policies for Kubernetes security guardrails.
related-rules:
  - policy-as-code.md
  - container-security.md
allowed-tools: Read, Write, Edit, Bash
---

# Skill: OPA Policies & Kyverno

> **Expertise:** Gatekeeper ConstraintTemplates, Kyverno ClusterPolicies, validation + mutation + generation.

## When to load

When writing admission policies, testing policy changes, or debugging policy-blocked deployments.

## Gatekeeper: ConstraintTemplate + Constraint

```yaml
# 1. ConstraintTemplate — defines the policy logic in Rego
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequirenonroot
spec:
  crd:
    spec:
      names: { kind: K8sRequireNonRoot }
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequirenonroot

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.runAsNonRoot
          msg := sprintf("Container '%v' must set runAsNonRoot: true", [container.name])
        }

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.runAsUser == 0
          msg := sprintf("Container '%v' must not run as UID 0", [container.name])
        }

---
# 2. Constraint — applies the template to specific resources/namespaces
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequireNonRoot
metadata:
  name: require-non-root-production
spec:
  enforcementAction: deny           # deny | warn | dryrun
  match:
    kinds:
      - apiGroups: [apps]
        kinds: [Deployment, StatefulSet, DaemonSet]
    namespaceSelector:
      matchExpressions:
        - key: environment
          operator: In
          values: [production, staging]
```

## Gatekeeper: Require Image Digest

```yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequireimagedigest
spec:
  crd:
    spec:
      names: { kind: K8sRequireImageDigest }
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequireimagedigest

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not contains(container.image, "@sha256:")
          msg := sprintf(
            "Container '%v' image '%v' must reference a digest (@sha256:...), not a mutable tag",
            [container.name, container.image]
          )
        }
```

## Kyverno: Simpler YAML Policies

```yaml
# Disallow privileged containers (Kyverno)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged-containers
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-privileged
      match:
        any:
          - resources:
              kinds: [Pod]
              namespaces: [production, staging]
      validate:
        message: "Privileged containers are not allowed in production/staging"
        pattern:
          spec:
            containers:
              - =(securityContext):
                  =(privileged): "false"
```

```yaml
# Kyverno MUTATION — auto-add security context defaults
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-default-securitycontext
spec:
  rules:
    - name: add-security-context
      match:
        any:
          - resources: { kinds: [Pod] }
      mutate:
        patchStrategicMerge:
          spec:
            containers:
              - (name): "*"
                securityContext:
                  +(runAsNonRoot): true
                  +(allowPrivilegeEscalation): false
                  +(readOnlyRootFilesystem): true
```

## Policy Testing

```bash
# OPA unit tests
cat > policies/test_nonroot.rego << 'REGO'
package k8srequirenonroot

test_deny_root_container {
  violation[{"msg": _}] with input as {
    "review": {"object": {"spec": {"containers": [
      {"name": "app", "securityContext": {"runAsUser": 0}}
    ]}}}
  }
}

test_allow_nonroot_container {
  count(violation) == 0 with input as {
    "review": {"object": {"spec": {"containers": [
      {"name": "app", "securityContext": {"runAsNonRoot": true, "runAsUser": 1000}}
    ]}}}
  }
}
REGO

opa test policies/ -v

# Kyverno test with example manifests
kyverno test . \
  --test-case-selector "policy=disallow-privileged-containers"

# Check which policies blocked a recent admission
kubectl get events -n <ns> | grep "denied\|violated"
```

## Debugging Policy Denials

```bash
# See why a deployment was rejected
kubectl describe deploy <n> -n <ns>
# Look at Events section for: "admission webhook ... denied"

# Check active constraints
kubectl get constraints

# Check constraint violations (audit mode)
kubectl get k8srequirenonroot.constraints.gatekeeper.sh -o jsonpath='{.items[*].status.violations}'
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.