> ## 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 cluster-admin Role Usage Should Be Restricted

### More Info:

The cluster-admin ClusterRole grants unrestricted access to every API. Bind it only to a small, audited set of break-glass identities; daily operations should use scoped roles.

### Risk Level

High

### Address

Compliance, Security

### Compliance Standards

* CIS OKE

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below is how to *tighten* and *restrict* `cluster-admin` usage for an OKE cluster using only the OCI Console (with Cloud Shell and `kubectl`).

        ***

        ## 1. Open the OKE cluster in OCI Console

        1. Sign in to the OCI Console.
        2. In the left menu, go to **Developer Services → Kubernetes Clusters (OKE)**.
        3. Select the **Compartment** that contains your cluster.
        4. Click the **name** of the target OKE cluster.

        ***

        ## 2. Get `kubeconfig` for the cluster

        1. On the cluster details page, click **Access Cluster**.
        2. In the panel that opens:
           * Choose **Cloud Shell** as the client environment (or “Local” if you prefer local `kubectl`, but Cloud Shell keeps you in console).
           * Copy the `kubectl` / `kubeconfig` command snippet shown under *Cloud Shell*.

        Example (you’ll see something similar):

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

        ***

        ## 3. Open Cloud Shell and configure `kubectl`

        1. In the top-right of the OCI Console, click the **Cloud Shell** icon (`>_`).
        2. When Cloud Shell opens, paste and run the **create-kubeconfig** command you copied.
        3. Test connectivity:

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

        If you see nodes listed, you’re connected.

        ***

        ## 4. Identify who currently has `cluster-admin`

        In Cloud Shell:

        ```bash theme={null}
        kubectl get clusterrolebindings.rbac.authorization.k8s.io -o wide
        ```

        Look for bindings that reference the `cluster-admin` ClusterRole, for example:

        ```yaml theme={null}
        Name: cluster-admin-binding
        Role: ClusterRole/cluster-admin
        Subjects:
        - Kind: User
          Name: some-user@example.com
        - Kind: Group
          Name: system:authenticated
        ```

        Take note of:

        * **Bindings that give cluster-admin to broad subjects**, e.g.:
          * `system:authenticated`
          * `system:serviceaccounts`
          * Wildcard-like or large external groups
        * Any **custom ClusterRoleBinding** whose `roleRef.name` is `cluster-admin`.

        ***

        ## 5. Remove or tighten dangerous ClusterRoleBindings

        ### 5.1. Delete overly broad ClusterRoleBindings

        If you find a binding such as:

        ```text theme={null}
        NAME                    ROLE
        everyone-admin          ClusterRole/cluster-admin
        ```

        Inspect it:

        ```bash theme={null}
        kubectl get clusterrolebinding everyone-admin -o yaml
        ```

        If it is broad (e.g., `system:authenticated` or a large IAM group), delete it:

        ```bash theme={null}
        kubectl delete clusterrolebinding everyone-admin
        ```

        Repeat for any other non-essential or overly broad `cluster-admin` bindings.

        **Do NOT** delete the critical system bindings you don’t fully understand (e.g., system ones created by OKE / Kubernetes), unless you are sure they’re not required.

        ***

        ## 6. Replace `cluster-admin` with least-privilege roles

        Instead of giving `cluster-admin`, create narrow roles and bind them.

        ### 6.1. Create a least-privilege ClusterRole (example)

        In Cloud Shell, create a file:

        ```bash theme={null}
        cat > limited-admin-role.yaml << 'EOF'
        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRole
        metadata:
          name: limited-admin
        rules:
          - apiGroups: [""]
            resources: ["pods", "services", "configmaps"]
            verbs: ["get", "list", "watch", "create", "update", "delete"]
          - apiGroups: ["apps"]
            resources: ["deployments", "statefulsets", "daemonsets"]
            verbs: ["get", "list", "watch", "create", "update", "delete"]
        EOF
        ```

        Apply it:

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

        ### 6.2. Bind specific users/groups to the limited role

        Example binding a specific group:

        ```bash theme={null}
        cat > limited-admin-binding.yaml << 'EOF'
        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRoleBinding
        metadata:
          name: limited-admin-binding
        subjects:
          - kind: Group
            name: my-oke-admins-group          # map this to your IdP / OIDC group or user
            apiGroup: rbac.authorization.k8s.io
        roleRef:
          kind: ClusterRole
          name: limited-admin
          apiGroup: rbac.authorization.k8s.io
        EOF
        ```

        Apply:

        ```bash theme={null}
        kubectl apply -f limited-admin-binding.yaml
        ```

        This way, people who previously had `cluster-admin` get only the permissions they actually need.

        ***

        ## 7. Restrict who can reach cluster-admin via OCI IAM

        OKE access is a combination of:

        * **OCI IAM Policies** (who can *manage* or *use* clusters and node pools)
        * **Kubernetes RBAC** (what they can do *inside* the cluster)

        To restrict who can even talk to the cluster as admins:

        1. In the OCI Console, go to **Identity & Security → IAM → Policies**.

        2. In the correct compartment / tenancy, locate policies like:

           ```text theme={null}
           allow group <SomeGroup> to manage cluster-family in compartment <CompartmentName>
           ```

        3. Tighten them as needed:
           * Limit to a smaller group (e.g., `oke-admins`).
           * Change `manage` to `use` if full management is not required.

        4. Save the updated policy.

        This reduces who can obtain kubeconfigs and then become cluster admins.

        ***

        ## 8. Verify the restriction

        1. In Cloud Shell:

           ```bash theme={null}
           kubectl auth can-i '*' '*' --as <some-regular-user>
           ```

           It should return `no` (or only `yes` for allowed verbs/resources).

        2. Confirm that only designated admins (limited group) have the permissions they need.

        ***

        If you tell me how `cluster-admin` is currently granted in your OKE (e.g., sample `clusterrolebinding` output), I can give you an exact “before/after” YAML to apply.
      </Accordion>

      <Accordion title="Using CLI">
        Below is a practical, step‑by‑step way to restrict `cluster-admin` usage in OKE, focusing on OCI CLI (plus `kubectl`, which you invoke after generating kubeconfig via OCI CLI).

        ***

        ## 0. Prereqs

        * OCI CLI configured with a user that has permission to manage IAM and OKE.
        * `kubectl` installed.
        * You know:
          * Your **compartment OCID**.
          * Your **cluster OCID**.
          * The **tenancy or IAM group OCIDs** you want to allow as cluster admins.

        ***

        ## 1. Tighten OCI IAM access to the cluster

        Cluster-admin in OKE is only possible if OCI IAM lets a user manage the cluster and generate kubeconfigs. First restrict who can do that.

        ### 1.1 List current policies

        ```bash theme={null}
        oci iam policy list \
          --compartment-id <compartment_ocid> \
          --all
        ```

        Inspect policies that look like:

        ```text theme={null}
        Allow group <some-group> to manage cluster-family in compartment <name>
        Allow group <some-group> to manage node-pools in compartment <name>
        ```

        And especially any that are overly broad:

        ```text theme={null}
        Allow group Administrators to manage all-resources in tenancy
        ```

        ### 1.2 Update policies to narrow access

        Example: restrict cluster management to a dedicated group `oke-admins`.

        1. Create a JSON file `policy-statements.json`:

        ```json theme={null}
        {
          "statements": [
            "Allow group oke-admins to manage cluster-family in compartment <compartment_name>",
            "Allow group oke-admins to manage node-pools in compartment <compartment_name>"
          ]
        }
        ```

        2. Update an existing policy:

        ```bash theme={null}
        oci iam policy update \
          --policy-id <policy_ocid> \
          --statements file://policy-statements.json
        ```

        3. Remove or modify any policies that give broader rights than needed (e.g., `manage all-resources` in tenancy) to regular users/groups.

        ***

        ## 2. Generate admin kubeconfig only for the right IAM group

        Make sure only your intended admin group members can get a kubeconfig with admin‑level access.

        For an admin user in the `oke-admins` group:

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

        Then:

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

        Confirm access:

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

        Ensure other users/groups that should NOT be cluster-admin:

        * Do not have policies allowing `manage cluster-family` (step 1),
        * Or only have limited policies (e.g., `use cluster-family` / specific verbs).

        ***

        ## 3. Restrict Kubernetes `cluster-admin` RBAC

        Now restrict actual Kubernetes RBAC bindings that grant the `cluster-admin` `ClusterRole`.

        ### 3.1 List all `cluster-admin` bindings

        ```bash theme={null}
        kubectl get clusterrolebindings -o wide | grep cluster-admin || true
        ```

        Also inspect all bindings:

        ```bash theme={null}
        kubectl get clusterrolebindings -o yaml > crb-all.yaml
        ```

        Look for subjects (users/groups/serviceaccounts) that should not have admin.

        ### 3.2 Remove or replace broad cluster-admin bindings

        Common problematic ones:

        * Bindings granting `cluster-admin` to a wide group like `system:masters` or to all authenticated users.

        Delete unwanted ClusterRoleBindings:

        ```bash theme={null}
        kubectl delete clusterrolebinding <binding_name>
        ```

        Examples:

        ```bash theme={null}
        kubectl delete clusterrolebinding cluster-admin-binding
        kubectl delete clusterrolebinding <any-other-problem-binding>
        ```

        If a binding is valid but has too many subjects, you can patch it:

        ```bash theme={null}
        kubectl patch clusterrolebinding <binding_name> \
          --type=json \
          -p='[{"op":"replace","path":"/subjects","value":[{"kind":"Group","name":"oke-admins","apiGroup":"rbac.authorization.k8s.io"}]}]'
        ```

        (Adjust group name as needed.)

        ### 3.3 Create a minimal, explicit `cluster-admin` binding for your admin group

        Create `cluster-admin-oke-admins.yaml`:

        ```yaml theme={null}
        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRoleBinding
        metadata:
          name: cluster-admin-oke-admins
        roleRef:
          apiGroup: rbac.authorization.k8s.io
          kind: ClusterRole
          name: cluster-admin
        subjects:
          - kind: Group
            apiGroup: rbac.authorization.k8s.io
            name: oke-admins
        ```

        Apply:

        ```bash theme={null}
        kubectl apply -f cluster-admin-oke-admins.yaml
        ```

        This ensures only the Kubernetes group `oke-admins` (mapped from your OCI IAM group via OKE auth) has full `cluster-admin` rights.

        ***

        ## 4. Validate

        1. As an admin (in `oke-admins`):

        ```bash theme={null}
        kubectl auth can-i '*' '*' --all-namespaces
        # should be "yes"
        ```

        2. As a non‑admin user (with a separate kubeconfig):

        ```bash theme={null}
        export KUBECONFIG=~/.kube/config-nonadmin
        kubectl auth can-i '*' '*' --all-namespaces
        # should be "no"
        ```

        3. Confirm only your intended bindings reference `cluster-admin`:

        ```bash theme={null}
        kubectl get clusterrolebindings -o yaml | grep -A5 "name: cluster-admin"
        ```

        ***

        If you provide your current policy statements and any `clusterrolebinding` YAML, I can give you exact `oci` and `kubectl` commands tailored to your environment.
      </Accordion>

      <Accordion title="Using Python">
        To restrict `cluster-admin` usage in an OCI OKE cluster using Python, you essentially need to:

        1. Connect to the OKE cluster’s Kubernetes API.
        2. Enumerate all `ClusterRoleBinding` objects that reference `cluster-admin`.
        3. Remove or tighten those bindings so only specific, approved subjects (users/groups/service accounts) retain `cluster-admin`.

        Below is a step‑by‑step approach and example Python code using the Kubernetes Python client.

        ***

        ## 1. Prerequisites

        1. **Have kubectl access to the OKE cluster** (so your kubeconfig works):
           ```bash theme={null}
           oci ce cluster create-kubeconfig \
             --cluster-id <cluster_ocid> \
             --file $HOME/.kube/config \
             --region <region> \
             --token-version 2.0.0 \
             --kube-endpoint PUBLIC_ENDPOINT
           ```

        2. **Install Python dependencies**:
           ```bash theme={null}
           pip install kubernetes
           ```

        3. Ensure your Python environment can read the same kubeconfig used by `kubectl` (usually `$HOME/.kube/config`).

        ***

        ## 2. Decide Your Policy

        Before running the script, decide:

        * Which **subjects are allowed** to have `cluster-admin`:
          * Type: `User`, `Group`, or `ServiceAccount`
          * Namespaces (only for `ServiceAccount`)
          * Names (e.g., `oke-cluster-admins` group)

        For example, you might allow only:

        ```text theme={null}
        - Group: "oke-cluster-admins"
        - ServiceAccount: "admin-sa" in namespace "kube-system"
        ```

        ***

        ## 3. Python Script: Audit and Remediate `cluster-admin` Bindings

        This script:

        * Connects to the cluster using local kubeconfig.
        * Lists all `ClusterRoleBinding` objects.
        * Finds those whose `roleRef.name == "cluster-admin"`.
        * For each such binding:
          * Keeps only **approved subjects**.
          * If no approved subjects remain, deletes the binding.
          * If some remain, updates the binding with a reduced subject list.

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

        # ----------------- CONFIGURE ALLOWED SUBJECTS HERE -----------------
        # Each subject is a dict with kind, name and optional namespace.
        # kind must be one of: "User", "Group", "ServiceAccount".
        ALLOWED_SUBJECTS = [
            # Example allowed Group
            {"kind": "Group", "name": "oke-cluster-admins"},
            # Example allowed ServiceAccount
            {"kind": "ServiceAccount", "name": "admin-sa", "namespace": "kube-system"},
        ]

        # -------------------------------------------------------------------

        def subject_matches_allowed(subject, allowed_subjects):
            """Return True if the Kubernetes Subject matches one of the allowed subjects."""
            for allowed in allowed_subjects:
                if subject.kind != allowed["kind"]:
                    continue
                if subject.name != allowed["name"]:
                    continue
                # ServiceAccount requires namespace match
                if subject.kind == "ServiceAccount":
                    if subject.namespace != allowed.get("namespace"):
                        continue
                return True
            return False


        def main():
            # Load kubeconfig from default location (~/.kube/config)
            config.load_kube_config()

            rbac_api = client.RbacAuthorizationV1Api()

            # List all ClusterRoleBindings
            crbs = rbac_api.list_cluster_role_binding().items

            for crb in crbs:
                if crb.role_ref.kind == "ClusterRole" and crb.role_ref.name == "cluster-admin":
                    print(f"Processing ClusterRoleBinding: {crb.metadata.name}")

                    original_subjects = crb.subjects or []
                    print("  Original subjects:")
                    for s in original_subjects:
                        print(f"    - {s.kind} {s.name}"
                              f"{' (ns=' + s.namespace + ')' if s.kind == 'ServiceAccount' else ''}")

                    # Filter subjects to allowed set only
                    filtered_subjects = [
                        s for s in original_subjects
                        if subject_matches_allowed(s, ALLOWED_SUBJECTS)
                    ]

                    if not filtered_subjects:
                        # No allowed subjects left -> delete the binding
                        print(f"  No allowed subjects remain. Deleting ClusterRoleBinding: {crb.metadata.name}")
                        rbac_api.delete_cluster_role_binding(name=crb.metadata.name)
                    else:
                        # Update the binding with the filtered subjects
                        print(f"  Updating ClusterRoleBinding: {crb.metadata.name}")
                        crb.subjects = filtered_subjects
                        # Use replace to update the resource
                        rbac_api.replace_cluster_role_binding(
                            name=crb.metadata.name,
                            body=crb
                        )

                        print("  New subjects:")
                        for s in filtered_subjects:
                            print(f"    - {s.kind} {s.name}"
                                  f"{' (ns=' + s.namespace + ')' if s.kind == 'ServiceAccount' else ''}")

            print("Remediation complete.")

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

        ***

        ## 4. Run the Script

        ```bash theme={null}
        python restrict_cluster_admin.py
        ```

        Review the output and verify:

        ```bash theme={null}
        kubectl get clusterrolebindings -o yaml | grep -A5 'name: cluster-admin'
        ```

        ***

        ## 5. OCI IAM Side (Optional But Recommended)

        To fully align with the control:

        * Ensure OCI IAM groups mapped to cluster access **do not automatically grant cluster-admin** via `kubeconfig` generation or admission policies.
        * Use more restrictive Kubernetes `ClusterRole` / `Role` bindings for regular dev/ops groups instead of `cluster-admin`.

        If you tell me how you currently map OCI IAM groups to Kubernetes RBAC (e.g., via `kubeconfig` or admission-controller rules), I can provide a Python/OCI-SDK snippet for that side as well.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # Provider configuration for OKE’s Kubernetes API
        # Substitute the kubeconfig or endpoint/cert details for your cluster
        provider "kubernetes" {
          host                   = var.OKE_CLUSTER_ENDPOINT   # e.g. "https://<OKE_API_ENDPOINT>"
          cluster_ca_certificate = base64decode(var.OKE_CLUSTER_CA_CERT) # base64 CA from OKE
          token                  = var.OKE_CLUSTER_BEARER_TOKEN          # short‑lived token or OIDC token
        }

        # Restrict usage of the built‑in cluster-admin ClusterRole
        # Bind it only to explicit “break-glass” subjects, and do not bind it to broad groups.
        resource "kubernetes_cluster_role_binding_v1" "cluster_admin_break_glass" {
          metadata {
            name = "cluster-admin-break-glass"
          }

          role_ref {
            api_group = "rbac.authorization.k8s.io"
            kind      = "ClusterRole"
            name      = "cluster-admin"
          }

          subject {
            kind      = "User"                  # or "Group" / "ServiceAccount" as needed
            name      = "BREAK_GLASS_USER"      # replace with the exact subject name in your IdP/cluster
            api_group = "rbac.authorization.k8s.io"
          }

          # Add additional tightly controlled “break-glass” subjects if absolutely necessary:
          # subject {
          #   kind      = "User"
          #   name      = "SECOND_BREAK_GLASS_USER"
          #   api_group = "rbac.authorization.k8s.io"
          # }
        }

        # Example: regular operators get a scoped role, *not* cluster-admin.
        # Define a limited ClusterRole (or use existing ones like edit/view) and bind that instead.
        resource "kubernetes_cluster_role_v1" "platform_ops_scoped" {
          metadata {
            name = "platform-ops-scoped"
          }

          rule {
            api_groups = [""]
            resources  = ["pods", "services", "configmaps"]
            verbs      = ["get", "list", "watch", "create", "update", "delete"]
          }

          rule {
            api_groups = ["apps"]
            resources  = ["deployments", "statefulsets", "daemonsets"]
            verbs      = ["get", "list", "watch", "create", "update", "delete"]
          }
        }

        resource "kubernetes_cluster_role_binding_v1" "platform_ops_binding" {
          metadata {
            name = "platform-ops-binding"
          }

          role_ref {
            api_group = "rbac.authorization.k8s.io"
            kind      = "ClusterRole"
            name      = kubernetes_cluster_role_v1.platform_ops_scoped.metadata[0].name
          }

          subject {
            kind      = "Group"
            name      = "PLATFORM_OPS_GROUP"    # replace with your normal ops group
            api_group = "rbac.authorization.k8s.io"
          }
        }
        ```

        This change is in-place for the OKE cluster (no cluster replacement), but it will replace or update the ClusterRoleBinding objects if they already exist with a different configuration.

        If you currently have broad `cluster-admin` bindings created outside Terraform (for example, bindings to `system:authenticated` or wide groups), you must either:

        * Import them into Terraform as `kubernetes_cluster_role_binding_v1` resources and then narrow their `subject` blocks, or
        * Remove them manually with `kubectl delete clusterrolebinding NAME` so only the controlled Terraform-managed binding remains.

        Verification: `terraform plan` should show creation or in-place update of `kubernetes_cluster_role_binding_v1.cluster_admin_break_glass` (and any other RBAC objects you added), with `roleRef` targeting `cluster-admin` and only the intended “break-glass” identities listed under `subject`.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
