Skip to main content

The Cluster Has At Least One Active Policy Control Mechanism

More Info:

Every namespace with user workloads should be governed by Pod Security Admission or an external policy engine to enforce pod security standards.

Risk Level

Medium

Address

Security

Compliance Standards

  • CIS Kubernetes

Triage and Remediation

Remediation

Manual Steps
  1. Identify namespaces with user workloads

    • Run on: any machine with kubectl access
    • Command:
      kubectl get namespaces
      kubectl get pods --all-namespaces -o wide
    • Decide which namespaces contain user applications (exclude clearly system ones like kube-system, kube-public, kube-node-lease, and any cloud-provider/system namespaces your platform uses).
  2. Check Pod Security Admission labels on those namespaces

    • Run on: any machine with kubectl access
    • Command (replace USER_NAMESPACE with each identified namespace):
      kubectl get ns USER_NAMESPACE -o jsonpath='{.metadata.name}{"\t"}{.metadata.labels}{"\n"}'
    • Review whether labels like pod-security.kubernetes.io/enforce, pod-security.kubernetes.io/warn, or pod-security.kubernetes.io/audit are present and set to an appropriate level (baseline or restricted for enforce).
  3. Check for external policy engines (e.g., Gatekeeper, Kyverno) in the cluster

    • Run on: any machine with kubectl access
    • Commands:
      kubectl get pods -A | egrep -i 'gatekeeper|kyverno|opa|policy'
      kubectl get crds | egrep -i 'constrainttemplate|kyverno|policy'
    • If present, note which engine(s) are installed (e.g., Gatekeeper, Kyverno).
  4. Verify that policies actually cover the user namespaces

    • Run on: any machine with kubectl access
    • For Gatekeeper-like engines:
      kubectl get k8sallowedrepos.constraints.gatekeeper.sh -A 2>/dev/null || true
      kubectl get constraints -A 2>/dev/null || true
    • For Kyverno-like engines:
      kubectl get clusterpolicy -A 2>/dev/null || true
      kubectl get policy -A 2>/dev/null || true
    • Inspect sample policies to confirm they apply cluster-wide or explicitly to each user namespace via spec.match / namespaceSelector (use kubectl get <kind> <name> -o yaml as needed).
  5. Decide and apply remediation where gaps exist

    • If a user namespace has neither Pod Security Admission labels nor coverage by an external policy engine:
      • Option A (Pod Security Admission):
        kubectl label namespace USER_NAMESPACE \
        pod-security.kubernetes.io/enforce=baseline \
        pod-security.kubernetes.io/enforce-version=latest \
        --overwrite
      • Option B (External policy engine): create or update policies to include that namespace in their match rules, then apply them with kubectl apply -f POLICY_FILE.yaml.
  6. Verify that every user namespace is now governed by at least one mechanism

    • Run on: any machine with kubectl access
    • Commands:
      # Re-check namespace labels
      kubectl get ns $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{" "}{end}') \
      -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels}{"\n"}{end}'

      # Optionally, attempt a clearly non-compliant pod in a user namespace to confirm enforcement
      kubectl run psp-test --image=busybox --restart=Never -n USER_NAMESPACE \
      --overrides='{"spec":{"securityContext":{"runAsUser":0}}}' -- sleep 3600 || true
      kubectl describe pod psp-test -n USER_NAMESPACE || true
    • Confirm that either PSA labels enforce a profile or the external engine denies or modifies non-compliant pods in each user namespace.
Using kubectl
# 1) List all namespaces and their PSA labels (if any)
# Run on: any machine with kubectl access
kubectl get ns -o custom-columns=NAME:.metadata.name, \
POD-SECURITY-ENFORCE:.metadata.labels.pod-security\.kubernetes\.io/enforce, \
POD-SECURITY-AUDIT:.metadata.labels.pod-security\.kubernetes\.io/audit, \
POD-SECURITY-WARN:.metadata.labels.pod-security\.kubernetes\.io/warn

# 2) Show full labels for specific namespaces that run user workloads
# Replace <namespace> with the actual namespace name
kubectl get ns <namespace> -o yaml

# 3) Check for known external policy engines (by common labels/CRDs)
# OPA Gatekeeper
kubectl get pods -A -l app=gatekeeper
kubectl get constrainttemplates.constraint.gatekeeper.sh 2>/dev/null
kubectl get constraints --all-namespaces 2>/dev/null

# Kyverno
kubectl get pods -A -l app.kubernetes.io/name=kyverno
kubectl get clusterpolicy,policy -A 2>/dev/null

# 4) List namespaces that have NO Pod Security Admission labels at all
kubectl get ns -o json | jq -r '
.items[]
| select(.metadata.labels["pod-security.kubernetes.io/enforce"] == null
and .metadata.labels["pod-security.kubernetes.io/audit"] == null
and .metadata.labels["pod-security.kubernetes.io/warn"] == null)
| .metadata.name
'

How to review the output

  • From command (1):

    • Problem indication: Any namespace that:
      • Contains user workloads (e.g., dev, prod, staging, app-specific namespaces), and
      • Shows "<none>" or empty values in all three columns POD-SECURITY-ENFORCE, POD-SECURITY-AUDIT, and POD-SECURITY-WARN.
    • These namespaces are not covered by Pod Security Admission and require either PSA labels or an external policy engine.
  • From command (2):

    • Inspect .metadata.labels for:
      • pod-security.kubernetes.io/enforce
      • pod-security.kubernetes.io/enforce-version
      • pod-security.kubernetes.io/audit
      • pod-security.kubernetes.io/warn
    • Problem indication: User-workload namespaces without any of these labels, or labels set to a profile that is weaker than your organization’s required standard (e.g., privileged where your standard is baseline or restricted).
  • From command (3):

    • Problem indication: No Gatekeeper or Kyverno pods running and no constraints/policies defined, combined with user-workload namespaces that also lack PSA labels.
    • In that case, those namespaces have no active policy control mechanism.
  • From command (4):

    • The printed list is all namespaces with no PSA labels.
    • Problem indication: Any namespace in this list that you identify as running user workloads and that is also not governed by an external policy engine (from step 3) fails the control and requires a design decision and remediation.
