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

# The Default Namespace Should Not Be Used

### More Info:

Using the default namespace for user workloads makes it harder to apply access controls and network policies. Place workloads in dedicated namespaces instead.

### Risk Level

Low

### Address

Security

### Compliance Standards

* CIS AKS

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. List all user resources in the default namespace
           * Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl get all -n default
           kubectl get configmap,secret,ingress,priorityclass,networkpolicy,serviceaccount,role,rolebinding -n default
           ```

        2. Create one or more dedicated namespaces for your workloads (per app/team as needed)
           * Run on: any machine with kubectl access
           ```bash theme={null}
           kubectl create namespace my-app-namespace
           # repeat with other namespace names as required
           ```

        3. Migrate workload controllers (Deployment/StatefulSet/DaemonSet/Job/CronJob) out of default
           * Run on: any machine with kubectl access
           * For each controller in `default`, choose a target namespace and run:
           ```bash theme={null}
           # Example for a Deployment named my-app
           kubectl get deployment my-app -n default -o yaml \
           | sed 's/namespace: default/namespace: my-app-namespace/' \
           | kubectl apply -f -

           kubectl delete deployment my-app -n default
           ```
           * Use the same pattern for `statefulset`, `daemonset`, `job`, and `cronjob` resources.

        4. Migrate Services, Ingresses, and supporting objects (ConfigMaps, Secrets, ServiceAccounts, Roles, RoleBindings, NetworkPolicies)
           * Run on: any machine with kubectl access
           * For each resource in `default`, re-apply into the target namespace and then delete from `default`. Examples:
           ```bash theme={null}
           # Service
           kubectl get service my-service -n default -o yaml \
           | sed 's/namespace: default/namespace: my-app-namespace/' \
           | kubectl apply -f -
           kubectl delete service my-service -n default

           # ConfigMap
           kubectl get configmap my-config -n default -o yaml \
           | sed 's/namespace: default/namespace: my-app-namespace/' \
           | kubectl apply -f -
           kubectl delete configmap my-config -n default

           # Secret
           kubectl get secret my-secret -n default -o yaml \
           | sed 's/namespace: default/namespace: my-app-namespace/' \
           | kubectl apply -f -
           kubectl delete secret my-secret -n default

           # Ingress
           kubectl get ingress my-ingress -n default -o yaml \
           | sed 's/namespace: default/namespace: my-app-namespace/' \
           | kubectl apply -f -
           kubectl delete ingress my-ingress -n default
           ```
           * Repeat for other names/resources until `kubectl get all -n default` only shows the `kubernetes` Service.

        5. Update clients/manifests to stop using the default namespace
           * Run on: any machine with kubectl access
           * Ensure your manifests declare the correct namespace:
           ```yaml theme={null}
           metadata:
             name: my-app
             namespace: my-app-namespace
           ```
           * If you use a kubeconfig context, set a non-default namespace:
           ```bash theme={null}
           kubectl config set-context --current --namespace=my-app-namespace
           ```

        6. Verification (default namespace has no user workloads)
           * Run on: any machine with kubectl access
           ```bash theme={null}
           output=$(kubectl get all -n default --no-headers 2>/dev/null | grep -v '^service\s\+kubernetes\s' || true)
           if [ -z "$output" ]; then echo "DEFAULT_NAMESPACE_UNUSED"; else echo "DEFAULT_NAMESPACE_IN_USE"; fi
           ```
      </Accordion>

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

        1. Create replacement namespaces for workloads currently in `default`\
           Example (adjust names as needed):
           ```bash theme={null}
           kubectl create namespace app-frontend
           kubectl create namespace app-backend
           ```
           Or via manifest:
           ```bash theme={null}
           cat << 'EOF' | kubectl apply -f -
           apiVersion: v1
           kind: Namespace
           metadata:
             name: app-frontend
           ---
           apiVersion: v1
           kind: Namespace
           metadata:
             name: app-backend
           EOF
           ```

        2. List all user resources in the `default` namespace (to plan migration):
           ```bash theme={null}
           kubectl get all -n default -o wide
           ```

        3. For each user workload in `default`, reapply it into a non-default namespace, then delete the original.\
           Example for a deployment:

           ```bash theme={null}
           # Recreate in new namespace
           kubectl get deployment my-app -n default -o yaml \
           | sed 's/namespace: default/namespace: app-frontend/' \
           | kubectl apply -f -

           # Delete from default namespace
           kubectl delete deployment my-app -n default
           ```

           Example for a service:

           ```bash theme={null}
           kubectl get service my-app-svc -n default -o yaml \
           | sed 's/namespace: default/namespace: app-frontend/' \
           | kubectl apply -f -

           kubectl delete service my-app-svc -n default
           ```

           Example for a configmap:

           ```bash theme={null}
           kubectl get configmap my-config -n default -o yaml \
           | sed 's/namespace: default/namespace: app-frontend/' \
           | kubectl apply -f -

           kubectl delete configmap my-config -n default
           ```

        4. For resources that may not have an explicit `namespace:` field (e.g., some autogenerated manifests), you can set it during reapply:
           ```bash theme={null}
           kubectl get deployment my-other-app -n default -o yaml \
           | sed '/^  namespace: /d' \
           | sed 's/^metadata:$/metadata:\n  namespace: app-backend/' \
           | kubectl apply -f -

           kubectl delete deployment my-other-app -n default
           ```

        5. Repeat step 3 for all user-defined objects in `default` (deployments, statefulsets, daemonsets, jobs, cronjobs, services, ingresses, configmaps, secrets, PVCs, etc.), making sure interdependent resources are moved into the same new namespace.

        6. Verification (CIS-aligned):
           ```bash theme={null}
           output=$(kubectl get all -n default --no-headers 2>/dev/null | grep -v '^service\s\+kubernetes\s' || true)
           if [ -z "$output" ]; then echo "DEFAULT_NAMESPACE_UNUSED"; else echo "DEFAULT_NAMESPACE_IN_USE"; fi
           ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Purpose:
        #   Ensure the "default" namespace is not used for user workloads by:
        #     - Creating a target namespace (if it does not exist)
        #     - Moving namespaced workloads out of "default"
        #     - Deleting the originals from "default"
        #     - Verifying no non-kubernetes service resources remain in "default"
        #
        # Requirements:
        #   - Run on any machine with kubectl access and appropriate RBAC.
        #   - kubectl must be configured (KUBECONFIG or in-cluster config).
        #
        # Usage:
        #   ./migrate-default-namespace.sh my-namespace
        #
        # Notes:
        #   - Idempotent: safe to re-run; resources already migrated will be skipped.
        #   - Only handles namespaced workload-style resources and services.
        #   - The script assumes that anything in "default" (except service/kubernetes)
        #     should be moved. Review before running in production.

        set -euo pipefail

        TARGET_NS="${1:-}"
        if [ -z "$TARGET_NS" ]; then
          echo "ERROR: target namespace argument is required."
          echo "Usage: $0 <target-namespace>"
          exit 1
        fi

        echo ">>> Ensuring target namespace '$TARGET_NS' exists"
        if ! kubectl get namespace "$TARGET_NS" >/dev/null 2>&1; then
          kubectl create namespace "$TARGET_NS"
        else
          echo "Namespace '$TARGET_NS' already exists; continuing."
        fi

        echo ">>> Detecting user-defined resources in 'default' namespace"

        # Resource kinds to migrate; adjust as needed for your cluster
        RESOURCE_KINDS=(
          deployments
          statefulsets
          daemonsets
          replicasets
          jobs
          cronjobs
          pods
          services
          configmaps
          secrets
          serviceaccounts
          ingresses
          networkpolicies
          roles
          rolebindings
          persistentvolumeclaims
        )

        # Build a list of "kind/name" in default excluding the built-in "kubernetes" service
        mapfile -t RESOURCES_IN_DEFAULT < <(
          for kind in "${RESOURCE_KINDS[@]}"; do
            # Skip if kind is not supported by the API server
            if ! kubectl api-resources --namespaced -o name 2>/dev/null | grep -qx "$kind"; then
              continue
            fi
            kubectl get "$kind" -n default --no-headers 2>/dev/null | awk -v k="$kind" '
              NF>=1 {
                name=$1;
                # Exclude core "kubernetes" service
                if (!(k=="services" && name=="kubernetes")) {
                  print k "/" name;
                }
              }'
          done
        )

        if [ "${#RESOURCES_IN_DEFAULT[@]}" -eq 0 ]; then
          echo "No user-defined resources found in 'default' (other than service/kubernetes). Nothing to migrate."
        else
          echo "Found the following resources in 'default' to migrate to '$TARGET_NS':"
          printf '  %s\n' "${RESOURCES_IN_DEFAULT[@]}"

          echo ">>> Migrating resources from 'default' to '$TARGET_NS'"

          for rn in "${RESOURCES_IN_DEFAULT[@]}"; do
            kind="${rn%%/*}"
            name="${rn##*/}"

            echo "Processing $kind/$name ..."

            # Check if the resource already exists in the target namespace with same name and kind
            if kubectl get "$kind" "$name" -n "$TARGET_NS" >/dev/null 2>&1; then
              echo "  Skipping: $kind/$name already exists in namespace '$TARGET_NS'."
              # Optionally, delete the source if desired. For safety, we leave it for manual review.
              continue
            fi

            # Export YAML, rewrite namespace, apply to target, then delete from default
            if ! kubectl get "$kind" "$name" -n default -o yaml >/dev/null 2>&1; then
              echo "  WARNING: $kind/$name no longer exists in 'default'; skipping."
              continue
            fi

            echo "  Migrating to '$TARGET_NS' ..."
            kubectl get "$kind" "$name" -n default -o yaml \
              | sed -E "s/^(  )?namespace: default$/\1namespace: $TARGET_NS/" \
              | kubectl apply -f -

            echo "  Deleting original from 'default' ..."
            kubectl delete "$kind" "$name" -n default --ignore-not-found
          done
        fi

        echo ">>> Verification: checking that 'default' namespace has no user workloads"

        output="$(
          kubectl get all -n default --no-headers 2>/dev/null \
            | grep -v '^service[[:space:]]\+kubernetes[[:space:]]' || true
        )"

        if [ -z "$output" ]; then
          echo "DEFAULT_NAMESPACE_UNUSED"
          echo "Verification passed: default namespace has no user-defined workloads."
        else
          echo "DEFAULT_NAMESPACE_IN_USE"
          echo "Verification FAILED: resources still exist in 'default' (excluding service/kubernetes):"
          echo "$output"
          echo "Review and migrate or delete these remaining resources manually."
          exit 2
        fi
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
