mTLS — identity for both sides

TLS proves the server to the client; mTLS adds a client cert so the proxy has a cryptographic workload identity — a stable name signed by a shared CA — for whoever called it, not just an IP.

Previously

Rate limiting and routing both want to know WHO is calling — but pod IPs change every restart, so the proxy needs a stronger answer to 'who are you' than an IP.

Scene 10

mTLS — identity for both sides

  1. Watch
  2. Try it
  3. Predict
  4. Capture
Control Plane · CAissues short-lived workload certsSIDECAR Aprod/orderenvoy proxyno identitySIDECAR Bprod/checkoutenvoy proxyno identityplaintext · no authIDENTITY POLICYonly prod/order may call prod/checkout✕DENIED · no client identitycannot enforce identity policy on plaintext trafficPlaintext: neither side knows the other's name beyond an IP. The policy cannot be enforced.
What to watch for

The control plane mints a short-lived cert for each sidecar, carrying a workload name — prod/order on the left, prod/checkout on the right. Watch the handshake: A presents its cert, B verifies it, B presents its cert, A verifies. Both sides finish with a cryptographic identity for the other — not an IP.

Continue unlocks when the animation finishes.
Implementation

Highlighted lines are the ones running in the diagram right now.

Sidecar.onBoot
control plane (Istiod) signs a short-lived SVID per workload
def on_sidecar_boot():
# workload name comes from the pod's serviceAccount + namespace
workload_name = spiffe_id(pod.namespace, pod.service_account)
# e.g. spiffe://cluster.local/ns/prod/sa/checkout
csr = generate_csr(workload_name)
svid = control_plane.sign(csr, ttl=24h) # via SDS
install(svid.cert, svid.key)
schedule_renewal(at = svid.expiry - 1h)
Sidecar.onConnect
mutual handshake — each side verifies the other's SVID
def on_connect(peer):
peer.cert = peer.present_cert()
ok = verify_signed_by_ca(peer.cert)
ok = ok and (peer.cert.expiry > now())
if not ok:
close(peer, reason='untrusted')
# SPIFFE ID baked into the cert by the CA
peer.workload_name = peer.cert.spiffe_id
# mutual: the server ALSO presents its cert to the client
present_my_cert(peer)
Policy.evaluate
'X may call Y' needs a cryptographic name for X
def evaluate(req):
caller = req.peer.workload_name # from peer's SVID
callee = self.workload_name
allowed = rules.lookup(caller, callee)
if not allowed:
return DENY # 403
return ALLOW
# TLS gives the client a name for the callee.
# mTLS gives the server a name for the CALLER — the new bit.

Where this sits in Build a Service Mesh (Envoy / Istio style)

Scene 09 of 13. TLS proves the server, mTLS proves both. The control plane mints short-lived certs that carry a stable workload identity — pod IPs are not identities.

Up next. Every workload getting a fresh cert from a shared CA — and every sidecar getting a fresh route table when an operator edits a YAML — implies a central process that hands all this config out live.

All 13 scenes in Build a Service Mesh (Envoy / Istio style) · Every curriculum

Built with Arqly
Every scene in Build a Service Mesh (Envoy / Istio style) builds on the one before it.All 13 Build a Service Mesh (Envoy / Istio style) scenes