Skip to main content

An Admission Policy Engine Should Enforce Workload Policy

More Info:

Advisory: an admission controller (Pod Security Admission, Kyverno, or OPA Gatekeeper) should enforce workload best practices at admission time, not only detect them after the fact.

Risk Level

Medium

Address

Security

Compliance Standards

  • Cloudanix Best Practice

Triage and Remediation

Remediation

Manual Steps
  1. Decide which admission policy engine to use (design choice)

    • If you’re on a recent Kubernetes/managed version that supports it and your needs are basic-to-moderate, prefer Pod Security Admission (PSA).
    • If you need rich, custom policies, consider Kyverno or OPA Gatekeeper, but ensure your cloud provider supports installing them (via add-ons or your existing IaC).
    • Map which C1–C5 best practices you want enforced (e.g., disallow privileged pods, require resource limits, restrict hostPath, force non‑root, control capabilities).
  2. Check if any admission policy engine is already enabled (cloud/IaC)

    • In the cloud console, open the cluster details page and look for:
      • A “Pod security” / “Pod security admission” / “Pod security standards” section and note if it is Enabled and which level (e.g., baseline/restricted).
      • Any add‑on entries for Kyverno, OPA Gatekeeper, or similar “policy” controllers.
    • In your IaC (Terraform, Helm, etc.), search for definitions referencing PSA, Kyverno, or Gatekeeper:
      • On a machine with access to your IaC repo:
        cd /absolute/path/to/your/iac/repository
        grep -RniE 'podSecurity|pod_security|kyverno|gatekeeper|constraintTemplate|ClusterPolicy' .
  3. Review whether C1–C5-aligned policies are configured in your chosen tool (cloud/IaC)

    • For PSA via provider/IaC, look at:
      • Cluster‑level settings (e.g., default Pod Security level) in the console or in your IaC resource definitions. Confirm that “baseline” or “restricted” is set to enforce (not only audit or warn).
    • For Kyverno/Gatekeeper via IaC, inspect the policy manifests in your repo (found from the grep in step 2) and confirm they:
      • Enforce: no privileged pods, no host networking/paths unless allowed, resource requests/limits, non‑root users, and other C1–C5 items.
      • Are set to enforce (e.g., Kyverno validationFailureAction: enforce, Gatekeeper enforcementAction: deny).
  4. Decide and implement the enforcement configuration (cloud/IaC change)

    • If no engine is enabled, update your cloud provider configuration or IaC to:
      • Turn on PSA (if available) with an appropriate enforced level on namespaces (e.g., “baseline” or “restricted”), or
      • Deploy a supported policy engine add-on (Kyverno/Gatekeeper) and add policies mapped to C1–C5.
    • If an engine is present but only auditing, modify its configuration (in the console or IaC) to switch relevant rules/policies from “audit/warn” to enforce/deny for the targeted namespaces.
    • Apply the IaC changes using your normal workflow (for example, on your IaC runner machine):
      cd /absolute/path/to/your/iac/repository
      # Example for Terraform; replace with your tooling/commands
      terraform plan
      terraform apply
  5. Verify that policies are enforced at admission time (cloud/IaC + kubectl evidence)

    • From any machine with kubectl access, intentionally try to create a pod that violates one of the C1–C5 controls (e.g., privileged container):
      cat >/tmp/privileged-pod.yaml << 'EOF'
      apiVersion: v1
      kind: Pod
      metadata:
      name: privileged-test
      namespace: default
      spec:
      containers:
      - name: c
      image: nginx
      securityContext:
      privileged: true
      EOF

      kubectl apply -f /tmp/privileged-pod.yaml
    • Confirm the request is rejected with an admission error message from PSA/Kyverno/Gatekeeper, rather than being created and only reported later.
  6. Document the decision and scope of enforcement (cloud/IaC)

    • In your cluster runbook or IaC repository (e.g., docs/security-policies.md), record:
      • Which admission policy engine is in use.
      • Which namespaces are covered and at what enforcement level.
      • Which C1–C5 best practices are enforced vs. only audited.
    • This documentation becomes the evidence that this manual control has been reviewed and a conscious enforcement decision has been made.
Using kubectl

kubectl cannot configure or enable admission policy engines on a managed control plane; this is done in the cloud provider’s console, CLI, or IaC for the cluster itself. Refer to the Manual Steps section for provider-specific guidance on enabling and configuring Pod Security Admission, Kyverno, or OPA Gatekeeper.

Automation
#!/usr/bin/env bash
# Automation: Assess whether an admission policy engine is enforcing workload policy

set -euo pipefail

echo "=== Context ==="
kubectl config current-context || true
echo

echo "=== 1) Pod Security Admission (PSA) configuration ==="
echo "--- Namespace-level PSA labels (enforce only) ---"
kubectl get ns -o custom-columns=NAME:.metadata.name,\
PSA_ENFORCE:.metadata.labels."pod-security\.kubernetes\.io/enforce",\
PSA_ENFORCE_VERSION:.metadata.labels."pod-security\.kubernetes\.io/enforce-version" \
--sort-by=.metadata.name

