Skip to main content
KBY Technologies Logo
cd ../config-traps
risk/register/etcd-peer-auth-the-flag-nobody-sets-on-2380.html
Kubernetes etcd Securitycritical severityKubernetes

etcd Peer Auth: The Flag Nobody Sets on 2380

Overview

A control-plane node reachable on TCP 2380 can join etcd's Raft quorum as a rogue member with no certificate at all, because peer traffic is often encrypted but never authenticated. Client-side TLS on 2379 does nothing to stop it, and no Kubernetes audit log records the replication.

At a glance

Unsafe setting
peer-client-cert-auth left disabled on the etcd static pod manifest while client-cert-auth is enforced on 2379.
Failure trigger
An attacker with network reach to port 2380 registers a rogue etcd member without presenting any verified certificate.
Blast radius
The rogue member joins the Raft quorum and receives the full replication stream of Secrets and cluster state, invisible to Kubernetes audit logging.
Recommended control
Enforce peer-client-cert-auth=true with CN-restricted peer certificates and firewall port 2380 to a pinned inventory of known etcd node IPs.

Fix commands and configuration

--peer-client-cert-auth=true
--peer-cert-allowed-cn
--peer-trusted-ca-file

The Trap

The --peer-client-cert-auth flag on the etcd static pod manifest, left unset or explicitly false while --client-cert-auth is correctly enforced on port 2379.

The Default State

kubeadm and most manual etcd bootstraps configure --peer-cert-file and --peer-key-file so peer traffic on TCP 2380 is TLS-encrypted, but they frequently stop there. Encryption alone does not require the connecting peer to present a certificate that etcd actually verifies. Without --peer-client-cert-auth=true, etcd will complete a TLS handshake with any node that can reach 2380, self-signed cert or none, because the server never mandates client cert verification on the peer listener. The 2379 client port gets all the attention during hardening reviews; 2380 gets none.

The Blast Radius

An attacker with network reach into the control-plane subnet, via a compromised CNI plugin, a flat VPC peering, or an SSRF pivot from a workload pod, can run etcdctl member add against 2380 and register their own node as a learner. Once it syncs, that rogue member receives the full Raft replication stream: every Secret, every ServiceAccount token, every encryption-at-rest key material object stored in etcd, regardless of what RBAC or --client-cert-auth enforces on 2379. None of this touches the API server’s audit log, because replication happens beneath the apiserver entirely. The rogue member can then force a leader election, inject writes directly into the keyspace, and have those writes reappear as legitimate-looking Kubernetes objects on the next apiserver read, with zero admission control ever invoked.

The Lead Mechanic Fix

Set --peer-client-cert-auth=true on every etcd static pod manifest, add --peer-cert-allowed-cn restricted to the exact CN values used by known etcd nodes, and point --peer-trusted-ca-file at a CA issued solely for peer identities, never reused for client certs. Firewall 2380 to the known etcd node IPs only, then verify continuously with etcdctl member list --write-out=table cross-checked against a pinned node inventory on a scheduled job, alerting on any member ID not present in that baseline.