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 your admission enforcement approach (design choice)

    • Choose one primary mechanism to enforce workload policy cluster‑wide:
      • Azure Policy for Kubernetes (OPA Gatekeeper) – recommended in AKS for broad policy-as-code.
      • Pod Security Admission (PSA) – for baseline/restricted pod security controls.
      • Kyverno – if your org standardizes on Kyverno and you are prepared to manage it yourself.
    • Define which CIS C1–C5 practices you want enforced (e.g., no privileged pods, runAsNonRoot, read-only root FS, restricted capabilities, proper ServiceAccount use).
  2. Check if Azure Policy / Gatekeeper is enabled and enforcing (any machine with Azure CLI access)

    • List policy assignments on the AKS cluster’s resource group and subscription (replace the IDs with real values):
      az policy assignment list --resource-group <AKS_RESOURCE_GROUP> --query "[?contains(scope, '<AKS_RESOURCE_ID>')]" -o table

      az policy assignment list --scope <AKS_RESOURCE_ID> -o table
    • In the Azure Portal, open the AKS cluster → Policies blade and review:
      • Whether Azure Policy Add-on for Kubernetes is Enabled.
      • Which Kubernetes policy definitions (Gatekeeper constraints) are Deny vs Audit.
    • If the add-on is disabled or policies are only in Audit/non-blocking mode, plan to enable it and switch critical policies to Deny where operationally acceptable.
  3. Review Pod Security Admission configuration (any machine with Azure CLI access)

    • Get AKS cluster config and inspect the API server profile for PSA settings:
      az aks show \
      --resource-group <AKS_RESOURCE_GROUP> \
      --name <AKS_CLUSTER_NAME> \
      --query "securityProfile.podSecurityPolicy,securityProfile.podSecurity" \
      -o json
    • In the Portal, under the AKS cluster Settings → Policies → Pod Security, review:
      • The Pod Security level (e.g., baseline/restricted) and enforcement mode (Enforce vs Audit).
    • If PSA is disabled or only auditing, decide whether to enable baseline or restricted and set it to Enforce (with appropriate exception strategy for sensitive namespaces).
  4. Map policies to CIS C1–C5 and identify gaps (design + portal/CLI review)

    • For C1–C5 requirements you care about (e.g., disallow hostPath, privileged, hostNetwork, missing resource limits, non-root user, dropped capabilities):
      • Verify there is at least one active enforcement mechanism for each requirement:
        • Azure Policy / Gatekeeper constraint in Deny mode, or
        • PSA level (baseline/restricted) covering that behavior, or
        • Kyverno policy in enforce/block mode.
    • Document gaps where policies exist only in Audit, or not at all.
  5. Adjust configuration to enforce (Portal / Azure CLI / your IaC only)

    • Using Azure Portal or your chosen IaC (ARM/Bicep/Terraform):
      • Enable the Azure Policy Add-on for Kubernetes on the AKS cluster if not enabled.
      • Assign or update Kubernetes policy definitions so that high‑risk CIS C1–C5 controls are configured with effect Deny, not just Audit.
      • In Pod Security settings, enable and enforce an appropriate level (baseline or restricted) for all or selected namespaces.
    • If using Kyverno via IaC, ensure:
      • Kyverno is installed as an add-on or via your deployment tooling.
      • Relevant ClusterPolicy/Policy objects are configured with validationFailureAction: Enforce.
  6. Verify admission enforcement is active (any machine with kubectl access)

    • Retrieve a kubeconfig for the AKS cluster if you don’t have one:
      az aks get-credentials \
      --resource-group <AKS_RESOURCE_GROUP> \
      --name <AKS_CLUSTER_NAME> \
      --overwrite-existing
    • Attempt to create a clearly non-compliant pod (e.g., privileged, hostPath) and confirm it is rejected at admission:
      cat <<'EOF' > /tmp/privileged-pod.yaml
      apiVersion: v1
      kind: Pod
      metadata:
      name: cis-test-privileged
      namespace: default
      spec:
      containers:
      - name: test
      image: mcr.microsoft.com/oss/nginx/nginx:1.21.6
      securityContext:
      privileged: true
      EOF

      kubectl apply -f /tmp/privileged-pod.yaml
    • Verify the command fails with an error message from Azure Policy / Gatekeeper, Pod Security Admission, or Kyverno. If it succeeds, revisit Steps 2–5 to tighten enforcement.
Using kubectl

kubectl cannot configure admission policy engines or AKS control-plane features; this must be done in the Azure portal, Azure CLI, or your IaC (ARM/Bicep/Terraform) definitions for the AKS cluster. Refer to the Manual Steps section for guidance on enabling and configuring Pod Security Admission, Kyverno, or Gatekeeper at the cluster/control-plane level.

Automation
#!/usr/bin/env bash
# Report whether an admission policy engine is enforcing workload policy in an AKS cluster.
# Run on: any machine with kubectl access and the correct context set.

set -euo pipefail

echo "=== 1. Check Kubernetes version (Pod Security Admission availability) ==="
kubectl version --short || {
echo "ERROR: kubectl cannot reach the cluster. Ensure context and credentials are correct."
exit 1
}

