Scheduler Pod Specification File Ownership Should Be
More Info:
Verifies that the kube-scheduler pod manifest file is owned by root:root so only privileged users can modify it.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On every control plane node, check the current ownership of the kube-scheduler manifest:
stat -c %U:%G /etc/kubernetes/manifests/kube-scheduler.yaml -
Still on the control plane node, set the file owner and group to root:root:
chown root:root /etc/kubernetes/manifests/kube-scheduler.yaml -
(Optional) Tighten permissions if needed so only root can modify the file:
chmod 600 /etc/kubernetes/manifests/kube-scheduler.yaml -
Verify the ownership is now root:root on the control plane node:
stat -c %U:%G /etc/kubernetes/manifests/kube-scheduler.yaml
Using kubectl
kubectl cannot change file ownership on control plane nodes, so it cannot be used to fix /etc/kubernetes/manifests/kube-scheduler.yaml. This must be corrected directly on each control plane node’s filesystem; see the Manual Steps section for how to do that.
Automation
#!/usr/bin/env bash
#
# Remediation for:
# CISKubernetes 1.1.6 - Ensure kube-scheduler pod specification file ownership is set to root:root
#
# Target: every control plane node
# Usage:
# - Run directly on each control plane node as root, OR
# - From an admin machine with SSH access and key-based auth:
# ./fix-kube_scheduler_ownership.sh node1 node2 ...
# (requires passwordless sudo/root on targets)
set -euo pipefail
SCHEDULER_MANIFEST="/etc/kubernetes/manifests/kube-scheduler.yaml"
fix_local_node() {
echo "==> Checking local node: $(hostname -f || hostname)"
if [ ! -e "$SCHEDULER_MANIFEST" ]; then
echo " [WARN] $SCHEDULER_MANIFEST does not exist on this node. Skipping."
return 0
fi
current_owner="$(stat -c '%U:%G' "$SCHEDULER_MANIFEST")" || {
echo " [ERROR] Failed to stat $SCHEDULER_MANIFEST"
return 1
}
if [ "$current_owner" = "root:root" ]; then
echo " [OK] Ownership already root:root ($current_owner)"
else
echo " [INFO] Current ownership: $current_owner. Changing to root:root..."
chown root:root "$SCHEDULER_MANIFEST"
fi
# Verification
verify_owner="$(stat -c '%U:%G' "$SCHEDULER_MANIFEST")"
if [ "$verify_owner" != "root:root" ]; then
echo " [ERROR] Verification failed. Ownership is $verify_owner, expected root:root"
return 1
fi
echo " [OK] Verified $SCHEDULER_MANIFEST ownership is root:root"
}
fix_remote_node() {
local node="$1"
echo "==> Connecting to control plane node: $node"
ssh "$node" /bin/bash -s << 'EOF'
set -euo pipefail
SCHEDULER_MANIFEST="/etc/kubernetes/manifests/kube-scheduler.yaml"
echo " Node: $(hostname -f || hostname)"
if [ ! -e "$SCHEDULER_MANIFEST" ]; then
echo " [WARN] $SCHEDULER_MANIFEST does not exist on this node. Skipping."
exit 0
fi
current_owner="$(stat -c '%U:%G' "$SCHEDULER_MANIFEST")" || {
echo " [ERROR] Failed to stat $SCHEDULER_MANIFEST"
exit 1
}
if [ "$current_owner" = "root:root" ]; then
echo " [OK] Ownership already root:root ($current_owner)"
else
echo " [INFO] Current ownership: $current_owner. Changing to root:root..."
chown root:root "$SCHEDULER_MANIFEST"
fi
verify_owner="$(stat -c '%U:%G' "$SCHEDULER_MANIFEST")"
if [ "$verify_owner" != "root:root" ]; then
echo " [ERROR] Verification failed. Ownership is $verify_owner, expected root:root"
exit 1
fi
echo " [OK] Verified $SCHEDULER_MANIFEST ownership is root:root"
EOF
}
main() {
if [ "$#" -eq 0 ]; then
# Run locally on this control plane node
fix_local_node
else
# Run via SSH on each specified control plane node
for node in "$@"; do
fix_remote_node "$node"
done
fi
}
main "$@"