> ## 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 without an enforce label or with an incorrect value (excluding system namespaces):
           ```bash theme={null}
           kubectl get ns --show-labels
           ```

        2. For each non-system namespace that should be set to baseline, apply the label:
           ```bash theme={null}
           kubectl label namespace <NAMESPACE_NAME> pod-security.kubernetes.io/enforce=baseline --overwrite
           ```

        3. For each non-system namespace that should be set to restricted, apply the label:
           ```bash theme={null}
           kubectl label namespace <NAMESPACE_NAME> pod-security.kubernetes.io/enforce=restricted --overwrite
           ```

        4. (Optional but recommended) Set the enforce-version label so behavior is consistent across upgrades (replace v1.28 with the API version you target):
           ```bash theme={null}
           kubectl label namespace <NAMESPACE_NAME> pod-security.kubernetes.io/enforce-version=v1.28 --overwrite
           ```

        5. (Optional) If you use GitOps/manifests for namespace definitions, add the labels to the Namespace manifests and re-apply them from any machine with kubectl access:
           ```yaml theme={null}
           apiVersion: v1
           kind: Namespace
           metadata:
             name: <NAMESPACE_NAME>
             labels:
               pod-security.kubernetes.io/enforce: baseline   # or restricted
               pod-security.kubernetes.io/enforce-version: v1.28
           ```
           Apply:
           ```bash theme={null}
           kubectl apply -f <namespace-manifest>.yaml
           ```

        6. Verification (on any machine with kubectl access): run the same audit logic and confirm all non-exempt namespaces show enforce=baseline or enforce=restricted with 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. Create a manifest labeling all existing non-system namespaces with `baseline` (edit to `restricted` if desired):

        ```bash theme={null}
        kubectl get ns \
          --no-headers \
          | awk '!/^(kube-system|kube-public|kube-node-lease)[[:space:]]/ {print $1}' \
          | xargs -I{} echo "---\napiVersion: v1\nkind: Namespace\nmetadata:\n  name: {}\n  labels:\n    pod-security.kubernetes.io/enforce: baseline" \
          > enforce-psa-namespaces.yaml
        ```

        2. Apply the manifest:

        ```bash theme={null}
        kubectl apply -f enforce-psa-namespaces.yaml
        ```

        3. For any new namespace you create, include the label in its manifest, for example:

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

        Apply it with:

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

        4. Verification (same logic as the audit, using kubectl):

        ```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 // {})["pod-security.kubernetes.io/enforce"] // "") as $lvl
          | "name=\($m.name) enforce=\(if $lvl == "" then "none" else $lvl end)"
            + " is_compliant=\(if ($lvl == "baseline" or $lvl == "restricted") then "true" else "false" end)"
          ][]'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Enforce Pod Security Admission level (baseline or restricted) on all applicable namespaces.
        # Platform: Azure AKS
        # Requirements: kubectl, jq in PATH; current context set to target cluster.

        set -euo pipefail

        # -----------------------------
        # Configuration
        # -----------------------------
        # Desired enforcement level: "baseline" or "restricted"
        DESIRED_LEVEL="baseline"

        # Namespaces to exclude from labeling (system namespaces)
        EXCLUDE_NS=("kube-system" "kube-public" "kube-node-lease")

        # -----------------------------
        # Helper functions
        # -----------------------------

        contains() {
          local e match="$1"; shift
          for e; do
            if [[ "$e" == "$match" ]]; then
              return 0
            fi
          done
          return 1
        }

        # -----------------------------
        # Main logic
        # -----------------------------

        echo "Fetching namespaces..."
        ALL_NS_JSON="$(kubectl get namespaces -o json)"

        # Build list of namespaces to process
        MAPFILE -t TARGET_NAMESPACES < <(
          echo "$ALL_NS_JSON" | jq -r '.items[].metadata.name' |
          while read -r ns; do
            if contains "$ns" "${EXCLUDE_NS[@]}"; then
              continue
            fi
            echo "$ns"
          done
        )

        if [[ "${#TARGET_NAMESPACES[@]}" -eq 0 ]]; then
          echo "No namespaces to process (only excluded namespaces found)."
        else
          echo "Will ensure label pod-security.kubernetes.io/enforce=${DESIRED_LEVEL} on namespaces:"
          printf '  %s\n' "${TARGET_NAMESPACES[@]}"
        fi

        # Apply label in an idempotent way
        for ns in "${TARGET_NAMESPACES[@]}"; do
          # Check current value
          current_val="$(kubectl get ns "$ns" -o jsonpath='{.metadata.labels.pod-security\.kubernetes\.io/enforce}' 2>/dev/null || true)"
          if [[ "$current_val" == "$DESIRED_LEVEL" ]]; then
            echo "Namespace '$ns' already has pod-security.kubernetes.io/enforce=${DESIRED_LEVEL}; skipping."
            continue
          fi

          echo "Labeling namespace '$ns' with pod-security.kubernetes.io/enforce=${DESIRED_LEVEL}..."
          kubectl label namespace "$ns" "pod-security.kubernetes.io/enforce=${DESIRED_LEVEL}" --overwrite
        done

        # -----------------------------
        # Verification (same logic as audit)
        # -----------------------------

        echo
        echo "Verification (CIS CBP C3.3):"

        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>
