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

# No Workloads Should Run In The default Namespace

### More Info:

Verifies the default namespace has no workloads so RBAC, quotas and NetworkPolicies can be scoped per tenant.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* Cloudanix Best Practice

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. List all workloads in the `default` namespace (run on any machine with kubectl access):
           ```sh theme={null}
           kubectl get all -n default
           ```

        2. For each Deployment/StatefulSet/DaemonSet/Job/CronJob in `default`, export its manifest to a file and edit the namespace (run on any machine with kubectl access). Example for a Deployment named `my-app`:
           ```sh theme={null}
           kubectl get deploy my-app -n default -o yaml > my-app.yaml
           ```
           Edit `my-app.yaml` and change:
           ```yaml theme={null}
           metadata:
             namespace: default
           ```
           to:
           ```yaml theme={null}
           metadata:
             namespace: my-tenant-namespace
           ```
           Ensure `my-tenant-namespace` exists:
           ```sh theme={null}
           kubectl create namespace my-tenant-namespace
           ```

        3. Apply the updated workload manifest in the new namespace (run on any machine with kubectl access):
           ```sh theme={null}
           kubectl apply -f my-app.yaml
           ```

        4. Once you confirm the workload is Running in the new namespace, delete the old object from `default` (run on any machine with kubectl access). Example:
           ```sh theme={null}
           kubectl get deploy my-app -n my-tenant-namespace
           kubectl delete deploy my-app -n default
           ```

        5. Repeat steps 2–4 for all remaining controllers and standalone Pods in `default`. For a standalone Pod called `my-pod`:
           ```sh theme={null}
           kubectl get pod my-pod -n default -o yaml > my-pod.yaml
           # edit namespace: default -> my-tenant-namespace
           kubectl apply -f my-pod.yaml
           kubectl get pod my-pod -n my-tenant-namespace
           kubectl delete pod my-pod -n default
           ```

        6. Verification (run on any machine with kubectl access):
           ```sh theme={null}
           { kubectl get pods -n default -o json
             kubectl get namespace default -o json
           } | jq -rs '
             .[0] as $pods | .[1] |
             .metadata as $m
             | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
             | (($pods.items // []) | length) as $count
             | "kind=Namespace name=default uid=\($m.uid) apiVersion=v1"
               + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
               + (if $labels == "" then "" else " labels=\($labels)" end)
               + " podCount=\($count)"
               + " is_compliant=\(if $count == 0 then "true" else "false" end)"'
           ```
           Confirm `podCount=0` and `is_compliant=true`.
      </Accordion>

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

        1. Identify workloads currently in the `default` namespace

        ```bash theme={null}
        kubectl get all -n default
        ```

        2. For each workload type, export its manifest from `default` and prepare it for a new namespace.
           Replace `my-namespace` with your target namespace name (which should already exist or be created ahead of time):

        Deployments:

        ```bash theme={null}
        kubectl get deployment -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "deployment-${name}.yaml"
        done
        ```

        StatefulSets:

        ```bash theme={null}
        kubectl get statefulset -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "statefulset-${name}.yaml"
        done
        ```

        DaemonSets:

        ```bash theme={null}
        kubectl get daemonset -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "daemonset-${name}.yaml"
        done
        ```

        Jobs:

        ```bash theme={null}
        kubectl get job -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "job-${name}.yaml"
        done
        ```

        CronJobs:

        ```bash theme={null}
        kubectl get cronjob -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "cronjob-${name}.yaml"
        done
        ```

        ReplicaSets (if you have standalone ones you want to keep):

        ```bash theme={null}
        kubectl get rs -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "replicaset-${name}.yaml"
        done
        ```

        Services, ConfigMaps, Secrets, and ServiceAccounts that belong with those workloads should also be moved:

        Services:

        ```bash theme={null}
        kubectl get svc -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "svc-${name}.yaml"
        done
        ```

        ConfigMaps:

        ```bash theme={null}
        kubectl get configmap -n default -o name | while read obj; do
          name="${obj##*/}"
          kubectl get "$obj" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "configmap-${name}.yaml"
        done
        ```

        Secrets (exclude built‑ins you don’t want to move, adjust selector as needed):

        ```bash theme={null}
        kubectl get secret -n default --no-headers | awk '{print $1}' | while read name; do
          kubectl get secret "$name" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "secret-${name}.yaml"
        done
        ```

        ServiceAccounts (excluding the default one):

        ```bash theme={null}
        kubectl get sa -n default --no-headers | awk '$1!="default"{print $1}' | while read name; do
          kubectl get sa "$name" -n default -o yaml \
          | sed '/namespace: default/d' \
          | sed "s/^metadata:/metadata:\n  namespace: my-namespace/" \
          > "sa-${name}.yaml"
        done
        ```

        3. Apply the generated manifests into the new namespace

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

        (From a directory containing only the YAMLs you intend to move.)

        4. After confirming the workloads are running correctly in `my-namespace`, delete them from `default`.

        Deployments, StatefulSets, DaemonSets, Jobs, CronJobs:

        ```bash theme={null}
        kubectl delete deployment,statefulset,daemonset,job,cronjob,rs,svc,configmap,secret,sa \
          -n default --all
        ```

        If you need more control, delete selected objects by name instead of `--all`.

        5. Verification (from any machine with kubectl access)

        ```bash theme={null}
        { kubectl get pods -n default -o json
          kubectl get namespace default -o json
        } | jq -rs '
          .[0] as $pods | .[1] |
          .metadata as $m
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | (($pods.items // []) | length) as $count
          | "kind=Namespace name=default uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $labels == "" then "" else " labels=\($labels)" end)
            + " podCount=\($count)"
            + " is_compliant=\(if $count == 0 then "true" else "false" end)"'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        set -euo pipefail

        # Automation for: No Workloads Should Run In The default Namespace (AKS)
        # Runs on: any machine with kubectl access and current-context pointing to the target cluster.

        # CONFIGURATION: set a non-default target namespace where workloads will be moved.
        TARGET_NAMESPACE="workloads"

        echo "==> Ensuring target namespace '${TARGET_NAMESPACE}' exists"
        if ! kubectl get namespace "${TARGET_NAMESPACE}" >/dev/null 2>&1; then
          kubectl create namespace "${TARGET_NAMESPACE}"
        fi

        echo "==> Checking for pods in the 'default' namespace"
        POD_COUNT=$(kubectl get pods -n default --no-headers 2>/dev/null | wc -l | tr -d ' ')
        if [ "${POD_COUNT}" -eq 0 ]; then
          echo "No pods found in 'default' namespace; nothing to move."
        else
          echo "Found ${POD_COUNT} pod(s) in 'default' namespace. Moving workloads to '${TARGET_NAMESPACE}'."

          # Move Deployments
          echo "-> Handling Deployments"
          kubectl get deploy -n default -o name | while read -r deploy; do
            [ -z "${deploy}" ] && continue
            echo "   - Moving ${deploy}"
            kubectl get "${deploy}" -n default -o yaml \
              | sed -e "s/namespace: default/namespace: ${TARGET_NAMESPACE}/" \
              | kubectl apply -n "${TARGET_NAMESPACE}" -f - 
            kubectl delete "${deploy}" -n default --ignore-not-found
          done

          # Move StatefulSets
          echo "-> Handling StatefulSets"
          kubectl get statefulset -n default -o name | while read -r sts; do
            [ -z "${sts}" ] && continue
            echo "   - Moving ${sts}"
            kubectl get "${sts}" -n default -o yaml \
              | sed -e "s/namespace: default/namespace: ${TARGET_NAMESPACE}/" \
              | kubectl apply -n "${TARGET_NAMESPACE}" -f -
            kubectl delete "${sts}" -n default --ignore-not-found
          done

          # Move DaemonSets
          echo "-> Handling DaemonSets"
          kubectl get daemonset -n default -o name | while read -r ds; do
            [ -z "${ds}" ] && continue
            echo "   - Moving ${ds}"
            kubectl get "${ds}" -n default -o yaml \
              | sed -e "s/namespace: default/namespace: ${TARGET_NAMESPACE}/" \
              | kubectl apply -n "${TARGET_NAMESPACE}" -f -
            kubectl delete "${ds}" -n default --ignore-not-found
          done

          # Move ReplicaSets (only those not owned by a higher-level controller)
          echo "-> Handling standalone ReplicaSets"
          kubectl get rs -n default -o jsonpath='{range .items[?(@.metadata.ownerReferences==null)]}{.metadata.name}{"\n"}{end}' \
            | while read -r rs; do
                [ -z "${rs}" ] && continue
                echo "   - Moving replicaset/${rs}"
                kubectl get rs "${rs}" -n default -o yaml \
                  | sed -e "s/namespace: default/namespace: ${TARGET_NAMESPACE}/" \
                  | kubectl apply -n "${TARGET_NAMESPACE}" -f -
                kubectl delete rs "${rs}" -n default --ignore-not-found
              done

          # Move standalone Pods (those not controlled by a workload controller)
          echo "-> Handling standalone Pods"
          kubectl get pods -n default -o jsonpath='{range .items[?(@.metadata.ownerReferences==null)]}{.metadata.name}{"\n"}{end}' \
            | while read -r pod; do
                [ -z "${pod}" ] && continue
                echo "   - Moving pod/${pod}"
                kubectl get pod "${pod}" -n default -o yaml \
                  | sed -e "/^status:$/,\$d" \
                        -e "s/namespace: default/namespace: ${TARGET_NAMESPACE}/" \
                  | kubectl apply -n "${TARGET_NAMESPACE}" -f -
                kubectl delete pod "${pod}" -n default --ignore-not-found
              done
        fi

        echo "==> Verification (CIS CBP C3.2 style)"
        { kubectl get pods -n default -o json
          kubectl get namespace default -o json
        } | jq -rs '
          .[0] as $pods | .[1] |
          .metadata as $m
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | (($pods.items // []) | length) as $count
          | "kind=Namespace name=default uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $labels == "" then "" else " labels=\($labels)" end)
            + " podCount=\($count)"
            + " is_compliant=\(if $count == 0 then "true" else "false" end)"'

        echo "==> Completed"
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
