Implementing Zero Trust with Istio Authorization Policies
Back to blog

Implementing Zero Trust with Istio Authorization Policies

Posted on November 4, 2025 by Matthew McLeod

Service Interaction Diagram

The concept of a secure network perimeter is becoming obsolete. In a modern, cloud-native world, we must adopt a Zero Trust security model, which assumes that threats can exist both inside and outside the network.

The core principle is simple: never trust, always verify.

Istio, a powerful open-source service mesh, provides the tools to implement Zero Trust principles at the service level. Using Istio’s AuthorizationPolicy, you can define fine-grained access control between workloads deciding who can talk to whom, which methods are allowed, and under what identity.

Think of it like the compartmentalized hull of a ship: if one section is breached, watertight doors seal it off to prevent the entire vessel from flooding. In Istio, each service becomes its own compartment, or micro-perimeter.

Scenario Overview

In this walkthrough, you’ll:

  • Start a Minikube cluster with Istio installed,
  • Deploy two BusyBox pods starboard and portside,
  • Apply a default-deny policy,
  • Then explicitly allow only one-way communication from starboard to portside.

This setup models a Zero Trust ship where only one compartment can talk to another through a sealed hatch.

Step 0: Start Minikube

First, start a local Kubernetes cluster with enough resources for Istio:

minikube start

Check that it’s running:

kubectl get nodes

You should see your Minikube node in Ready state.

Step 1: Install Istio

Download and install Istio (v1.22+ recommended):

Install Istio

Install the Istio control plane using the demo profile:

Install Istio Profile

Label the default namespace for automatic sidecar injection:

Enable Sidecar Injection

Step 2: Deploy Two BusyBox Pods

Deploy your “ship compartments” starboard and portside:

Deploy Pods

Expose portside as a service so it has a stable address:

Expose Portside

Verify both are running:

Check Pods

You should see starboard and portside pods up and running.

Step 3: Enforce a Namespace-Wide Default Deny Policy

By default, Istio allows all traffic between workloads. To enforce Zero Trust, we start by denying everything.

Create a file called deny-all.yaml:

deny-all.yaml

Apply it:

Apply Deny Policy

What This Does

  • Applies to all workloads in the default namespace.
  • Since there are no rules, it denies every request by default.
  • This sets your Zero Trust baseline. Nothing talks until explicitly allowed.

You can test it:

Test Deny Policy

Expected output: wget: error getting response: Connection refused

Step 4: Allow Starboard to Communicate with Portside

Now, let’s open one “watertight door”: only the starboard service account can make GET requests to portside.

Create allow-starboard-to-portside.yaml:

allow-starboard-to-portside.yaml

Apply it:

Apply Allow Policy

Step 5: Test Connectivity

Run a request from starboard to portside:

Test GET from Starboard

You should now see a 200 OK response (or an empty connection, but no error).

Now test in the opposite direction (portside to starboard):

Test GET from Portside

Expected output: wget: error getting response: Connection refused

Only one-way access is allowed our “ship compartment” logic is working.

Step 6: Verify the Active Policies

Check which AuthorizationPolicies are active:

Check Policies

Step 7: Clean Up

When you’re done experimenting:

Clean up resources

Key Takeaways

This pattern deny everything, allow by necessity is the foundation of Zero Trust in Istio.

In summary:

  • Start with a namespace-wide default-deny baseline.
  • Add explicit ALLOW policies for legitimate paths.
  • Treat each service as a compartment strong boundaries, minimal trust.

This not only enforces Zero Trust but also builds a clear audit trail of every permitted communication path. Configuration, not hope, becomes your security model.