Protecting node metadata and endpoints
Why the metadata endpoint matters
A Pod that can reach 169.254.169.254 can usually fetch the node's cloud
credentials. That is a node compromise from a container, with no exploit
required:
# from inside a pod on a cloud node
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
The Kubernetes-side lever is an egress NetworkPolicy (see the Networks lesson):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: block-metadata, namespace: prod}
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except: ["169.254.169.254/32"]
With IMDSv2 the fix is also an HTTP-token requirement at the cloud level; in the
exam you only have the cluster, so the policy is the answer.
Node endpoints that are open by accident
# on a worker
ss -tulpn | grep -E '10250|10255|10248|10249'
- 10250 kubelet HTTPS API — should require authentication (
--anonymous-auth=false) and authorisation (--authorization-mode=Webhook). - 10255 kubelet read-only port — must be closed (
--read-only-port=0). It serves pod specs and logs with no authentication at all. - 10248 kubelet healthz, 10249 kube-proxy metrics — bind to
127.0.0.1.
# /var/lib/kubelet/config.yaml on the node
authentication:
anonymous:
enabled: false
webhook:
enabled: true
authorization:
mode: Webhook
readOnlyPort: 0
systemctl restart kubelet && systemctl status kubelet --no-pager
curl -sk https://NODE:10255/pods # must now refuse the connection
The dashboard
If a task mentions the Kubernetes Dashboard, the security questions are: is it
exposed publicly, does it have --enable-skip-login, and which token can read
what. A dashboard task is really an RBAC task — bind a restricted ClusterRole
(typically list on a couple of resources) rather than cluster-admin:
kubectl -n kubernetes-dashboard create token dashboard-user
Never leave cluster-admin bound to an automatically mounted service account:
that is a permanent, never-expiring root token sitting in a Secret.
The pattern to remember
"Protect node metadata" = egress NetworkPolicy to 169.254.169.254.
"Protect node endpoints" = **kubelet anonymous-auth off, read-only port off,
bind healthz to localhost, firewall anything that should not be public**.
Both are five-line changes. The exam gives you maybe seven minutes for them.