> ## 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 Roles and ClusterRoles Should Avoid Wildcard Use

### More Info:

Wildcards in Kubernetes Roles and ClusterRoles grant unintended permissions and break least-privilege. Replace wildcards with explicit verbs and resources to limit blast radius if a service account or user is compromised.

### 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">
        In OKE this is a Kubernetes RBAC issue, so you fix it inside the cluster (via `kubectl`), not by flipping an OKE setting. You can do all of this from the OCI Console using Cloud Shell.

        ### 1. Open Cloud Shell from the OCI Console

        1. Sign in to OCI Console.
        2. Click the Cloud Shell icon (top-right of the console).
        3. A terminal opens at the bottom of the browser.

        ### 2. Get kubeconfig for the OKE cluster

        1. In the left menu: **Developer Services → Kubernetes Clusters (OKE)**.

        2. Select the correct **Compartment**.

        3. Click your **Cluster**.

        4. Click **Access Cluster**.

        5. Under “Cloud Shell access”, click **Copy** next to the `oci ce cluster create-kubeconfig` command.

        6. Paste it into Cloud Shell and run it, for example:

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

        7. Verify access:

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

        ### 3. Identify Roles and ClusterRoles using wildcards

        Check ClusterRoles:

        ```bash theme={null}
        kubectl get clusterroles -o yaml | grep -n "verbs: \[\\"*\\\"\|resources: \[\\"*\\\"" -n
        ```

        Or list them and inspect one by one:

        ```bash theme={null}
        kubectl get clusterroles
        kubectl get clusterrole <name> -o yaml
        ```

        Check namespace-scoped Roles:

        ```bash theme={null}
        kubectl get roles -A
        kubectl get role <name> -n <namespace> -o yaml
        ```

        Look for rules like:

        ```yaml theme={null}
        rules:
          - apiGroups: ["*"]
            resources: ["*"]
            verbs: ["*"]
        ```

        or any use of `"*"` in `apiGroups`, `resources`, `resourceNames`, or `verbs`.

        ### 4. Plan least-privilege replacements

        For each offending Role/ClusterRole:

        * Replace `resources: ["*"]` with the exact resources needed (e.g. `["pods", "deployments"]`).
        * Replace `verbs: ["*"]` with the minimal verbs (e.g. `["get", "list", "watch"]`).
        * Avoid `apiGroups: ["*"]`; specify actual groups (e.g. `["", "apps"]`).

        Example: From **overly broad**:

        ```yaml theme={null}
        rules:
        - apiGroups: ["*"]
          resources: ["*"]
          verbs: ["*"]
        ```

        To **least-privilege**:

        ```yaml theme={null}
        rules:
        - apiGroups: [""]
          resources: ["pods"]
          verbs: ["get", "list", "watch"]
        - apiGroups: ["apps"]
          resources: ["deployments"]
          verbs: ["get", "list", "watch"]
        ```

        ### 5. Edit the Roles/ClusterRoles

        Use `kubectl edit` in Cloud Shell:

        * ClusterRole:

          ```bash theme={null}
          kubectl edit clusterrole <name>
          ```

        * Role:

          ```bash theme={null}
          kubectl edit role <name> -n <namespace>
          ```

        This opens an editor (usually `vi`); modify the `rules` section to remove `*` and save.

        Or apply updated YAML manifests:

        1. Dump existing definition:

           ```bash theme={null}
           kubectl get clusterrole <name> -o yaml > cr-<name>.yaml
           ```

        2. Edit the file in Cloud Shell:

           ```bash theme={null}
           nano cr-<name>.yaml
           ```

           * Under `rules:`, replace any `"*"` with specific resources/verbs/groups.
           * Ensure you do **not** modify system roles prefixed with `system:` unless you know exactly what you’re doing.

        3. Apply:

           ```bash theme={null}
           kubectl apply -f cr-<name>.yaml
           ```

        Repeat similarly for namespace Roles.

        ### 6. Verify remediation

        Recheck for wildcards:

        ```bash theme={null}
        kubectl get clusterroles -o yaml | grep "\*"
        kubectl get roles -A -o yaml | grep "\*"
        ```

        If nothing returns (or only comments), the wildcard usage is removed.

        ### 7. Additional notes

        * Avoid changing Kubernetes built-in `system:*` roles unless absolutely necessary.
        * If a third-party Helm chart installed broad roles, consider:
          * Overriding its RBAC values to use custom, restricted roles.
          * Reinstalling/upgrading the chart with more restrictive RBAC configuration.
      </Accordion>

      <Accordion title="Using CLI">
        In OKE you can only *reach* the cluster via OCI CLI; the RBAC objects themselves are standard Kubernetes and must be changed with `kubectl`. So the remediation flow is:

        1. use OCI CLI to fetch kubeconfig
        2. use `kubectl` to find Roles/ClusterRoles that use `*`
        3. replace wildcards with explicit verbs/resources and apply

        Below is a minimal, step‑by‑step process.

        ***

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

        ```bash theme={null}
        # Variables
        COMPARTMENT_OCID="<your_compartment_ocid>"
        CLUSTER_OCID="<your_cluster_ocid>"
        KUBECONFIG_FILE="$HOME/.kube/config-oke"

        # Generate kubeconfig for the OKE cluster
        oci ce cluster create-kubeconfig \
          --cluster-id "$CLUSTER_OCID" \
          --file "$KUBECONFIG_FILE" \
          --region <your_region> \
          --token-version 2.0.0 \
          --kube-endpoint PUBLIC_ENDPOINT  # or PRIVATE_ENDPOINT as applicable

        # Point kubectl to this kubeconfig
        export KUBECONFIG="$KUBECONFIG_FILE"
        ```

        ***

        ## 2. Identify Roles and ClusterRoles using wildcards

        ### 2.1 ClusterRoles with wildcards

        ```bash theme={null}
        # Any ClusterRole that has verbs: ["*"]
        kubectl get clusterrole -o json \
          | jq -r '.items[]
            | select(.rules[]? | (.verbs[]? == "*"))
            | .metadata.name'

        # Any ClusterRole that has resources: ["*"]
        kubectl get clusterrole -o json \
          | jq -r '.items[]
            | select(.rules[]? | (.resources[]? == "*"))
            | .metadata.name'

        # Optional: inspect full definition of a specific role
        kubectl get clusterrole <name> -o yaml
        ```

        ### 2.2 Namespaced Roles with wildcards

        ```bash theme={null}
        # All Roles in all namespaces that use verbs: ["*"]
        kubectl get role -A -o json \
          | jq -r '.items[]
            | select(.rules[]? | (.verbs[]? == "*"))
            | "\(.metadata.namespace)/\(.metadata.name)"'

        # All Roles in all namespaces that use resources: ["*"]
        kubectl get role -A -o json \
          | jq -r '.items[]
            | select(.rules[]? | (.resources[]? == "*"))
            | "\(.metadata.namespace)/\(.metadata.name)"'
        ```

        ***

        ## 3. Replace wildcard rules with least‑privilege rules

        For each identified (Cluster)Role:

        1. Export it to a file:
           ```bash theme={null}
           kubectl get clusterrole <name> -o yaml > cr-<name>.yaml
           # or for Role:
           kubectl get role <name> -n <namespace> -o yaml > r-<namespace>-<name>.yaml
           ```

        2. Edit the file and remove wildcards:

           Example BEFORE:

           ```yaml theme={null}
           rules:
             - apiGroups: ["*"]
               resources: ["*"]
               verbs: ["*"]
           ```

           Example AFTER (replace with explicit groups/resources/verbs you actually need):

           ```yaml theme={null}
           rules:
             - apiGroups: [""]
               resources: ["pods", "pods/log"]
               verbs: ["get", "list", "watch"]
             - apiGroups: ["apps"]
               resources: ["deployments"]
               verbs: ["get", "list"]
           ```

           Key principles:

           * Do not use `*` in `verbs`, `resources`, or `apiGroups`.
           * List only the verbs required (`get`, `list`, `watch`, `create`, `update`, `patch`, `delete`, `deletecollection`).
           * List only the resources needed.

        3. Apply the updated role:

           ```bash theme={null}
           kubectl apply -f cr-<name>.yaml
           # or
           kubectl apply -f r-<namespace>-<name>.yaml
           ```

        ***

        ## 4. Verify there are no remaining wildcards

        ```bash theme={null}
        # ClusterRoles
        kubectl get clusterrole -o json \
          | jq -e '.items[]
            | select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*"))' \
          >/dev/null && echo "Still have wildcard ClusterRoles" || echo "No wildcard ClusterRoles"

        # Roles
        kubectl get role -A -o json \
          | jq -e '.items[]
            | select(.rules[]? | (.verbs[]? == "*" or .resources[]? == "*" or .apiGroups[]? == "*"))' \
          >/dev/null && echo "Still have wildcard Roles" || echo "No wildcard Roles"
        ```

        ***

        If you share a sample Role/ClusterRole manifest that currently uses `*`, I can suggest an explicit least‑privilege replacement for that exact case.
      </Accordion>

      <Accordion title="Using Python">
        Below is a practical, Python-based approach to identify and remediate OCI OKE `Role` and `ClusterRole` objects that use wildcard (`"*"`) verbs or resources.

        Assumptions:

        * You have `kubectl` access to the OKE cluster.
        * You can install Python dependencies on a machine that has network access to the cluster.
        * You understand what the correct least-privilege permissions should be (you must decide the replacement for `"*"`).

        ***

        ## 1. Set up Python environment

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

        Ensure your kubeconfig points to the OKE cluster (e.g. from OCI Console, “Access Cluster” > `kubectl` setup).

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

        ***

        ## 2. Connect to the OKE cluster from Python

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

        # Load kubeconfig from default location or explicit path
        config.load_kube_config()  # or config.load_kube_config(config_file="path/to/kubeconfig")

        rbac_api = client.RbacAuthorizationV1Api()
        ```

        ***

        ## 3. Detect Roles and ClusterRoles using wildcards

        ```python theme={null}
        def has_wildcard(rule):
            # Detect if rule has wildcard in verbs, resources or apiGroups
            return (
                any(v == "*" for v in (rule.verbs or [])) or
                any(r == "*" for r in (rule.resources or [])) or
                any(ag == "*" for ag in (rule.api_groups or []))
            )

        def find_wildcard_roles():
            bad_roles = []
            bad_clusterroles = []

            # Namespaced Roles
            roles = rbac_api.list_role_for_all_namespaces().items
            for role in roles:
                bad_rules = [r for r in role.rules or [] if has_wildcard(r)]
                if bad_rules:
                    bad_roles.append((role, bad_rules))

            # ClusterRoles
            clusterroles = rbac_api.list_cluster_role().items
            for cr in clusterroles:
                bad_rules = [r for r in cr.rules or [] if has_wildcard(r)]
                if bad_rules:
                    bad_clusterroles.append((cr, bad_rules))

            return bad_roles, bad_clusterroles

        bad_roles, bad_clusterroles = find_wildcard_roles()

        print("Roles with wildcard rules:")
        for role, rules in bad_roles:
            print(f"  Role: {role.metadata.namespace}/{role.metadata.name}")
        print("ClusterRoles with wildcard rules:")
        for cr, rules in bad_clusterroles:
            print(f"  ClusterRole: {cr.metadata.name}")
        ```

        ***

        ## 4. Define a least-privilege replacement policy

        You must decide how `"*"` should be replaced.\
        Example: convert some typical wildcards to explicit sets.

        ```python theme={null}
        # Example mapping – adjust to your environment and security policy
        VERB_REPLACEMENTS = {
            "*": ["get", "list", "watch"]  # Or full CRUD set: ["get","list","watch","create","update","patch","delete"]
        }

        RESOURCE_REPLACEMENTS = {
            "*": [
                "pods", "pods/log",
                "deployments", "replicasets", "statefulsets",
                "services", "configmaps", "secrets"
                # Add only what is really required
            ]
        }

        API_GROUP_REPLACEMENTS = {
            "*": ["", "apps", "batch"]  # Core group is ""; add only needed groups
        }
        ```

        ***

        ## 5. Function to “de-wildcard” a single rule

        ```python theme={null}
        from copy import deepcopy

        def replace_wildcards_in_rule(rule):
            new_rule = deepcopy(rule)

            # Replace verbs
            new_verbs = []
            for v in rule.verbs or []:
                if v == "*" and "*" in VERB_REPLACEMENTS:
                    new_verbs.extend(VERB_REPLACEMENTS["*"])
                else:
                    new_verbs.append(v)
            new_rule.verbs = list(sorted(set(new_verbs)))

            # Replace resources
            new_resources = []
            for r in rule.resources or []:
                if r == "*" and "*" in RESOURCE_REPLACEMENTS:
                    new_resources.extend(RESOURCE_REPLACEMENTS["*"])
                else:
                    new_resources.append(r)
            new_rule.resources = list(sorted(set(new_resources)))

            # Replace apiGroups
            new_api_groups = []
            for ag in rule.api_groups or []:
                if ag == "*" and "*" in API_GROUP_REPLACEMENTS:
                    new_api_groups.extend(API_GROUP_REPLACEMENTS["*"])
                else:
                    new_api_groups.append(ag)
            new_rule.api_groups = list(sorted(set(new_api_groups)))

            return new_rule
        ```

        ***

        ## 6. Create updated Role / ClusterRole specs without wildcards

        ```python theme={null}
        def sanitize_role(role_obj):
            new_role = deepcopy(role_obj)
            new_rules = []

            for r in role_obj.rules or []:
                if has_wildcard(r):
                    new_rules.append(replace_wildcards_in_rule(r))
                else:
                    new_rules.append(r)

            new_role.rules = new_rules
            return new_role


        def sanitize_clusterrole(cr_obj):
            new_cr = deepcopy(cr_obj)
            new_rules = []

            for r in cr_obj.rules or []:
                if has_wildcard(r):
                    new_rules.append(replace_wildcards_in_rule(r))
                else:
                    new_rules.append(r)

            new_cr.rules = new_rules
            return new_cr
        ```

        ***

        ## 7. Apply the changes back to the cluster

        Use the Kubernetes API `replace_*` methods.\
        Best practice: print a diff or backup yaml before applying.

        ### 7.1 Backup originals to YAML

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

        backup_dir = Path("./rbac-backup")
        backup_dir.mkdir(exist_ok=True)

        def backup_obj(obj, kind):
            ns = getattr(obj.metadata, "namespace", None)
            name = obj.metadata.name
            file_name = f"{kind}_{ns+'_' if ns else ''}{name}.yaml"
            with open(backup_dir / file_name, "w") as f:
                yaml.safe_dump(client.ApiClient().sanitize_for_serialization(obj), f)

        for role, _ in bad_roles:
            backup_obj(role, "Role")

        for cr, _ in bad_clusterroles:
            backup_obj(cr, "ClusterRole")
        ```

        ### 7.2 Replace Roles and ClusterRoles

        ```python theme={null}
        # Sanitize and apply Roles
        for role, _ in bad_roles:
            ns = role.metadata.namespace
            name = role.metadata.name
            updated_role = sanitize_role(role)
            print(f"Updating Role {ns}/{name}")
            rbac_api.replace_namespaced_role(
                name=name,
                namespace=ns,
                body=updated_role
            )

        # Sanitize and apply ClusterRoles
        for cr, _ in bad_clusterroles:
            name = cr.metadata.name
            updated_cr = sanitize_clusterrole(cr)
            print(f"Updating ClusterRole {name}")
            rbac_api.replace_cluster_role(
                name=name,
                body=updated_cr
            )
        ```

        ***

        ## 8. Validate post-remediation

        ```bash theme={null}
        kubectl get roles -A -o yaml | grep -n "\*" || echo "No wildcards in Roles"
        kubectl get clusterroles -o yaml | grep -n "\*" || echo "No wildcards in ClusterRoles"
        ```

        Additionally test workloads and CI/CD pipelines that depend on these RBAC objects to ensure nothing breaks.

        ***

        ## 9. OCI/OKE-specific notes

        * These steps work the same in OKE as in any Kubernetes cluster, because RBAC is Kubernetes-native.
        * If any `ClusterRole`/`Role` is managed by OCI add-ons or Helm charts (e.g. `oci-volume-provisioner`, `oci-cloud-controller-manager`, ingress controller, etc.), update the *chart/manifests* as well, or your changes may be overwritten on upgrade or redeploy.

        ***

        If you share an example of an actual `Role`/`ClusterRole` from your OKE cluster, I can give a concrete “before/after” Python transformation for that object.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # This finding cannot be remediated on the OCI OKE *cluster* resource itself.
        # Kubernetes RBAC (Roles/ClusterRoles) is managed via the Kubernetes API,
        # so you must use the Kubernetes provider (or Helm) rather than
        # `oci_containerengine_cluster` / `oci-containers-oke-cluster`.

        provider "kubernetes" {
          host                   = var.CLUSTER_ENDPOINT          # OKE API server endpoint
          cluster_ca_certificate = base64decode(var.CLUSTER_CA)  # OKE cluster CA cert
          token                  = var.BEARER_TOKEN              # Or use exec/auth-provider as appropriate
        }

        # Example of a Role that previously used wildcards:
        #   verbs = ["*"]
        #   resources = ["*"]
        # Replace wildcards with explicit verbs and resources.

        resource "kubernetes_role" "app_namespace_reader" {
          metadata {
            name      = "APP_ROLE_NAME"        # e.g. "app-namespace-reader"
            namespace = "TARGET_NAMESPACE"     # e.g. "app-namespace"
          }

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

          rule {
            api_groups = [""]
            resources  = ["secrets"]
            verbs      = ["get"]               # no list/watch to reduce exposure
          }
        }

        # Example of a ClusterRole that previously used wildcards:
        #   verbs = ["*"]
        #   resources = ["*"]
        # Again, enumerate exactly what is required.

        resource "kubernetes_cluster_role" "cluster_reader_limited" {
          metadata {
            name = "CLUSTER_ROLE_NAME"         # e.g. "cluster-reader-limited"
          }

          rule {
            api_groups = [""]
            resources  = ["nodes", "pods", "namespaces"]
            verbs      = ["get", "list", "watch"]
          }

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

        # Optionally bind these to service accounts/users instead of
        # any broad existing bindings that assume wildcard permissions.

        resource "kubernetes_role_binding" "app_namespace_reader_bind" {
          metadata {
            name      = "APP_ROLE_BINDING_NAME"  # e.g. "app-namespace-reader-binding"
            namespace = "TARGET_NAMESPACE"
          }

          role_ref {
            api_group = "rbac.authorization.k8s.io"
            kind      = "Role"
            name      = kubernetes_role.app_namespace_reader.metadata[0].name
          }

          subject {
            kind      = "ServiceAccount"
            name      = "TARGET_SERVICE_ACCOUNT" # e.g. "app-sa"
            namespace = "TARGET_NAMESPACE"
          }
        }

        resource "kubernetes_cluster_role_binding" "cluster_reader_limited_bind" {
          metadata {
            name = "CLUSTER_ROLE_BINDING_NAME"   # e.g. "cluster-reader-limited-binding"
          }

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

          subject {
            kind      = "User"
            name      = "TARGET_USER_OR_OIDC_SUBJECT"
            api_group = "rbac.authorization.k8s.io"
          }
        }
        ```

        The `oci_containerengine_cluster` / `oci-containers-oke-cluster` resource has no arguments for Kubernetes Roles or ClusterRoles; RBAC is entirely managed via the Kubernetes API. Update or replace your existing `kubernetes_role` / `kubernetes_cluster_role` resources (or Helm charts) to remove `resources = ["*"]` and `verbs = ["*"]`, enumerating only the specific verbs and resources each principal needs.

        Verification: `terraform plan` should show updates to the affected `kubernetes_role` and/or `kubernetes_cluster_role` resources where `verbs` and `resources` change from `["*"]` to explicit lists, with no changes to the OKE cluster resource itself.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