echo
echo ">> Review guidance:"
echo " - Problem indicators:"
echo " * Many application namespaces lack 'pod-security.kubernetes.io/enforce' label."
echo " * Enforce level is 'privileged' or very permissive in non-system namespaces."
echo " - Healthy indicators:"
echo " * Most workload namespaces have 'baseline' or 'restricted' enforce labels,"
echo " with an explicit enforce-version."

echo
echo "--- Cluster-wide PSA admission configuration (if available) ---"
# This may be empty on some managed control planes; still useful where supported.
kubectl get configmap -n kube-system \
--ignore-not-found \
| grep -E 'psa|admission|pod-security' || echo "No obvious PSA-related ConfigMaps by simple name match."
echo
echo ">> Review guidance:"
echo " - Problem indicators:"
echo " * No provider-level documentation or config visible for PSA,"
echo " AND namespaces also lack enforce labels."
echo " - Note: Provider-managed PSA settings may only be visible in the cloud console or IaC."

echo
echo "=== 2) Kyverno admission controller ==="
echo "--- Kyverno components (namespace kyverno) ---"
kubectl get ns kyverno >/dev/null 2>&1 || {
echo "Namespace 'kyverno' not found."
echo ">> Problem indicator: Kyverno not installed in the standard namespace."
} && {
kubectl get deploy,ds,po,svc -n kyverno || true
}

echo
echo "--- Kyverno ClusterPolicies (cluster-scoped) ---"
kubectl get clusterpolicies.kyverno.io 2>/dev/null || echo "No Kyverno ClusterPolicies found."

echo
echo "--- Kyverno Namespaced Policies ---"
for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'); do
kubectl get policies.kyverno.io -n "$ns" 2>/dev/null | sed "s/^/$ns: /" || true
done

echo
echo ">> Review guidance for Kyverno:"
echo " - Problem indicators:"
echo " * 'kyverno' namespace missing or Kyverno pods not running/Ready."
echo " * No ClusterPolicies or Policies defined."
echo " * Policies all use 'validationFailureAction: audit' (or default audit)"
echo " so violations only log and do NOT block workloads."
echo " - Healthy indicators:"
echo " * Kyverno controller/webhook pods are Running and Ready."
echo " * There are ClusterPolicies/Policies with 'validationFailureAction: enforce'"
echo " covering C1–C5-type best practices (securityContext, resources, etc.)."

echo
echo "=== 3) OPA Gatekeeper admission controller ==="
echo "--- Gatekeeper components (namespace gatekeeper-system) ---"
kubectl get ns gatekeeper-system >/dev/null 2>&1 || {
echo "Namespace 'gatekeeper-system' not found."
echo ">> Problem indicator: Gatekeeper not installed in the standard namespace."
} && {
kubectl get deploy,ds,po,svc -n gatekeeper-system || true
}

echo
echo "--- Gatekeeper Constraints (enforcing policies) ---"
kubectl api-resources --api-group='constraints.gatekeeper.sh' -o name 2>/dev/null || \
echo "No Gatekeeper constraint types registered."

for ct in $(kubectl api-resources --api-group='constraints.gatekeeper.sh' -o name 2>/dev/null); do
echo
echo "Constraint type: $ct"
kubectl get "$ct" -A 2>/dev/null || echo " (none)"
done

echo
echo "--- Gatekeeper ConstraintTemplates (registered policy types) ---"
kubectl get constrainttemplates.templates.gatekeeper.sh 2>/dev/null || echo "No ConstraintTemplates found."

echo
echo ">> Review guidance for Gatekeeper:"
echo " - Problem indicators:"
echo " * 'gatekeeper-system' namespace or pods missing/not Ready."
echo " * No ConstraintTemplates and/or no Constraints."
echo " * Constraints are only used in 'dryrun' (if configured that way in spec.status),"
echo " so violations do not block workloads."
echo " - Healthy indicators:"
echo " * Gatekeeper controller/webhook pods are Running and Ready."
echo " * Constraints exist and are actively enforcing workload best practices."

echo
echo "=== 4) General admission webhooks overview ==="
echo "--- MutatingWebhookConfiguration objects ---"
kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io \
-o wide || echo "No MutatingWebhookConfiguration objects found."

echo
echo "--- ValidatingWebhookConfiguration objects ---"
kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io \
-o wide || echo "No ValidatingWebhookConfiguration objects found."

echo
echo ">> Review guidance for webhooks overall:"
echo " - Problem indicators:"
echo " * No validating/mutating webhooks associated with security policy engines"
echo " (PSA, Kyverno, Gatekeeper, or similar)."
echo " - Healthy indicators:"
echo " * Webhook configurations referencing Kyverno or Gatekeeper services are present,"
echo " and their 'failurePolicy' and 'rules' are set to actually enforce policy."
echo
echo "=== Interpretation summary ==="
echo "Use the sections above to decide:"
echo " - Whether at least one admission policy engine (PSA, Kyverno, or Gatekeeper)"
echo " is installed and its pods are healthy."
echo " - Whether it has policies/constraints configured in enforcing mode, not just audit/dry-run."
echo "If no enforcing admission policy engine is present, this control fails and"
echo "cloud-provider / control-plane configuration should be updated to enable and enforce"
echo "workload best practices at admission time."