mTLS Service-to-Service Authentication
Mutual TLS (mTLS) requires both the client and server to present certificates during the TLS handshake. This authenticates both ends of a connection, providing stronger guarantees than one-way TLS where only the server presents a certificate.
mTLS = a secret handshake where BOTH people must prove they know it. Regular TLS is like checking only the bouncer's badge; mTLS means the bouncer checks YOUR badge too.
In service-to-service communication, mTLS ensures: (1) the client is connecting to the real server (server certificate validation — same as regular TLS); (2) the server knows exactly which service is calling it (client certificate validation — the new capability). This eliminates the need for API keys or passwords between services. Service mesh infrastructure (Istio) handles certificate issuance, rotation, and mTLS enforcement transparently — services communicate over what looks like plain HTTP to the application code, while the sidecar handles TLS.
Certificate pinning vs CA-based validation: pinning the specific leaf certificate provides stronger guarantees but makes rotation painful; CA-based validation (trusting certificates signed by your internal CA) is operationally manageable with short-lived certs. SPIFFE SVIDs (X.509 certificates with a SPIFFE ID URI in the Subject Alternative Name) encode service identity in a portable, verifiable format. The SPIFFE ID (spiffe://cluster.local/ns/payments/sa/payment-service) encodes the trust domain, namespace, and service account — Istio AuthorizationPolicies can allow/deny based on the SPIFFE ID of the calling service. Certificate rotation: SVIDs should rotate frequently (every 1 hour) to limit the blast radius of a compromised certificate. SPIRE handles rotation automatically, pushing new SVIDs to workloads before expiry.
In my Kubernetes architecture, Istio injects sidecar proxies and automatically provisions mTLS between all services using SPIFFE/SPIRE workload identity. I apply an Istio PeerAuthentication policy (mode: STRICT) at the mesh level to reject any plaintext inter-service traffic. AuthorizationPolicies then add RBAC: the frontend service is only allowed to call the product catalog and cart services — all other calls are denied by default. This gives us mTLS with zero application code changes and per-service RBAC in Kubernetes config.
Issuing long-lived client certificates (1-year validity) for service-to-service auth. If a certificate is compromised, it remains valid for the remainder of its lifetime. Use certificates with 1-hour TTL and automate rotation — the blast radius of a compromise is bounded to 1 hour.