> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Namespaces Should Enforce Pod Security Admission Baseline Or Stricter

### 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

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On any machine with kubectl access, list all namespaces and identify those missing an enforce label or using an incorrect value (ignore kube-system, kube-public, kube-node-lease if desired):
           ```bash theme={null}
           kubectl get namespaces --show-labels
           ```

        2. For a single noncompliant namespace, set the Pod Security Admission enforce label to baseline (or restricted if your policy requires that) using kubectl:
           ```bash theme={null}
           kubectl label namespace my-namespace pod-security.kubernetes.io/enforce=baseline --overwrite
           ```
           Replace `my-namespace` with the actual namespace name.

        3. If you want to update all noncompliant namespaces at once to baseline, run:
           ```bash theme={null}
           for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
             | grep -Ev '^(kube-system|kube-public|kube-node-lease)$'); do
             lvl=$(kubectl get ns "$ns" -o jsonpath='{.metadata.labels.pod-security\.kubernetes\.io/enforce}' 2>/dev/null || true)
             if [ "$lvl" != "baseline" ] && [ "$lvl" != "restricted" ]; then
               kubectl label namespace "$ns" pod-security.kubernetes.io/enforce=baseline --overwrite
             fi
           done
           ```

        4. For namespaces where you want restricted instead of baseline, label them explicitly:
           ```bash theme={null}
           kubectl label namespace prod-namespace pod-security.kubernetes.io/enforce=restricted --overwrite
           ```

        5. (Optional) If you manage namespaces via manifests or GitOps, ensure each Namespace manifest includes the enforce label so changes persist:
           ```yaml theme={null}
           apiVersion: v1
           kind: Namespace
           metadata:
             name: my-namespace
             labels:
               pod-security.kubernetes.io/enforce: baseline
           ```

        6. Verification (on any machine with kubectl access): rerun the audit command and confirm all relevant namespaces report `is_compliant=true`:
           ```bash theme={null}
           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'
           ```
      </Accordion>

      <Accordion title="Using kubectl">
        On any machine with kubectl access:

        1. Identify noncompliant namespaces (same as audit):

        ```bash theme={null}
        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'
        ```

        2. Patch a specific namespace to enforce `baseline` (example: `dev-namespace`):

        ```bash theme={null}
        kubectl label namespace dev-namespace pod-security.kubernetes.io/enforce=baseline --overwrite
        ```

        To enforce `restricted` instead:

        ```bash theme={null}
        kubectl label namespace dev-namespace pod-security.kubernetes.io/enforce=restricted --overwrite
        ```

        3. Declarative manifest example (preferred for GitOps/IaC):

        Create `namespace-dev-namespace.yaml`:

        ```yaml theme={null}
        apiVersion: v1
        kind: Namespace
        metadata:
          name: dev-namespace
          labels:
            pod-security.kubernetes.io/enforce: baseline
        ```

        Apply it:

        ```bash theme={null}
        kubectl apply -f namespace-dev-namespace.yaml
        ```

        4. Bulk label all existing non-system namespaces to `baseline`:

        ```bash theme={null}
        for ns in $(kubectl get ns --no-headers | awk '{print $1}' | grep -vE '^(kube-system|kube-public|kube-node-lease)$'); do
          kubectl label namespace "$ns" pod-security.kubernetes.io/enforce=baseline --overwrite
        done
        ```

        5. Verification (re-run compliance-style check):

        ```bash theme={null}
        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'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Enforce Pod Security Admission baseline (or keep restricted) on all namespaces
        # except kube-system, kube-public, kube-node-lease.
        #
        # Requirements:
        # - Run on any machine with kubectl access to the cluster.
        # - kubectl must be configured to talk to the target EKS cluster.
        #
        # Behavior:
        # - Namespaces with no enforce label get "baseline".
        # - Namespaces already set to "baseline" or "restricted" are left as-is.
        # - System namespaces kube-system, kube-public, kube-node-lease are skipped.
        # - Safe to re-run (idempotent).

        set -euo pipefail

        echo "Discovering namespaces that need Pod Security Admission enforcement..."

        # Get all non-system namespaces and their current enforce label
        mapfile -t NS_INFO < <(
          kubectl get ns -o jsonpath='{range .items[?(@.metadata.name!="kube-system" && @.metadata.name!="kube-public" && @.metadata.name!="kube-node-lease")]}{.metadata.name}{" "}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\n"}{end}'
        )

        if [ "${#NS_INFO[@]}" -eq 0 ]; then
          echo "No non-system namespaces found."
        fi

        for line in "${NS_INFO[@]}"; do
          ns_name="$(echo "$line" | awk '{print $1}')"
          enforce_val="$(echo "$line" | awk '{print $2}')"

          # Normalize empty to "none"
          if [ -z "${enforce_val:-}" ]; then
            enforce_val="none"
          fi

          case "$enforce_val" in
            restricted)
              echo "Namespace ${ns_name}: already 'restricted', leaving unchanged."
              ;;
            baseline)
              echo "Namespace ${ns_name}: already 'baseline', leaving unchanged."
              ;;
            *)
              echo "Namespace ${ns_name}: enforce='${enforce_val}', setting to 'baseline'."
              kubectl label namespace "${ns_name}" \
                pod-security.kubernetes.io/enforce=baseline \
                --overwrite
              ;;
          esac
        done

        echo
        echo "Verification (should show enforce=baseline or enforce=restricted for all non-system 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 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'
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
