Skip to main content

Namespaces Should Enforce Pod Security Admission Baseline

More Info:​

Verifies each namespace is labeled with pod-security.kubernetes.io/enforce set to baseline or restricted so the built-in Pod Security Admission controller rejects unsafe pods.

Risk Level​

High

Address​

Security

Compliance Standards​

  • Cloudanix Best Practice

Triage and Remediation​

Remediation​

Manual Steps
  1. On any machine with kubectl access, list all namespaces and identify ones missing an enforce label or with an incorrect value:

    kubectl get ns --show-labels
  2. For a single non-excluded namespace (example: my-app), set the enforce level to baseline (or restricted if you choose stricter):

    kubectl label namespace my-app pod-security.kubernetes.io/enforce=baseline --overwrite
  3. To label all non-excluded namespaces at once with baseline, run:

    for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
    | grep -Ev '^(kube-system|kube-public|kube-node-lease)$'); do
    kubectl label namespace "$ns" pod-security.kubernetes.io/enforce=baseline --overwrite
    done
  4. If you prefer restricted for specific namespaces (example: prod-app), override as needed:

    kubectl label namespace prod-app pod-security.kubernetes.io/enforce=restricted --overwrite
  5. (Optional) Review labels on a specific namespace to confirm:

    kubectl get ns my-app -o jsonpath='{.metadata.labels}'
  6. Verification (on any machine with kubectl access):

    kubectl get namespaces -o json | jq -r '
    [ .items[]
    | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
    | .metadata as $m
    | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
    | (($m.labels // {})["pod-security.kubernetes.io/enforce"] // "") as $lvl
    | "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
    + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
    + (if $labels == "" then "" else " labels=\($labels)" end)
    + " enforce=\(if $lvl == "" then "none" else $lvl end)"
    + " is_compliant=\(if ($lvl == "baseline" or $lvl == "restricted") then "true" else "false" end)"
    ] as $rows
    | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
Using kubectl

On any machine with kubectl access to the cluster:

  1. Create a manifest to enforce Pod Security Admission (choose baseline or restricted as appropriate). Example for baseline:
cat > enforce-psa-namespaces.yaml << 'EOF'
apiVersion: v1
kind: Namespace
metadata:
name: default
labels:
pod-security.kubernetes.io/enforce: baseline
---
apiVersion: v1
kind: Namespace
metadata:
name: my-apps
labels:
pod-security.kubernetes.io/enforce: baseline
EOF

Edit the file to include all target namespaces and the desired level (baseline or restricted). Do not include kube-system, kube-public, or kube-node-lease unless you have explicitly decided to.

  1. Apply the labels declaratively:
kubectl apply -f enforce-psa-namespaces.yaml

If you prefer imperative labeling for a few namespaces, you can run (example for restricted):

kubectl label namespace default pod-security.kubernetes.io/enforce=restricted --overwrite
kubectl label namespace my-apps pod-security.kubernetes.io/enforce=restricted --overwrite
  1. Verification (same logic as the audit):
kubectl get namespaces -o json | jq -r '
[ .items[]
| select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
| .metadata as $m
| (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
| (($m.labels // {})["pod-security.kubernetes.io/enforce"] // "") as $lvl
| "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
+ (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
+ (if $labels == "" then "" else " labels=\($labels)" end)
+ " enforce=\(if $lvl == "" then "none" else $lvl end)"
+ " is_compliant=\(if ($lvl == "baseline" or $lvl == "restricted") then "true" else "false" end)"
] as $rows
| if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
Automation
#!/usr/bin/env bash
set -euo pipefail

# PURPOSE:
# Ensure every non-system namespace has
# pod-security.kubernetes.io/enforce set to at least "baseline"
# (leaves "restricted" as-is, does not touch excluded namespaces).
#
# REQUIREMENTS:
# - Run on any machine with kubectl access and current context set.
# - jq must be installed.

# 1) Identify target namespaces (exclude core system ones)
echo "[INFO] Discovering namespaces to label..."
mapfile -t TARGET_NAMESPACES < <(
kubectl get namespaces -o json | jq -r '
.items[]
| select(.metadata.name as $n
| ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
| .metadata.name'
)

if [ "${#TARGET_NAMESPACES[@]}" -eq 0 ]; then
echo "[INFO] No non-system namespaces found. Nothing to do."
exit 0
fi

echo "[INFO] Namespaces considered for enforcement:"
printf ' - %s\n' "${TARGET_NAMESPACES[@]}"

# 2) Apply/ensure enforce=baseline where needed
for ns in "${TARGET_NAMESPACES[@]}"; do
current_level="$(
kubectl get namespace "$ns" -o json \
| jq -r '.metadata.labels["pod-security.kubernetes.io/enforce"] // ""'
)"

case "$current_level" in
restricted)
echo "[SKIP] $ns already at 'restricted' (stricter than baseline)."
;;
baseline)
echo "[OK] $ns already enforced at 'baseline'."
;;
"")
echo "[FIX] Setting enforce=baseline on namespace: $ns"
kubectl label namespace "$ns" \
pod-security.kubernetes.io/enforce=baseline \
--overwrite
;;
*)
echo "[INFO] Namespace $ns currently has enforce='$current_level'."
echo "[INFO] Leaving as-is to avoid downgrading/overriding custom policy."
;;
esac
done

# 3) Verification (adapted from audit command)
echo
echo "[VERIFY] Current Pod Security Admission enforcement per namespace:"
kubectl get namespaces -o json | jq -r '
[ .items[]
| select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
| .metadata as $m
| (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
| (($m.labels // {})["pod-security.kubernetes.io/enforce"] // "") as $lvl
| "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
+ (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
+ (if $labels == "" then "" else " labels=\($labels)" end)
+ " enforce=\(if $lvl == "" then "none" else $lvl end)"
+ " is_compliant=\(if ($lvl == "baseline" or $lvl == "restricted") then "true" else "false" end)"
] as $rows
| if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'