Skip to main content
Securing a Kubernetes cluster requires layers of protection: access control (RBAC), configuration validation (admission control), and runtime constraints (Pod Security Standards). Equally important is securing pod-to-pod traffic inside the cluster so workloads cannot eavesdrop on or impersonate one another. This document shows how mutual TLS (mTLS) and service-level authorization work together in an Istio service mesh to provide encryption, strong service identity, and service-to-service access control. Why this matters
  • Kubernetes networking is plaintext by default — a compromised pod can sniff traffic on the same node.
  • There is no native service identity, so one pod can pretend to be another.
  • No built-in, identity-based mechanism exists to restrict which services can call which.
Istio + mTLS solves these issues by:
  • Encrypting traffic in transit.
  • Issuing SPIFFE-based identities to workloads.
  • Enabling identity-based authentication and authorization using AuthorizationPolicy.
How Istio implements mTLS Istio’s control plane (istiod) acts as a certificate authority that issues short-lived X.509 certificates to sidecar proxies (Envoy). Each certificate encodes a SPIFFE identity (trust domain, namespace, service account). When Pod A calls Pod B, the local Envoy sidecars perform mutual TLS: they validate each other’s certificate and establish an encrypted connection. Applications keep sending plain HTTP to their local sidecar; all encryption and authentication happen at the sidecar layer, so no application changes are required.
A three-panel diagram titled "How Istio mTLS Works" showing Istiod (control plane) issuing SPIFFE certificates to sidecar proxies and Envoy sidecars at the source and destination. Arrows show the source sidecar intercepts and encrypts outgoing traffic with the pod’s certificate, and the destination sidecar verifies, decrypts, and forwards it to the app.
PeerAuthentication — configuring mTLS mode Istio’s PeerAuthentication resource controls mTLS behavior. The important field is spec.mtls.mode. The common modes are: Example: enable strict mTLS for the payments namespace
Scope and precedence
  • A PeerAuthentication named default in istio-system affects the entire mesh.
  • A default resource in a target namespace affects only that namespace.
  • Adding a selector allows you to scope mTLS to specific workloads (label selector), enabling fine-grained rollout.
If you want to enable strict mTLS for a namespace, create a PeerAuthentication named default in that namespace with mode: STRICT.
A presentation slide titled "PeerAuthentication: Configuring mTLS" that shows examples for mesh-wide, namespace, and workload configurations. It includes labeled boxes explaining where to apply settings (e.g., "Apply in istio-system namespace", "Apply in target namespace") and outcomes like "Entire mesh uses STRICT" and "payments namespace uses STRICT."
AuthorizationPolicy — service-level RBAC PeerAuthentication provides encryption and identity. AuthorizationPolicy uses that identity to allow or deny service-to-service calls. Policies use SPIFFE principals (the identity issued by Istiod) to control which callers are allowed to access a service and which operations they may perform. Example: allow only the web-app service account in the frontend namespace to call the payment-api service, limiting operations to GET and POST under /api/*:
Note: AuthorizationPolicy path-matching syntax can vary across Istio versions. Some control planes accept glob-style patterns like “/api/*”, while others require explicit match types (for example, using a prefix or regex match). If you see validation errors, switch to the explicit match form your Istio version expects (e.g., a prefix or regex-based match).
These two resources together
  • PeerAuthentication guarantees callers present a verifiable SPIFFE identity.
  • AuthorizationPolicy evaluates those identities and enforces fine-grained allow/deny rules.
A presentation slide titled "AuthorizationPolicy: Service-to-Service" explaining that mTLS provides identity which AuthorizationPolicy uses for access control. It warns that without mTLS strict mode pods can fake identities, while SPIFFE certificates prove the caller.
Note: Some Istio versions and examples show SPIFFE IDs with the spiffe:// prefix (for example, spiffe://cluster.local/ns/frontend/sa/web-app). In many AuthorizationPolicy examples the prefix is omitted (cluster.local/ns/frontend/sa/web-app) — both forms are commonly seen, but check your Istio Service Mesh version and use the form that your control plane expects.
How to verify your configuration
  1. Confirm the PeerAuthentication resource exists for the target namespace:
Sample output:
  1. Inspect effective mTLS and policy configuration for a pod with istioctl (replace the pod name):
This command shows which PeerAuthentication and AuthorizationPolicy resources apply to the pod and the effective mTLS mode.
  1. Verify sidecar injection and readiness. A 2/2 READY indicates the application container plus the Envoy sidecar are present:
Sample output:
A 1/1 READY indicates the sidecar is not injected or is unhealthy; mTLS will not be enforced for that pod. Migration pattern (safe rollout)
  • Step 1: Enable automatic sidecar injection on the namespace:
  • Step 2: Start with a PeerAuthentication in PERMISSIVE mode at the appropriate scope so non-mesh workloads can still communicate.
  • Step 3: Monitor traffic and validate sidecar behavior using observability tools like Kiali, istioctl, and application logs.
  • Step 4: When confident, switch the PeerAuthentication to STRICT to reject plaintext connections.
  • Step 5: Add AuthorizationPolicy resources to enforce service-level access control.
We always test before enforcing. Use permissive mode and observability to validate communication and certificate issuance before moving to strict enforcement.
The slide titled "Migrating to STRICT mTLS" outlines a four-step process to enable mutual TLS in Istio. Steps: enable sidecar injection (label namespace istio-injection=enabled), start with PeerAuthentication in PERMISSIVE mode, monitor traffic with Kiali/istioctl to ensure sidecars and mTLS, then switch to STRICT to reject plaintext.
Summary
  • Default cluster traffic is plaintext and vulnerable to eavesdropping and impersonation.
  • Istio mTLS provides transparent encryption plus SPIFFE identities via sidecars and certificates.
  • Control mTLS with the PeerAuthentication resource (spec.mtls.mode): use STRICT for production, PERMISSIVE for migration.
  • Enforce service-to-service access using AuthorizationPolicy based on SPIFFE identities.
  • Verify sidecar injection (2/2 READY) and examine effective policies with istioctl and observability tooling before switching a namespace to STRICT.
Links and references

Watch Video