Kubernetes orchestrates complex container workloads, but its modular architecture exposes several high-risk attack surfaces if left with default configurations. An exposed kubelet port or an over-privileged service account token can turn a single compromised web container into a cluster-wide takeover.
In this first article of our Kubernetes Hardening & Threat Hunting playlist, we audit the Kubernetes control plane, harden the API server against unauthorized access, and enforce strict RBAC boundaries.
1. Kubernetes Control Plane Attack Surface
The Kubernetes control plane consists of four core components:
kube-apiserver: The central gateway (Port 6443 / 8443).etcd: Key-value data store holding all cluster secrets and configuration state (Port 2379 / 2380).kube-scheduler&kube-controller-manager: Operational control loops.kubelet: Node agent executing pod specifications (Port 10250).
┌──────────────────────────────────────────────────────────┐
│ Kubernetes Control Plane │
│ ┌─────────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ kube-apiserver │ ──│ etcd │ │ Kubelet │ │
│ │ (Port 6443) │ │ (Port 2379) │ │(Port 10250│ │
│ └────────┬────────┘ └──────────────┘ └─────┬─────┘ │
└───────────┼─────────────────────────────────────┼────────┘
│ │
▼ ▼
┌───────────────────────┐ ┌───────────────────────┐
│ Pod (Namespace A) │ │ Pod (Namespace B) │
│ ServiceAccount Token │ │ Container Runtime │
└───────────────────────┘ └───────────────────────┘
2. Hardening kube-apiserver Authentication & Authorization
Disabling Anonymous Authentication
By default, unauthenticated API requests may be treated as system:anonymous. Ensure --anonymous-auth=false is set in /etc/kubernetes/manifests/kube-apiserver.yaml:
spec:
containers:
- command:
- kube-apiserver
- --anonymous-auth=false
- --authorization-mode=Node,RBAC
- --enable-admission-plugins=NodeRestriction,PodSecurity
3. Auditing & Hardening Kubelet Configuration
Unauthenticated access to the kubelet on port 10250 allows remote command execution inside containers (/exec endpoint).
Update /var/lib/kubelet/config.yaml:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false # Disable anonymous kubelet access
webhook:
enabled: true # Require API server token authentication
authorization:
mode: Webhook # Delegate authorization decisions to API server
4. RBAC Auditing & Least-Privilege Role Design
Auditing Risky ClusterRoles
Search for ClusterRoles granting wildcard verbs or sensitive API groups:
# Find ClusterRoles with wildcard permissions
kubectl get clusterroles -o json | jq '.items[] | select(.rules[]? | .verbs[]? == "*") | .metadata.name'
# Find service accounts with cluster-admin binding
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name == "cluster-admin") | .subjects[]'
Disabling Automatic ServiceAccount Token Automounting
Pods that do not need to interact with the Kubernetes API server should never have service account tokens mounted into /var/run/secrets/kubernetes.io/serviceaccount:
apiVersion: v1
kind: Pod
metadata:
name: hardened-app
spec:
automountServiceAccountToken: false # Prevents token theft if pod is exploited
containers:
- name: web
image: nginx:alpine
In Part 2 of this playlist, we implement Zero-Trust Microsegmentation & Falco eBPF Runtime Threat Hunting.
// Discussion