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. Identify noncompliant namespaces (run 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 // {})["pod-security.kubernetes.io/enforce"] // "") as $lvl
    | select($lvl != "baseline" and $lvl != "restricted")
    | .name ][]'
  2. Choose the desired enforcement level for each namespace:

    • Use baseline to allow most workloads while blocking known unsafe patterns.
    • Use restricted for the strongest isolation where workloads can comply.
  3. Label a single namespace to enforce baseline (run on any machine with kubectl access):

    kubectl label namespace NAMESPACE_NAME pod-security.kubernetes.io/enforce=baseline --overwrite
  4. Or label a single namespace to enforce restricted:

    kubectl label namespace NAMESPACE_NAME pod-security.kubernetes.io/enforce=restricted --overwrite
  5. Optionally label multiple namespaces at once (example with baseline):

    kubectl label namespace ns1 ns2 ns3 pod-security.kubernetes.io/enforce=baseline --overwrite
  6. Verify compliance (run 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'

    Confirm that all relevant namespaces show enforce=baseline or enforce=restricted and is_compliant=true.

Using kubectl

On any machine with kubectl access:

  1. Identify noncompliant namespaces
kubectl get ns -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 // {})["pod-security.kubernetes.io/enforce"] // "") as $lvl
| select($lvl != "baseline" and $lvl != "restricted")
| .name
] | .[]'
  1. Label each target namespace to enforce baseline (adjust names as needed; use restricted instead if you choose that policy):
kubectl label namespace my-app-namespace \
pod-security.kubernetes.io/enforce=baseline \
--overwrite

kubectl label namespace another-namespace \
pod-security.kubernetes.io/enforce=baseline \
--overwrite

For many namespaces at once:

for ns in $(kubectl get ns --no-headers | awk '!/kube-system|kube-public|kube-node-lease/ {print $1}'); do
kubectl label namespace "$ns" \
pod-security.kubernetes.io/enforce=baseline \
--overwrite
done
  1. Verification

Run the same audit used by the check:

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
#
# Enforce Pod Security Admission baseline (or restricted) on all
# non-excluded namespaces in an OKE cluster.
#
# Requirements:
# - Run on any machine with kubectl access and jq installed.
# - Current kubeconfig context points to the target OKE cluster.
#
# Behavior:
# - Skips kube-system, kube-public, kube-node-lease.
# - For namespaces without an enforce label, sets baseline.
# - For namespaces already labeled baseline or restricted, leaves as-is.
# - For namespaces with another value, updates to baseline.
# - Safe to re-run (idempotent).
set -euo pipefail

echo "[INFO] Detecting namespaces without compliant Pod Security enforce label..."

# Get list of candidate namespaces (excluding the system namespaces)
mapfile -t NAMESPACES < <(
kubectl get ns -o json | jq -r '
.items[]
| select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
| .metadata.name
'
)

if [ "${#NAMESPACES[@]}" -eq 0 ]; then
echo "[INFO] No user namespaces found."
else
for ns in "${NAMESPACES[@]}"; do
current_level="$(
kubectl get ns "$ns" -o jsonpath='{.metadata.labels.pod-security\.kubernetes\.io/enforce}' 2>/dev/null || true
)"

case "$current_level" in
baseline|restricted)
echo "[INFO] Namespace '$ns' already compliant (enforce=$current_level), skipping."
;;
*)
echo "[INFO] Setting Pod Security enforce level to 'baseline' on namespace '$ns' (was: '${current_level:-none}')."
kubectl label namespace "$ns" \
"pod-security.kubernetes.io/enforce=baseline" \
--overwrite
;;
esac
done
fi

echo "[INFO] Verification: running compliance 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
'