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
- Remediation
Remediation
Using Console
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
- Sign in to the OCI Console.
- Open the Navigation Menu → Developer Services → Kubernetes Clusters (OKE).
- Select the Compartment where your cluster resides.
- Click your Cluster name.
- 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.
- Cluster Type / Networking:
If you confirm the cluster is using VNIC-native Pod networking, proceed.
2. Enable Kubelet Client Certificate Auto-Rotation
- Still on the Cluster Details page for your OKE cluster:
- In the top-right corner, click Edit Cluster (or Update Cluster depending on UI version).
- 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
- Check/enable the option:
- Example: Tick Enable kubelet client certificate auto-rotation.
- 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:
- From the cluster page, go to Node Pools.
- 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.
- Verify nodes come back to Active status and workloads reschedule successfully.
4. Validate Kubelet Cert Rotation
From a workstation with kubectl access:
- List kubelet certificates on a node (via SSH) or check
kubeletlogs to confirm:- Certificates now have a shorter lifetime and are renewed periodically.
- 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.
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
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:
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:
"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:
{
"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:
oci ce cluster get --cluster-id <cluster_ocid> --query "data.\"options\"" --raw-output > current-options.json
Then edit current-options.json to set:
"isKubeletCertificateRotationEnabled": true
and save it as oke-kubelet-rotation-options.json.
4. Apply the update to the cluster
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
oci ce cluster get --cluster-id <cluster_ocid> --query "data.options.isKubeletCertificateRotationEnabled"
Should return:
true
This enables kubelet client certificate auto‑rotation for that OKE cluster using OCI CLI.
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
- Install the OCI Python SDK:
pip install oci
- Configure OCI credentials (one of):
~/.oci/configwith a profile (e.g.DEFAULT), or- Instance principal / resource principal (if running on OCI).
~/.oci/config example:
[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=Trueif not already set.
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_pooltriggers 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
isKubeletCertificateRotationEnabledshows astruein:- OCI Console → OKE → Node Pools, or
get_node_poolvia SDK/CLI.
Using Terraform
# 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.