> ## 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 Limit Default Service Account Usage

### More Info:

Workloads should not run under the namespaces default ServiceAccount. Mounting tokens from the default SA to every pod blurs blast-radius and breaks per-workload least privilege.

### Risk Level

Medium

### Address

Compliance, Security

### Compliance Standards

* CIS OKE

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        In OKE this is a Kubernetes-level issue, so you remediate it by changing service accounts and RBAC inside the cluster. You can *start* from the OCI Console, but the actual fix is done via `kubectl` (e.g., from OCI Cloud Shell).

        Below are the steps doing everything initiated from the OCI Console.

        ***

        ### 1. Open Cloud Shell and connect to the OKE cluster

        1. Sign in to the **OCI Console**.

        2. Open the **navigation menu** → **Developer Services** → **Kubernetes Clusters (OKE)**.

        3. Select the **Compartment** and click your **cluster**.

        4. On the cluster details page, click **Access Cluster**.

        5. In the panel that opens, click **Cloud Shell Access** (or open **Cloud Shell** from the top-right “>\_” icon and follow the displayed `oci ce cluster create-kubeconfig` command).

        6. Run the suggested `oci ce cluster create-kubeconfig` command in Cloud Shell, for example:

           ```bash theme={null}
           oci ce cluster create-kubeconfig \
             --cluster-id <OCID_OF_CLUSTER> \
             --file $HOME/.kube/config \
             --region <region> \
             --token-version 2.0.0 \
             --kube-endpoint PRIVATE_ENDPOINT
           ```

        7. Verify access:

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

        ***

        ### 2. Disable token auto-mount for the default service account

        You need to patch the `default` service account in each namespace where workloads run. Commonly at least `default` and any custom namespaces.

        1. List namespaces:

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

        2. For each relevant namespace (e.g. `default`, `production`, `staging`), run:

           ```bash theme={null}
           kubectl patch serviceaccount default \
             -n <namespace> \
             -p '{"automountServiceAccountToken": false}'
           ```

           Example for the default namespace:

           ```bash theme={null}
           kubectl patch serviceaccount default \
             -n default \
             -p '{"automountServiceAccountToken": false}'
           ```

        This prevents pods in that namespace from automatically mounting the default token unless explicitly overridden.

        ***

        ### 3. Create dedicated, least-privilege service accounts

        Instead of relying on the default service account, create service accounts per application with minimal RBAC.

        1. Create a service account:

           ```bash theme={null}
           kubectl create serviceaccount my-app-sa -n <namespace>
           ```

        2. Define an RBAC role (example: read-only access to ConfigMaps in that namespace). Create a YAML file `role.yaml` in Cloud Shell:

           ```yaml theme={null}
           apiVersion: rbac.authorization.k8s.io/v1
           kind: Role
           metadata:
             name: my-app-readonly
             namespace: <namespace>
           rules:
             - apiGroups: [""]
               resources: ["configmaps"]
               verbs: ["get", "list", "watch"]
           ```

           Apply it:

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

        3. Bind the role to the new service account. Create `rolebinding.yaml`:

           ```yaml theme={null}
           apiVersion: rbac.authorization.k8s.io/v1
           kind: RoleBinding
           metadata:
             name: my-app-readonly-binding
             namespace: <namespace>
           subjects:
             - kind: ServiceAccount
               name: my-app-sa
               namespace: <namespace>
           roleRef:
             kind: Role
             name: my-app-readonly
             apiGroup: rbac.authorization.k8s.io
           ```

           Apply it:

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

        ***

        ### 4. Update workloads to stop using the default service account

        For each deployment/statefulset/daemonset, explicitly set a non-default service account and (optionally) ensure auto-mount is disabled if not needed.

        1. Edit the deployment (example):

           ```bash theme={null}
           kubectl edit deployment my-app -n <namespace>
           ```

        2. Under `spec.template.spec`, add or change:

           ```yaml theme={null}
           spec:
             serviceAccountName: my-app-sa
             automountServiceAccountToken: false   # set to true only if the pod truly needs the token
           ```

        3. Save and exit; Kubernetes will roll out the updated pods.

        4. Verify:

           ```bash theme={null}
           kubectl get pods -n <namespace> -o jsonpath='{range .items[*]}{.metadata.name}{" => "}{.spec.serviceAccountName}{"\n"}{end}'
           ```

        ***

        ### 5. (Optional) Enforce this pattern for new namespaces

        For each new namespace you create, immediately:

        ```bash theme={null}
        kubectl patch serviceaccount default \
          -n <new-namespace> \
          -p '{"automountServiceAccountToken": false}'
        ```

        And always define explicit service accounts + RBAC for new applications.

        ***

        If you share how your workloads are structured (namespaces, critical apps), I can give you concrete `kubectl` patches tailored to your setup.
      </Accordion>

      <Accordion title="Using CLI">
        You can’t directly change Kubernetes service accounts with `oci` itself; you use `oci` to get kubeconfig, then `kubectl` to do the remediation on the OKE cluster.

        Below are the minimal CLI steps to **limit default service account usage** in OKE.

        ***

        ### 1. Get kubeconfig for your OKE cluster (with OCI CLI)

        ```bash theme={null}
        # Set variables
        COMPARTMENT_OCID="<compartment_ocid>"
        CLUSTER_OCID="<cluster_ocid>"
        KUBECONFIG_PATH="$HOME/.kube/config"

        # Generate kubeconfig
        oci ce cluster create-kubeconfig \
          --cluster-id "$CLUSTER_OCID" \
          --file "$KUBECONFIG_PATH" \
          --region "<region_identifier>" \
          --token-version 2.0.0 \
          --kube-endpoint PUBLIC_ENDPOINT
        ```

        Verify:

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

        ***

        ### 2. Disable token automount on the default service account

        Run this for each namespace where you want to restrict the default SA (including `default` and any app namespaces):

        ```bash theme={null}
        NAMESPACE="default"

        kubectl patch serviceaccount default \
          -n "$NAMESPACE" \
          -p '{"automountServiceAccountToken": false}'
        ```

        Optional: verify

        ```bash theme={null}
        kubectl get sa default -n "$NAMESPACE" -o yaml | grep automountServiceAccountToken
        ```

        ***

        ### 3. Ensure workloads don’t use the default SA

        For each Deployment/StatefulSet/DaemonSet, patch them to either:

        #### Option A – Explicitly disable token mounting (if they don’t need K8s API access)

        ```bash theme={null}
        kubectl patch deployment <deployment_name> \
          -n <namespace> \
          --type merge \
          -p '{"spec":{"template":{"spec":{"automountServiceAccountToken": false}}}}'
        ```

        #### Option B – Use a dedicated least-privilege service account

        1. Create a new service account:

           ```bash theme={null}
           kubectl create serviceaccount <sa_name> -n <namespace>
           ```

        2. Bind only needed permissions (example: read-only in namespace):

           ```bash theme={null}
           cat <<EOF | kubectl apply -f -
           apiVersion: rbac.authorization.k8s.io/v1
           kind: Role
           metadata:
             name: <role_name>
             namespace: <namespace>
           rules:
             - apiGroups: [""]
               resources: ["pods"]
               verbs: ["get", "list", "watch"]
           ---
           apiVersion: rbac.authorization.k8s.io/v1
           kind: RoleBinding
           metadata:
             name: <rb_name>
             namespace: <namespace>
           subjects:
             - kind: ServiceAccount
               name: <sa_name>
               namespace: <namespace>
           roleRef:
             kind: Role
             name: <role_name>
             apiGroup: rbac.authorization.k8s.io
           EOF
           ```

        3. Patch the workload to use this SA:

           ```bash theme={null}
           kubectl patch deployment <deployment_name> \
             -n <namespace> \
             --type merge \
             -p '{"spec":{"template":{"spec":{"serviceAccountName":"<sa_name>","automountServiceAccountToken": true}}}}'
           ```

        ***

        ### 4. (Optional) Restrict the default service account’s RBAC rights

        If the `default` service account already has bindings, remove or tighten them:

        ```bash theme={null}
        # List all RoleBindings/ClusterRoleBindings referencing default SA
        kubectl get rolebindings,clusterrolebindings --all-namespaces -o yaml | \
          grep -B5 -A5 "name: default"
        ```

        Then delete or replace those bindings as appropriate, for example:

        ```bash theme={null}
        kubectl delete rolebinding <rb_name> -n <namespace>
        kubectl delete clusterrolebinding <crb_name>
        ```

        ***

        These steps, driven via **OCI CLI → kubeconfig → kubectl**, will effectively limit use and privileges of the default service account in your OKE cluster.
      </Accordion>

      <Accordion title="Using Python">
        Here’s how to remediate “OCI OKE Should Limit Default Service Account Usage” using Python and the Kubernetes API.

        ### Goal

        1. Stop the `default` ServiceAccount from automatically getting tokens.
        2. Detect workloads still using the `default` ServiceAccount so you can fix them.

        ***

        ## 1. Prerequisites

        Install the Kubernetes Python client:

        ```bash theme={null}
        pip install kubernetes
        ```

        Make sure your local `kubectl` can access the OKE cluster (e.g., via `oci ce cluster create-kubeconfig ...` and `KUBECONFIG` or `~/.kube/config`).

        ***

        ## 2. Disable token auto-mounting for the `default` ServiceAccount in all namespaces

        This script:

        * Lists all namespaces
        * Patches the `default` ServiceAccount in each namespace to set `automountServiceAccountToken: false`

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

        def disable_default_sa_automount():
            # Load kubeconfig (adjust if running inside a pod)
            config.load_kube_config()

            v1 = client.CoreV1Api()

            # Get all namespaces
            namespaces = [ns.metadata.name for ns in v1.list_namespace().items]

            for ns in namespaces:
                print(f"Processing namespace: {ns}")
                try:
                    # Build patch body
                    patch_body = {
                        "automountServiceAccountToken": False
                    }

                    # Patch the default ServiceAccount in this namespace
                    v1.patch_namespaced_service_account(
                        name="default",
                        namespace=ns,
                        body=patch_body
                    )
                    print(f"  Patched default ServiceAccount in {ns}")
                except ApiException as e:
                    if e.status == 404:
                        print(f"  No default ServiceAccount found in {ns} (unexpected)")
                    else:
                        print(f"  Failed to patch default SA in {ns}: {e}")

        if __name__ == "__main__":
            disable_default_sa_automount()
        ```

        This makes the default service account safer (no token auto-mount), but it does **not** prevent workloads from explicitly specifying `serviceAccountName: default` or inheriting it.

        ***

        ## 3. Detect pods using the `default` ServiceAccount

        You should also identify existing pods and controllers using the default SA so you can fix manifests (Deployments, StatefulSets, Jobs, etc.) to use dedicated service accounts.

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

        def find_pods_using_default_sa():
            config.load_kube_config()
            v1 = client.CoreV1Api()

            pods = v1.list_pod_for_all_namespaces().items

            print("Pods using the 'default' ServiceAccount:")
            for pod in pods:
                sa_name = pod.spec.service_account_name or "default"
                if sa_name == "default":
                    print(f"- Namespace: {pod.metadata.namespace}, Pod: {pod.metadata.name}")

        if __name__ == "__main__":
            find_pods_using_default_sa()
        ```

        Use this output to:

        * Create dedicated service accounts with minimal RBAC.
        * Update Deployment/Job/StatefulSet specs to use those service accounts.
        * Redeploy workloads so new pods don’t run with `default`.

        ***

        ## 4. (Optional) Enforce at Namespace Level

        You can also set `automountServiceAccountToken: false` at the namespace level as a default:

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

        def set_namespace_default_automount_false():
            config.load_kube_config()
            v1 = client.CoreV1Api()

            namespaces = [ns.metadata.name for ns in v1.list_namespace().items]

            for ns in namespaces:
                print(f"Processing namespace: {ns}")
                patch_body = {
                    "metadata": {
                        "annotations": {
                            "kubernetes.io/automount-service-account-token": "false"
                        }
                    }
                }
                try:
                    v1.patch_namespace(name=ns, body=patch_body)
                    print(f"  Patched namespace {ns}")
                except Exception as e:
                    print(f"  Failed to patch namespace {ns}: {e}")

        if __name__ == "__main__":
            set_namespace_default_automount_false()
        ```

        ***

        Minimal remediation steps in OKE:

        1. Run the script to set `automountServiceAccountToken: false` on all `default` ServiceAccounts.
        2. Identify pods using the `default` SA and update their controllers to use dedicated service accounts with least-privilege RBAC.
        3. (Optional) Annotate namespaces to default to no token auto-mount.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # This cannot be remediated on oci_containerengine_cluster itself; it is a Kubernetes-level setting
        # that must be applied inside the OKE cluster via the Kubernetes provider.

        provider "kubernetes" {
          # Configure this provider to talk to your OKE cluster (substitute as appropriate)
          host                   = "https://OKE_API_ENDPOINT"                 # replace with your OKE API server endpoint
          token                  = "KUBE_BEARER_TOKEN"                        # replace with a valid token
          cluster_ca_certificate = file("PATH_TO_OKE_CLUSTER_CA_CERT.pem")    # replace with the CA file path
        }

        # 1) Disable default ServiceAccount token mounting in a namespace
        resource "kubernetes_service_account" "default_sa_patch" {
          metadata {
            name      = "default"
            namespace = "TARGET_NAMESPACE"  # replace with the namespace you are hardening
          }

          automount_service_account_token = false
        }

        # 2) Create a dedicated ServiceAccount for a workload
        resource "kubernetes_service_account" "app_sa" {
          metadata {
            name      = "APP_SERVICE_ACCOUNT_NAME"  # e.g., "payments-api-sa"
            namespace = "TARGET_NAMESPACE"
          }

          automount_service_account_token = true
        }

        # 3) Example: ensure a deployment uses the dedicated ServiceAccount (not the default)
        resource "kubernetes_deployment" "app" {
          metadata {
            name      = "APP_DEPLOYMENT_NAME"   # e.g., "payments-api"
            namespace = "TARGET_NAMESPACE"
            labels = {
              app = "APP_LABEL"
            }
          }

          spec {
            replicas = 2

            selector {
              match_labels = {
                app = "APP_LABEL"
              }
            }

            template {
              metadata {
                labels = {
                  app = "APP_LABEL"
                }
              }

              spec {
                service_account_name = kubernetes_service_account.app_sa.metadata[0].name

                container {
                  name  = "APP_CONTAINER_NAME"
                  image = "APP_IMAGE_REF"
                }
              }
            }
          }
        }

        # No replacement of the OKE cluster resource is required; these are in-cluster changes only.

        # Verification: `terraform plan` should show:
        # - an in-place update for the `kubernetes_service_account.default_sa_patch` (creating or modifying the "default" SA)
        # - creation of `kubernetes_service_account.app_sa`
        # - creation or update of `kubernetes_deployment.app` to reference the non-default ServiceAccount.
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