Automation
#!/usr/bin/env bash
set -euo pipefail

# This script must run on any machine with kubectl access and a kubeconfig
# that can list namespaces and pods cluster‑wide.

# Namespaces to ignore (system/control-plane)
IGNORED_NS_REGEX='^(kube-system|kube-public|kube-node-lease|kube-storage-version-migrator|kube-*|tigera-operator|calico-system|cilium-system|gatekeeper-system|opa|istio-system|linkerd|velero|cert-manager)$'

echo "=== Detecting namespaces with user workloads and checking policy controls ==="
echo

# 1. List namespaces that have at least one non-terminated pod (user workloads candidates)
echo "# Namespaces with running/non-terminated pods (candidate user-workload namespaces):"
kubectl get pods --all-namespaces --field-selector=status.phase!=Succeeded,status.phase!=Failed -o custom-columns='NAMESPACE:.metadata.namespace' --no-headers \
| sort -u \
| grep -Ev "$IGNORED_NS_REGEX" || true
echo

# 2. Show pod-security admission labels on those namespaces
echo "# Pod Security Admission labels on user-workload namespaces:"
echo "# (psa labels: pod-security.kubernetes.io/enforce, warn, audit + version)"
kubectl get ns \
-o custom-columns='NAMESPACE:.metadata.name,ENFORCE:metadata.labels.pod-security\.kubernetes\.io/enforce,ENFORCE_VER:metadata.labels.pod-security\.kubernetes\.io/enforce-version,WARN:metadata.labels.pod-security\.kubernetes\.io/warn,WARN_VER:metadata.labels.pod-security\.kubernetes\.io/warn-version,AUDIT:metadata.labels.pod-security\.kubernetes\.io/audit,AUDIT_VER:metadata.labels.pod-security\.kubernetes\.io/audit-version' \
--no-headers \
| grep -Ev "$IGNORED_NS_REGEX" \
| sort
echo

# 3. Highlight user-workload namespaces that appear to lack a PSA enforce level
echo "# POSSIBLE PROBLEM: user-workload namespaces with no Pod Security 'enforce' label:"
echo "# (These namespaces have running/non-terminated pods but no enforce label set)"
user_ns_with_pods=$(
kubectl get pods --all-namespaces --field-selector=status.phase!=Succeeded,status.phase!=Failed \
-o custom-columns='NAMESPACE:.metadata.namespace' --no-headers \
| sort -u \
| grep -Ev "$IGNORED_NS_REGEX" || true
)

if [ -n "$user_ns_with_pods" ]; then
# Join list into grep pattern
pattern=$(printf '%s\n' "$user_ns_with_pods" | paste -sd'|' -)

kubectl get ns \
-o custom-columns='NAMESPACE:.metadata.name,ENFORCE:metadata.labels.pod-security\.kubernetes\.io/enforce' \
--no-headers \
| grep -E "$pattern" \
| awk '$2=="" {print $1}' \
| sort -u || true
else
echo "# None (no user-workload namespaces with running pods found)."
fi
echo

# 4. OPTIONAL: Look for common external policy engines (Gatekeeper, Kyverno, OPA) by label/namespace
echo "# Detected external policy engine components (best-effort heuristics):"
echo "## Gatekeeper:"
kubectl get pods -A -l gatekeeper.sh/system=yes 2>/dev/null || echo " (none detected)"
echo
echo "## Kyverno:"
kubectl get pods -A -l app=kyverno 2>/dev/null || echo " (none detected)"
echo
echo "## OPA (gatekeeper-system or opa-related namespaces):"
kubectl get pods -A -n gatekeeper-system 2>/dev/null || echo " (no gatekeeper-system namespace)"
kubectl get ns | grep -Ei 'opa|policy' || true
echo

cat <<'EOF'
INTERPRETING OUTPUT (what indicates a problem):

1. Candidate user-workload namespaces:
- Any namespace listed under:
"# Namespaces with running/non-terminated pods (candidate user-workload namespaces):"
is considered to host user workloads (and so SHOULD have a policy control mechanism).

2. Pod Security Admission labels:
- For these namespaces, check the line under:
"# Pod Security Admission labels on user-workload namespaces:"
- If ENFORCE (and ideally ENFORCE_VER) is empty for a user-workload namespace,
that namespace does NOT have Pod Security Admission enforcement configured.

3. Problem indicator:
- The section:
"# POSSIBLE PROBLEM: user-workload namespaces with no Pod Security 'enforce' label:"
lists namespaces that:
* Have running/non-terminated pods (candidate user workloads), AND
* Do NOT have a pod-security.kubernetes.io/enforce label.
- Each namespace listed here is a REVIEW REQUIRED condition for this control:
* Either add/adjust Pod Security Admission labels, OR
* Confirm that an external policy engine is actively governing that namespace.

4. External policy engines:
- The detections under "Detected external policy engine components" are heuristic.
- Presence alone does NOT prove policies are enforced on every user namespace.
- For any namespace flagged as a possible problem, you must manually verify
that your external policy engine has constraints/clusterpolicies that apply
to that namespace and enforce appropriate pod security standards.

This script does NOT automatically fix anything. It surfaces namespaces that
likely need manual review and policy decisions to comply with CIS 5.2.1.
EOF