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

# OCI OKE Should Use Non-Default Namespaces

### More Info:

Workloads should live in dedicated namespaces, not the default namespace. Per-team namespaces enable namespace-scoped RBAC, NetworkPolicy, and quota, all of which are awkward to apply to default.

### Risk Level

Low

### Address

Compliance, Security

### Compliance Standards

* CIS OKE

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        In OKE, namespaces are Kubernetes objects, so you remediate this by:

        1. **Open OCI Console and Cloud Shell**
           * Sign in to OCI Console.
           * In the top-right, click **Cloud Shell** (terminal icon) to open a shell already authenticated to your tenancy.

        2. **Get Cluster Kubeconfig in Cloud Shell**
           * In the Console, go to **Developer Services → Kubernetes Clusters (OKE)**.
           * Select your **cluster**.
           * Click **Access Cluster** (or **Cluster Access**), choose **Local access** (for Cloud Shell it’s treated as local), and copy the `kubectl` setup command shown (something like `oci ce cluster create-kubeconfig ...`).
           * Paste that command into Cloud Shell and run it.
           * Verify access:
             ```bash theme={null}
             kubectl get ns
             ```

        3. **Create a Non-Default Namespace**
           * Still in Cloud Shell, create a new namespace, e.g. `prod`:
             ```bash theme={null}
             kubectl create namespace prod
             kubectl get ns
             ```
           * Confirm `prod` (or your chosen name) appears.

        4. **Move Workloads Out of `default` Namespace**
           For each deployment/service currently in `default`:

           * Export its manifest:
             ```bash theme={null}
             kubectl get deploy <deployment-name> -n default -o yaml > deploy.yaml
             kubectl get svc <service-name> -n default -o yaml > svc.yaml
             ```

           * Edit the YAML files (in Cloud Shell, use `nano` or `vi`):
             * Change:
               ```yaml theme={null}
               namespace: default
               ```
               to:
               ```yaml theme={null}
               namespace: prod
               ```
             * Remove fields under `metadata` that Kubernetes auto-manages (like `uid`, `resourceVersion`, `creationTimestamp`, `managedFields`) to avoid errors.

           * Apply them into the new namespace:
             ```bash theme={null}
             kubectl apply -f deploy.yaml
             kubectl apply -f svc.yaml
             ```

           * Once confirmed running in the new namespace, delete from `default`:
             ```bash theme={null}
             kubectl delete deploy <deployment-name> -n default
             kubectl delete svc <service-name> -n default
             ```

        5. **Set a Default Namespace in Your Context (Optional)**
           * To avoid accidentally using `default`:
             ```bash theme={null}
             kubectl config set-context --current --namespace=prod
             ```
           * Now running `kubectl get pods` will act in `prod` by default.

        6. **Verify No Workloads Use `default`**
           * Check `default` namespace is empty of your apps:
             ```bash theme={null}
             kubectl get all -n default
             ```
           * Only Kubernetes system objects (if any) should remain, or it can be empty.

        This satisfies the “use non-default namespaces” requirement using the OCI Console plus Cloud Shell.
      </Accordion>

      <Accordion title="Using CLI">
        Below are concise, step‑by‑step remediation instructions to ensure your OCI OKE cluster uses non‑default namespaces, using OCI CLI (to get kubeconfig) and kubectl (for Kubernetes objects).

        ***

        ## 1. Get kubeconfig for the OKE cluster (using OCI CLI)

        1. Make sure OCI CLI is configured:

        ```bash theme={null}
        oci setup config
        ```

        2. Get your OKE cluster OCID (if you don’t have it already):

        ```bash theme={null}
        oci ce cluster list \
          --compartment-id <COMPARTMENT_OCID> \
          --all
        ```

        Copy the `id` of the target cluster.

        3. Generate kubeconfig for that cluster:

        ```bash theme={null}
        oci ce cluster create-kubeconfig \
          --cluster-id <CLUSTER_OCID> \
          --file ~/.kube/oke-config \
          --region <REGION> \
          --token-version 2.0.0 \
          --kube-endpoint PUBLIC_ENDPOINT
        ```

        4. Point kubectl to that config:

        ```bash theme={null}
        export KUBECONFIG=~/.kube/oke-config
        ```

        ***

        ## 2. Create non-default namespaces

        Decide the logical namespaces (e.g., `prod`, `staging`, `dev`).

        ```bash theme={null}
        kubectl create namespace prod
        kubectl create namespace staging
        kubectl create namespace dev
        ```

        Check:

        ```bash theme={null}
        kubectl get namespaces
        ```

        ***

        ## 3. Move workloads out of `default` namespace

        ### 3.1 Identify resources currently in `default` namespace

        ```bash theme={null}
        kubectl get all -n default
        kubectl get configmap,secret,ingress,serviceaccount -n default
        ```

        ### 3.2 Re-deploy workloads into new namespaces

        You cannot “move” namespace of an existing object; you must recreate it:

        1. Export current manifests:

        ```bash theme={null}
        kubectl get deploy,svc,ingress,cm,secret -n default -o yaml > default-resources.yaml
        ```

        2. Edit the file:
           * Change `namespace: default` to the target namespace (e.g., `namespace: prod`) under `metadata`.
           * Remove `status` sections, and any cluster-assigned fields like `resourceVersion`, `uid`, `creationTimestamp`, etc.

        3. Apply to new namespace:

        ```bash theme={null}
        kubectl apply -f default-resources.yaml
        ```

        4. Once you verify everything runs correctly in the new namespace(s), delete the resources from `default`:

        ```bash theme={null}
        kubectl delete all --all -n default
        kubectl delete configmap,secret,ingress,serviceaccount --all -n default
        ```

        ***

        ## 4. Enforce “no workloads in default namespace” (optional but recommended)

        ### 4.1 Use a Namespace-level or cluster policy (Gatekeeper / OPA or admission webhook)

        If using Gatekeeper (as an example):

        1. Install Gatekeeper (once per cluster).
        2. Create a ConstraintTemplate that denies `default` namespace usage.
        3. Create a Constraint, e.g.:

        ```yaml theme={null}
        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: K8sDenyDefaultNamespace
        metadata:
          name: deny-default-namespace
        spec:
          match:
            kinds:
              - apiGroups: [""]
                kinds: ["Pod", "Service", "ConfigMap", "Secret"]
              - apiGroups: ["apps"]
                kinds: ["Deployment", "StatefulSet", "DaemonSet", "ReplicaSet"]
            namespaces: ["*"]
          parameters: {}
        ```

        (Template details depend on your Gatekeeper setup; key point: reject manifests with `metadata.namespace: default` or no namespace.)

        ### 4.2 Enforce namespace usage in CI/CD

        Update Helm charts/Manifests to always specify a non-default namespace and/or use `--namespace <ns>` in deployment scripts.

        ***

        ## 5. Validation

        1. Ensure no resources exist in `default`:

        ```bash theme={null}
        kubectl get all -n default
        kubectl get configmap,secret,ingress,serviceaccount -n default
        ```

        2. Ensure workloads run in non-default namespaces:

        ```bash theme={null}
        kubectl get all -n prod
        kubectl get all -n staging
        kubectl get all -n dev
        ```

        3. Test that new deployments to `default` are rejected (if you added an admission policy).
      </Accordion>

      <Accordion title="Using Python">
        To remediate **“OCI OKE should use non-default namespaces”** with Python, you essentially need to:

        1. Create one or more custom namespaces.
        2. Migrate workloads from `default` to the new namespace(s).
        3. Enforce that new workloads don’t get deployed into `default`.

        Below are concise, step‑by‑step instructions using Python and the Kubernetes Python client (works with any OKE cluster once you have `kubeconfig`).

        ***

        ## 1. Prereqs

        1. Ensure you have `kubectl` access to the OKE cluster and a valid `kubeconfig`:
           ```bash theme={null}
           kubectl get nodes
           ```

        2. Install the Kubernetes Python client:
           ```bash theme={null}
           pip install kubernetes
           ```

        3. Ensure your `KUBECONFIG` environment variable is set (or `~/.kube/config` exists and points to OKE):

           ```bash theme={null}
           export KUBECONFIG=/path/to/oke-kubeconfig
           ```

        ***

        ## 2. Create a Non-Default Namespace via Python

        ```python theme={null}
        from kubernetes import client, config

        # Load kubeconfig for OKE cluster
        config.load_kube_config()   # or load_incluster_config() if running inside OKE

        v1 = client.CoreV1Api()

        namespace_name = "prod-apps"   # choose your non-default namespace

        # Check if namespace already exists
        existing_namespaces = [ns.metadata.name for ns in v1.list_namespace().items]
        if namespace_name not in existing_namespaces:
            namespace_body = client.V1Namespace(
                metadata=client.V1ObjectMeta(
                    name=namespace_name,
                    labels={"istio-injection": "enabled"}  # example label; optional
                )
            )
            v1.create_namespace(body=namespace_body)
            print(f"Namespace '{namespace_name}' created.")
        else:
            print(f"Namespace '{namespace_name}' already exists.")
        ```

        ***

        ## 3. Migrate Existing Deployments from `default` to the New Namespace

        Kubernetes does not support changing the namespace of an existing object in place. You have to:

        * Fetch the object from `default`
        * Remove the `resourceVersion`, `uid`, etc.
        * Re-create it in the new namespace
        * Delete it from `default`

        Example for Deployments:

        ```python theme={null}
        from kubernetes import client, config
        from copy import deepcopy

        config.load_kube_config()
        apps_v1 = client.AppsV1Api()

        old_ns = "default"
        new_ns = "prod-apps"

        # 1. Get all deployments in the default namespace
        deployments = apps_v1.list_namespaced_deployment(namespace=old_ns).items

        for dep in deployments:
            name = dep.metadata.name
            print(f"Migrating deployment: {name}")

            # 2. Clean metadata for re-create
            new_dep = deepcopy(dep)
            new_dep.metadata.namespace = new_ns
            for attr in ["resource_version", "uid", "creation_timestamp", "self_link", "generation"]:
                if hasattr(new_dep.metadata, attr):
                    setattr(new_dep.metadata, attr, None)
            if new_dep.status:
                new_dep.status = None

            # 3. Create in new namespace
            apps_v1.create_namespaced_deployment(namespace=new_ns, body=new_dep)

            # 4. Delete in old namespace
            apps_v1.delete_namespaced_deployment(
                name=name,
                namespace=old_ns,
                body=client.V1DeleteOptions(propagation_policy="Foreground")
            )
            print(f"Deployment '{name}' moved from '{old_ns}' to '{new_ns}'")
        ```

        Repeat similarly for Services, ConfigMaps, Secrets, etc., as needed.

        ***

        ## 4. Ensure New Workloads Use Non-Default Namespace

        You can enforce non-default namespaces in several ways. The simplest operational method:

        * Create and use context that defaults to your new namespace.
        * Optionally, use an Admission Controller (e.g., Gatekeeper/Kyverno) to block `default` usage.

        ### 4.1. Default to the New Namespace in `kubeconfig` (Operational Control)

        You can script modification of your `kubeconfig` with Python (YAML edit) so your context defaults to the non-default namespace:

        ```python theme={null}
        import yaml
        from pathlib import Path

        kubeconfig_path = Path("~/.kube/config").expanduser()
        with kubeconfig_path.open() as f:
            cfg = yaml.safe_load(f)

        current_context_name = cfg["current-context"]
        for ctx in cfg["contexts"]:
            if ctx["name"] == current_context_name:
                ctx["context"]["namespace"] = "prod-apps"   # your non-default ns
                break

        with kubeconfig_path.open("w") as f:
            yaml.safe_dump(cfg, f)

        print(f"Context '{current_context_name}' now defaults to namespace 'prod-apps'")
        ```

        With this, `kubectl apply` (and tools using this context) will use `prod-apps` by default instead of `default`.

        ***

        ## 5. (Optional) Block Use of `default` Namespace with Policy

        If you use Gatekeeper/OPA or Kyverno on OKE, you can add a policy to **deny** resources in `default`. Example (Kyverno) policy YAML (not Python, but you can apply it via Python using the same client patterns above):

        ```yaml theme={null}
        apiVersion: kyverno.io/v1
        kind: ClusterPolicy
        metadata:
          name: disallow-default-namespace
        spec:
          validationFailureAction: enforce
          rules:
            - name: block-default-namespace
              match:
                any:
                - resources:
                    namespaces:
                    - default
                    kinds:
                    - Pod
                    - Deployment
                    - Service
                    - StatefulSet
                    - DaemonSet
              validate:
                message: "Use a non-default namespace. 'default' is not allowed."
                deny: {}
        ```

        You can create that via Python as a generic `CustomObjectsApi` call if Kyverno is installed.

        ***

        **Summary of Remediation**

        1. Use Python/Kubernetes client to **create a non-default namespace** in OKE.
        2. **Migrate workloads** from `default` to that namespace (re-create in the new namespace and delete the old).
        3. **Change your kubeconfig context** so the new namespace is the default.
        4. Optionally **enforce a policy** to block new objects in `default`.

        This satisfies the requirement that OKE “should use non-default namespaces” and provides an automated Python-based approach.
      </Accordion>

      <Accordion title="Using Terraform">
        The `oci_containerengine_cluster` (OKE cluster) resource cannot manage Kubernetes namespaces; namespaces are runtime Kubernetes objects, not an OCI cluster property, so this finding cannot be fixed on that exact resource type via Terraform.

        To remediate with Terraform, you must use the Kubernetes provider against the OKE cluster and create non-default namespaces for your workloads, then move workloads to those namespaces:

        ```hcl theme={null}
        # Configure Kubernetes provider for the OKE cluster
        provider "kubernetes" {
          host                   = "https://YOUR_OKE_ENDPOINT"      # Replace with OKE cluster API endpoint
          cluster_ca_certificate = base64decode("BASE64_CA_CERT")   # Replace with OKE cluster CA cert
          token                  = "BEARER_TOKEN"                   # Replace with an auth token
        }

        # Example dedicated namespaces
        resource "kubernetes_namespace_v1" "team_a" {
          metadata {
            name = "team-a"  # Replace with your team/tenant namespace name
          }
        }

        resource "kubernetes_namespace_v1" "team_b" {
          metadata {
            name = "team-b"  # Replace with your team/tenant namespace name
          }
        }

        # Example workload moved out of "default" into team-a namespace
        resource "kubernetes_deployment_v1" "team_a_app" {
          metadata {
            name      = "team-a-app"
            namespace = kubernetes_namespace_v1.team_a.metadata[0].name
          }

          spec {
            replicas = 2

            selector {
              match_labels = {
                app = "team-a-app"
              }
            }

            template {
              metadata {
                labels = {
                  app = "team-a-app"
                }
              }

              spec {
                container {
                  name  = "app"
                  image = "YOUR_IMAGE:TAG"  # Replace with your image
                }
              }
            }
          }
        }
        ```

        This change does not replace the OKE cluster; it only creates namespaces and re-homes workloads. You must separately update or recreate any existing workloads currently in the `default` namespace to target the new namespaces.

        Verification: `terraform plan` should show creation of `kubernetes_namespace_v1` resources and modifications (or replacements) of Kubernetes workload resources changing `metadata.namespace` from `default` to the dedicated namespaces.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