echo
echo "=== 2. Pod Security Admission (PSA) configuration (if enabled) ==="
echo "--- Namespaces with Pod Security labels ---"
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{"pod-security.kubernetes.io/enforce="}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\t"}{"version="}{.metadata.labels.pod-security\.kubernetes\.io/enforce-version}{"\n"}{end}' 2>/dev/null | sort || true

echo
echo "--- Namespaces without PSA enforce labels (potentially not enforced) ---"
kubectl get ns -o jsonpath='{range .items[?(!@.metadata.labels.pod-security\.kubernetes\.io/enforce)]}{.metadata.name}{"\n"}{end}' 2>/dev/null | sort || true

echo
echo "INTERPRETATION:"
echo "- Namespaces listed WITHOUT 'pod-security.kubernetes.io/enforce' are not covered by Pod Security Admission enforcement."
echo "- If all or most workload namespaces lack an enforce label, PSA is not effectively enforcing workload policy."

echo
echo "=== 3. Kyverno presence and enforcing policies ==="
echo "--- Kyverno deployment in kyverno namespace ---"
kubectl get deploy -n kyverno 2>/dev/null || echo "No kyverno namespace or deployment found."

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

echo
echo "--- Kyverno Policies (namespaced) ---"
kubectl get policies.kyverno.io --all-namespaces 2>/dev/null || echo "No namespaced Kyverno Policies found."

echo
echo "--- Kyverno ClusterPolicies with validate rules and enforce action ---"
kubectl get clusterpolicies.kyverno.io -o json 2>/dev/null \
| jq -r '
.items[]
| {name: .metadata.name, validationFailureAction: .spec.validationFailureAction, rules: .spec.rules}
| select(.rules != null)
| select([.rules[]? | select(.validate != null)] | length > 0)
| "\(.name)\tvalidationFailureAction=\(.validationFailureAction)"' 2>/dev/null || true

echo
echo "INTERPRETATION:"
echo "- If there is no kyverno Deployment AND no (Cluster)Policies, Kyverno is not enforcing anything."
echo "- For enforcement, you should see ClusterPolicies with validate rules and validationFailureAction set to 'enforce' (or 'audit' + policy exception handling)."

echo
echo "=== 4. OPA Gatekeeper presence and enforcing constraints ==="
echo "--- Gatekeeper system components ---"
kubectl get deploy -n gatekeeper-system 2>/dev/null || echo "No gatekeeper-system namespace or deployment found."

echo
echo "--- Gatekeeper ConstraintTemplates ---"
kubectl get constrainttemplates 2>/dev/null || echo "No ConstraintTemplates found."

echo
echo "--- Gatekeeper Constraints (all kinds) ---"
# List all constraint CRDs and then their instances
CONSTRAINT_CRDS=$(kubectl get crd -o name 2>/dev/null | grep -E '\.constraints.gatekeeper.sh$' || true)
if [ -z "$CONSTRAINT_CRDS" ]; then
echo "No Gatekeeper constraint CRDs found."
else
for crd in $CONSTRAINT_CRDS; do
kind=$(echo "$crd" | cut -d'/' -f2 | cut -d'.' -f1)
echo
echo "Constraints of kind: ${kind}"
kubectl get "$kind" --all-namespaces 2>/dev/null || echo " (none)"
done
fi

echo
echo "INTERPRETATION:"
echo "- If there is no gatekeeper-system deployment AND no ConstraintTemplates/Constraints, Gatekeeper is not enforcing policy."
echo "- Active enforcement normally means:"
echo " * gatekeeper-controller-manager and gatekeeper-audit deployments are running"
echo " * at least one ConstraintTemplate and one or more Constraints exist targeting Pods/workloads."

echo
echo "=== 5. Summary checklist (manual review) ==="
echo "Review the above output and answer:"
echo "1) Pod Security Admission:"
echo " - Are your workload namespaces labeled with 'pod-security.kubernetes.io/enforce' at an appropriate level (e.g., baseline or restricted)?"
echo "2) Kyverno:"
echo " - Is the kyverno deployment running?"
echo " - Are there ClusterPolicies/Policies with validate rules and validationFailureAction=enforce that cover Pods/Deployments/etc.?"
echo "3) OPA Gatekeeper:"
echo " - Is gatekeeper-system running (controller-manager at least)?"
echo " - Are there Constraints that validate Pods/workloads (not just dry-run or audit-only logic)?"

echo
echo "If NONE of PSA, Kyverno (with enforce), or Gatekeeper (with active Constraints) are clearly enforcing workload policies,"
echo "then this cluster DOES NOT meet the requirement for 'an admission policy engine enforcing workload policy'."

What output indicates a problem

  • PSA section: many or all workload namespaces appear under “Namespaces without PSA enforce labels”.
  • Kyverno section: no kyverno deployment and/or no ClusterPolicies/Policies with validationFailureAction=enforce and validate rules.
  • Gatekeeper section: no gatekeeper-system deployment and/or no ConstraintTemplates and Constraints.

If all three mechanisms above are effectively absent or only configured in audit/detect mode, the cluster fails this control and requires a design decision and implementation to introduce an enforcing admission policy engine via AKS configuration/IaC.