Enforcing mTLS across Microservices using Istio Service Mesh

Why Zero-Trust Matters in Kubernetes
Relying solely on perimeter security inside a Kubernetes cluster introduces significant risk. Once an attacker bypasses the ingress layer, they can typically move laterally across the flat network with minimal resistance.
A zero-trust model addresses this vulnerability by requiring every internal request to be authenticated, authorized, and encrypted. Istio simplifies this process: it offloads mutual TLS (mTLS) from your application code into Envoy sidecar proxies deployed alongside your pods.
Istio serves as the Certificate Authority (CA), manages automatic certificate rotation, and configures Envoy sidecars to establish encrypted TLS tunnels for all inter-service communication.
---
1. Enabling Strict mTLS Cluster-Wide
By default, Istio operates in PERMISSIVE mode to allow workload migration without disrupting existing plaintext connections. To enforce full encryption, update the configuration to STRICT using a PeerAuthentication policy.
# strict-mtls.yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default-strict-mtls
namespace: istio-system # Applying to istio-system makes it cluster-scoped
spec:
mtls:
mode: STRICT
Breakdown:
kind: PeerAuthentication: Governs how sidecars handle incoming traffic.namespace: istio-system: Applying this policy within Istio's root namespace enforces mTLS globally across the entire service mesh.mode: STRICT: Instructs sidecars to reject any unencrypted HTTP or raw TCP connection. Workloads will accept only connections encrypted with a valid Istio certificate.
---
2. Restricting Access with AuthorizationPolicies
While mTLS handles encryption and authentication (verifying who is issuing the request), access control requires explicit authorization rules (verifying what actions they are permitted to execute).
Istio assigns SPIFFE (Secure Production Identity Framework for Everyone) identities based on Kubernetes ServiceAccounts. You can utilize these identities within an AuthorizationPolicy to secure sensitive endpoints.
# authz-policy-finance.yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-frontend-identity
namespace: finance-app
spec:
selector:
matchLabels:
app: payment-processor # Target workload
action: ALLOW
rules:
- from:
- source:
# Require a valid cryptographically verified SPIFFE ID
principals: ["cluster.local/ns/frontend-app/sa/frontend-service-account"]
to:
- operation:
methods: ["POST"]
paths: ["/api/v1/process-payment"]
Breakdown:
action: ALLOW: When anALLOWrule is defined, Istio defaults to denying all unspecified requests.selector.matchLabels: Applies this security policy specifically to thepayment-processorpod in thefinance-appnamespace.source.principals: Validates the client's identity using its mTLS certificate. In this configuration, only requests originating fromfrontend-service-accountwithin thefrontend-appnamespace are accepted, preventing IP spoofing attempts.operation: Restricts access strictly toPOST /api/v1/process-payment, blocking all other HTTP methods and endpoints.
---
Combining strict mTLS with SPIFFE-based authorization rules delivers robust service-level security without requiring modifications to your application source code.