> ## 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 Kubelet Client Certificates Should Be Auto-Rotated

### More Info:

Setting rotateCertificates to true allows kubelet to automatically renew its client certificate before expiry. Without rotation, expired certs cause node outages and long-lived credentials raise the impact of compromise.

### 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">
        To remediate this in OCI OKE via the Console, you need to enable **Kubelet certificate auto-rotation** on the cluster.

        **Prerequisites**

        * You must be using **VNIC-native Pod networking** (required for kubelet cert rotation in OKE).
        * You need permissions to **update OKE clusters** in the compartment.

        ***

        ### 1. Confirm the Cluster Networking Type

        1. Sign in to the **OCI Console**.
        2. Open the **Navigation Menu** → **Developer Services** → **Kubernetes Clusters (OKE)**.
        3. Select the **Compartment** where your cluster resides.
        4. Click your **Cluster name**.
        5. On the cluster **Details** page, check:
           * **Cluster Type / Networking**:
             * If it shows something like *“Native VCN / VCN-native pods (VNP)”* or similar wording, you’re using VNIC-native Pod networking.
             * If you are on older **Flannel/Overlay** networking, kubelet cert auto-rotation will not be available; you would need to create a new cluster with VCN-native Pod networking and migrate workloads.

        If you confirm the cluster is using VNIC-native Pod networking, proceed.

        ***

        ### 2. Enable Kubelet Client Certificate Auto-Rotation

        1. Still on the **Cluster Details** page for your OKE cluster:
        2. In the top-right corner, click **Edit Cluster** (or **Update Cluster** depending on UI version).
        3. Look for the **Security** or **Kubernetes Configuration** section; the exact wording can vary, but find:
           * **Kubelet client certificate auto-rotation**
           * Or **Enable kubelet certificate rotation**
        4. Check/enable the option:
           * Example: Tick **Enable kubelet client certificate auto-rotation**.
        5. Click **Save changes / Update**.

        The change applies at the **cluster** level; newly created or restarted nodes in the node pools will honor the setting and rotate kubelet client certificates automatically before expiration.

        ***

        ### 3. (If Needed) Cycle Nodes to Pick Up the Setting

        If the setting was just enabled on an existing cluster and node pools:

        1. From the cluster page, go to **Node Pools**.
        2. For each node pool:
           * Option A: **Rolling restart** / **Rolling replace** nodes if the UI provides that.
           * Option B: Manually:
             * **Drain and terminate** nodes one at a time, allowing the node pool to recreate them, so new nodes start with the updated cluster config.
        3. Verify nodes come back to **Active** status and workloads reschedule successfully.

        ***

        ### 4. Validate Kubelet Cert Rotation

        From a workstation with `kubectl` access:

        1. List kubelet certificates on a node (via SSH) or check `kubelet` logs to confirm:
           * Certificates now have a shorter lifetime and are renewed periodically.
        2. Optionally, use `kubectl get csr` (if your OKE version exposes CSRs) to see certificate signing requests being created/approved over time.

        This configuration should clear the “OCI OKE Kubelet Client Certificates Should Be Auto-Rotated” finding.
      </Accordion>

      <Accordion title="Using CLI">
        Below is a CLI‑only way to enable kubelet client certificate auto‑rotation on an OKE cluster.

        > Note: Field names can change slightly between CLI versions. I’ll show you how to *discover* the exact flag via the CLI itself so you’re not guessing.

        ***

        ## 1. Make sure you have a recent OCI CLI

        ```bash theme={null}
        oci -v
        pip install --upgrade oci-cli  # or your platform’s method
        ```

        ***

        ## 2. Discover the cluster options payload structure

        Generate the full JSON skeleton for `update-cluster`:

        ```bash theme={null}
        oci ce cluster update --generate-full-command-json-input > cluster-update.json
        ```

        Open `cluster-update.json` and look for the `options` section. You should see something like:

        ```json theme={null}
        "options": {
          "kubernetesNetworkConfig": { ... },
          "addOns": { ... },
          "admissionControllerOptions": { ... },
          "serviceLbSubnetIds": [],
          "isKubeletCertificateRotationEnabled": false
        }
        ```

        If you don’t see `isKubeletCertificateRotationEnabled`, upgrade the CLI and re‑check; if it uses a different name, use that exact field instead.

        ***

        ## 3. Create a minimal options JSON file

        Create a file `oke-kubelet-rotation-options.json` with only the fields you want to change. For example:

        ```json theme={null}
        {
          "options": {
            "isKubeletCertificateRotationEnabled": true
          }
        }
        ```

        If your existing cluster already uses options like `serviceLbSubnetIds`, `addOns`, etc., include them as well so they don’t get cleared. You can grab the current options from:

        ```bash theme={null}
        oci ce cluster get --cluster-id <cluster_ocid> --query "data.\"options\"" --raw-output > current-options.json
        ```

        Then edit `current-options.json` to set:

        ```json theme={null}
        "isKubeletCertificateRotationEnabled": true
        ```

        and save it as `oke-kubelet-rotation-options.json`.

        ***

        ## 4. Apply the update to the cluster

        ```bash theme={null}
        oci ce cluster update \
          --cluster-id <cluster_ocid> \
          --from-json file://oke-kubelet-rotation-options.json \
          --force \
          --wait-for-state ACTIVE
        ```

        Replace `<cluster_ocid>` with your OKE cluster OCID.

        ***

        ## 5. Verify the setting

        ```bash theme={null}
        oci ce cluster get --cluster-id <cluster_ocid> --query "data.options.isKubeletCertificateRotationEnabled"
        ```

        Should return:

        ```text theme={null}
        true
        ```

        ***

        This enables kubelet client certificate auto‑rotation for that OKE cluster using OCI CLI.
      </Accordion>

      <Accordion title="Using Python">
        In OKE, kubelet client certificate auto-rotation is controlled **per node pool** via the `is_kubelet_certificate_rotation_enabled` flag.\
        To remediate, you need to **enable this on every node pool** in your clusters using the OCI Python SDK.

        Below is a concise step‑by‑step with Python code.

        ***

        ## 1. Prerequisites

        1. Install the OCI Python SDK:

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

        2. Configure OCI credentials (one of):
           * `~/.oci/config` with a profile (e.g. `DEFAULT`), or
           * Instance principal / resource principal (if running on OCI).

        `~/.oci/config` example:

        ```ini theme={null}
        [DEFAULT]
        user=ocid1.user.oc1..aaaa...
        fingerprint=aa:bb:cc:...
        key_file=/path/to/oci_api_key.pem
        tenancy=ocid1.tenancy.oc1..aaaa...
        region=us-ashburn-1
        ```

        ***

        ## 2. Enable kubelet certificate rotation for all node pools in a compartment

        This script:

        * Connects to OKE (Container Engine for Kubernetes).
        * Lists all node pools in a given compartment (optionally filtered by cluster).
        * Updates each node pool to set `is_kubelet_certificate_rotation_enabled=True` if not already set.

        ```python theme={null}
        import oci
        from oci.container_engine import ContainerEngineClient
        from oci.container_engine.models import UpdateNodePoolDetails, NodePoolNodeConfigDetails

        # ---- CONFIG ----
        COMPARTMENT_ID = "ocid1.compartment.oc1..xxxx"  # your compartment OCID
        # Optional: limit to a specific cluster
        CLUSTER_ID_FILTER = None  # or "ocid1.cluster.oc1..xxxx"
        PROFILE = "DEFAULT"       # profile in ~/.oci/config
        # -----------------

        def get_ce_client(profile_name: str = "DEFAULT"):
            config = oci.config.from_file("~/.oci/config", profile_name)
            return ContainerEngineClient(config)

        def main():
            ce_client = get_ce_client(PROFILE)

            # 1. List node pools in the compartment
            list_params = {
                "compartment_id": COMPARTMENT_ID
            }
            if CLUSTER_ID_FILTER:
                list_params["cluster_id"] = CLUSTER_ID_FILTER

            node_pools = oci.pagination.list_call_get_all_results(
                ce_client.list_node_pools,
                **list_params
            ).data

            for np in node_pools:
                print(f"Checking node pool: {np.id} ({np.name})")

                # Some SDK versions expose node_config_details directly; others only via get_node_pool
                # Safest: fetch full node pool details first
                full_np = ce_client.get_node_pool(np.id).data
                node_config = full_np.node_config_details

                # If node_config_details is None, create one to update (rare in modern OKE)
                if node_config is None:
                    node_config = NodePoolNodeConfigDetails()

                current = getattr(node_config, "is_kubelet_certificate_rotation_enabled", None)

                if current is True:
                    print("  - Kubelet cert rotation already enabled, skipping.")
                    continue

                print(f"  - Enabling kubelet cert rotation (current: {current})")

                # 2. Prepare updated node_config_details
                updated_node_config = NodePoolNodeConfigDetails(
                    size=node_config.size,
                    placement_configs=node_config.placement_configs,
                    is_pv_encryption_in_transit_enabled=getattr(
                        node_config, "is_pv_encryption_in_transit_enabled", None
                    ),
                    nsg_ids=node_config.nsg_ids,
                    subnet_ids=node_config.subnet_ids,
                    kms_key_id=getattr(node_config, "kms_key_id", None),
                    freeform_tags=node_config.freeform_tags,
                    defined_tags=node_config.defined_tags,
                    # The important part:
                    is_kubelet_certificate_rotation_enabled=True
                )

                # 3. Build update details - keep other settings unchanged
                update_details = UpdateNodePoolDetails(
                    name=full_np.name,
                    kubernetes_version=full_np.kubernetes_version,
                    node_shape=full_np.node_shape,
                    node_shape_config=full_np.node_shape_config,
                    node_config_details=updated_node_config,
                    initial_node_labels=full_np.initial_node_labels,
                    freeform_tags=full_np.freeform_tags,
                    defined_tags=full_np.defined_tags,
                    node_source_details=full_np.node_source_details
                )

                # 4. Call update_node_pool
                response = ce_client.update_node_pool(
                    node_pool_id=full_np.id,
                    update_node_pool_details=update_details
                )
                work_request_id = response.headers.get("opc-work-request-id")
                print(f"  - Update initiated. Work request: {work_request_id}")

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

        ***

        ## 3. Notes / Operational Considerations

        * **Rolling update:** `update_node_pool` triggers a rolling update of the node pool. Plan for some disruption; ensure PodDisruptionBudgets and replicas are configured.
        * **Per‑node‑pool:** You must run this for each node pool in each cluster that should have rotation enabled.
        * **Idempotent:** Re-running the script is safe; it skips pools where rotation is already enabled.
        * **Validation:** After completion, describe the node pool and confirm `isKubeletCertificateRotationEnabled` shows as `true` in:
          * OCI Console → OKE → Node Pools, or
          * `get_node_pool` via SDK/CLI.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        # As of the current Oracle/OCI Terraform provider, the kubelet
        # `rotateCertificates` setting on OKE node pools is NOT exposed as a
        # Terraform argument on `oci_containerengine_node_pool` or any related
        # resource, so it cannot be managed from Terraform.

        # You must enable kubelet client certificate rotation for the node pool
        # via the OCI Console or OCI CLI instead of Terraform.
        #
        # Console (high level):
        # 1. Go to Developer Services → Kubernetes Clusters (OKE).
        # 2. Open the cluster, then the specific node pool.
        # 3. Edit the node pool configuration and enable kubelet client certificate
        #    auto-rotation (rotateCertificates = true), then save/apply.
        #
        # OCI CLI (high level):
        # Use `oci ce node-pool update` with the appropriate kubelet config payload
        # that sets rotateCertificates=true for the node pool in question.
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
