Skip to main content

More Info:

The kubelet configuration file (typically /etc/kubernetes/kubelet.conf) should be owned by root:root. Incorrect ownership lets unprivileged users read or modify kubelet credentials and bootstrap state.

Risk Level

High

Address

Compliance, Security

Compliance Standards

  • CIS OKE

Triage and Remediation

Remediation

Using Console

In OKE you can’t directly “click a button” in the console to change file ownership inside worker nodes; you have to use the console to push a startup script (cloud‑init) via the node pool configuration so each node fixes it on boot.Below are step‑by‑step instructions to remediate this using only the OCI Console (no manual SSH per node).

1. Identify the kubelet config file path on OKE nodes

On standard OKE managed node images, the kubelet config is typically at:
  • /var/lib/kubelet/config.yaml
    (and sometimes a secondary config at /etc/kubernetes/kubelet.conf)
You should fix ownership for both, to be safe.

2. Prepare a cloud‑init script (user data)

You’ll use a cloud‑init script that runs on each node at startup and enforces ownership and permissions.Example script:
You’ll paste this into the node pool’s “User data” section in the console.

3. Update an existing Node Pool to apply the script

  1. In OCI Console, go to:
    • Developer ServicesKubernetes Clusters (OKE).
  2. Click your cluster.
  3. In the cluster details page, go to Node Pools tab.
  4. Click the node pool you want to fix.
  5. Click Edit (or Update Node Pool Configuration, depending on UI).
  6. Find the Node Metadata / Cloud-Init / User Data (or “Boot volume, Metadata” or similar) section.
  7. In User data, select Plain text and paste the script from step 2.
  8. Save the changes.
This ensures any new/replaced nodes in this pool will automatically set the kubelet config file to root:root and 600 on boot.
Note: Existing running nodes won’t automatically re‑run cloud‑init just because you updated user data. You need to cycle them.

4. Recycle nodes so the script runs

To ensure all current worker nodes pick up the fix:
  1. In the same node pool page, note the Number of nodes.
  2. Option A – Rolling replacement by scaling:
    • Temporarily increase the node count (e.g., from 3 to 4).
    • Wait for the new node(s) to be Active and Ready in the cluster.
    • Then decrease the node count back (e.g., from 4 to 3), which terminates old nodes.
  3. Option B – Delete and let the pool replace nodes (if “Autoscale” or node draining is configured appropriately):
    • From Compute → Instances, filter by the node pool’s compartment and name.
    • Terminate nodes one by one; the node pool will create new ones using the updated user data.
New nodes created after the update will run the script at first boot and fix file ownership.

5. (Optional) Verify via Kubernetes / SSH

If you can SSH (or via bastion) to a node:
Expected:
  • Owner: root
  • Group: root
  • Mode: 600 (or at least not group/world writable or readable)
Example output:

6. Apply this pattern to all Node Pools

Repeat steps 3–4 for every node pool in the cluster (and across clusters) so every worker node is remediated consistently.
Summary via OCI Console:
  • Use Node Pool → Edit → User data to add a small boot script (chown root:root + chmod 600 + systemctl restart kubelet).
  • Recycle/replace nodes through node pool scaling so the new config is enforced cluster‑wide.
You fix this on the worker node OS; the OCI CLI is used to target the instances and run a remote command that corrects file ownership.Below is a minimal, end‑to‑end way using Instance Agent Commands via OCI CLI.

1. Identify the OKE node pool and nodes

If you don’t already have the node pool OCID:
Then get the node pool details to see the worker nodes:
Each node has an associated Compute instance. Get them:
Repeat or use --all and a jmespath query to list all instance OCIDs.

2. Ensure Instance Agent is enabled

On each instance OCID, the Oracle Cloud Agent must be enabled and running (this is the default for OKE images):
"is-management-disabled": false and "is-monitoring-disabled": false is what you want.

3. Run the remediation command via OCI CLI

On OKE worker nodes, kubelet config is typically at:
  • /var/lib/kubelet/config.yaml (most OKE images)
  • or /etc/kubernetes/kubelet.conf (older/custom images)
You can set ownership to root:root for both safely.For each instance:
Notes:
  • The script is run as root by the agent.
  • You can add permissions hardening if desired, e.g.:

4. Verify ownership on each node

Option A – via another instance-agent command:
Retrieve output:
You should see root root as owner and group.Option B – SSH into a node and:

5. Make it persistent for new nodes

For future OKE nodes (new node pools or scale‑out), ensure this is applied automatically, e.g.:
  • Use a custom node image with correct ownership baked in, or
  • Add an OKE node pool cloud‑init script that fixes ownership on boot:
Then attach this via --node-config-details / --node-metadata (cloud-init user-data) when creating the node pool.
In OKE you can’t SSH into every node manually at scale, so the standard pattern is:
  1. Run a privileged DaemonSet that:
    • Mounts the host’s /var/lib/kubelet/config.yaml (or the kubelet config directory).
    • Runs chown root:root and chmod 600 (or whatever you require) on the host file.
  2. Create/apply that DaemonSet using Python (either via kubectl or the Kubernetes Python client).
Below is a minimal, end‑to‑end example using Python and the Kubernetes Python client.

1. Identify kubelet config path on OKE nodes

On OKE node pools today it is typically:
Confirm on one node (via Cloud Shell + ssh into the node, or via an existing debug DaemonSet):
Use that path in the script below.

2. Python script to deploy a DaemonSet that fixes ownership

This script:
  • Connects to your OKE cluster using local kubeconfig.
  • Creates a DaemonSet in kube-system that:
    • Runs privileged.
    • Mounts the host’s /var/lib/kubelet/config.yaml.
    • Executes chown root:root /host/kubelet/config.yaml && chmod 600 /host/kubelet/config.yaml.
After it runs on all nodes once, you can optionally delete the DaemonSet.

3. Verify the remediation

After the DaemonSet pods are Running on all nodes:
When you’re satisfied:

Notes

  • Adjust KUBELET_CONFIG_HOST_PATH if your OKE version uses a different location.
  • If your policy requires different permissions (e.g., 640), change the chmod value in the command.
  • If you prefer, replace the sleep 3600 with sleep infinity or keep the DaemonSet only long enough to fix the files, then delete it.