---
title: "Zero-Trust for microservices, a practical blueprint"
description: "Learn how to implement a Zero-Trust security model for microservices. Discover how to secure service-to-service communication, manage workload identities, and enforce fine-grained authorization across distributed systems, AI agents, and APIs."
author: "Alex Olivier"
date: "2025-10-17T13:56:05.424Z"
canonical: "https://www.cerbos.dev/blog/zero-trust-for-microservices"
image: "https://stylish-appliance-1c1cc1c30d.media.strapiapp.com/Zero_Trust_for_microservices_a_practical_blueprint_8e7a56ff02.png"
tags: ["guide","engineering"]
source: "https://www.cerbos.dev/blog/zero-trust-for-microservices"
---

# Zero-Trust for microservices, a practical blueprint

Modern application development has embraced distributed systems. Microservices, serverless functions, and now, increasingly, AI agents, all communicate with each other to deliver powerful user experiences. However, this complexity creates a challenge: how do you control what these services and agents are allowed to do?

Traditional authorization has focused on the user. But in a distributed world, we need to answer a more complex question: "Is **Service A** allowed to access **Resource X** on behalf of **User Y**?"

This is where a decoupled authorization system becomes essential. Let's explore how to move from a vulnerable, perimeter-based security model to a granular, zero-trust architecture using [Cerbos](https://www.cerbos.dev/product-cerbos-hub).

<p>&nbsp;</p>

## The problem: The wild west of workload identity

In many architectures, once a request is inside the network perimeter, it's trusted. An `orders` service can freely call a `payments` service, which can call a `users` service. This "Wild West" approach is a significant security risk. If a single service is compromised, an attacker can move laterally across your entire system.

The first step to securing this is establishing **workload identity**. Just like users, every service, bot, or automated process needs a unique, verifiable identity. An [Identity Provider (IdP)](https://www.cerbos.dev/blog/authentication-vs-authorization) can issue credentials, often in the form of JSON Web Tokens (JWTs), for each workload.

With identities in place, we can now enforce authorization. This is where Cerbos, a decoupled authorization layer, comes in.

### Example: A basic workload policy

With Cerbos, you can write a simple, human-readable policy to control which services can communicate. This policy ensures only the `employee-service` can read `review` resources, creating workload isolation.

```
# Filename: policies/review.yml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: "default"
  resource: "review"
  rules:
    - actions: ["read"]
      effect: EFFECT_ALLOW
      # This policy only applies to principals with the "employee-service" role
      roles:
        - "employee-service"
```

<p>&nbsp;</p>

## On-behalf-of authorization: Merging identities

True zero-trust requires verifying access at every step. We need to check the permissions of both the service making the call and the end-user who initiated the request.

This is the "on-behalf-of" authorization model. The calling service presents two credentials:

1. **Its own workload JWT.**  
2. **The original user's JWT.**

Cerbos can then make a fine-grained decision based on the combined identity context. For example, a policy can state:

* **ALLOW** a request if:  
  * The principal is the `employee-service` (verified via its workload JWT).  
  * **AND** the request is on behalf of a user with the `hr` role (verified via the user's JWT).

This ensures that even a valid service can't perform actions outside the scope of the user it's representing. This logic is encapsulated in a simple, human-readable Cerbos policy, completely separate from your application code.

### Example: An on-behalf-of policy

In this scenario, a manager should only see reviews of employees in their own department. The `employee-service` passes the user's details inside its own principal attributes. Cerbos can inspect this nested context to make a granular decision.

```
# Filename: policies/review.yml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: "default"
  resource: "review"
  rules:
    # Rule for managers to read reviews within their department
    - actions: ["read"]
      effect: EFFECT_ALLOW
      derivedRoles:
        - manager_in_department
      condition:
        match:
          # Check the department of the user in the "act" attribute against the review's department
          expr: "request.principal.attr.act.user.attr.department == request.resource.attr.department"

    # Rule for HR to read any review
    - actions: ["read"]
      effect: EFFECT_ALLOW
      derivedRoles:
        - hr_user
```

<p>&nbsp;</p>

## The next frontier: Governing AI agents

AI agents are the next evolution of workloads. They are autonomous, powerful, and need to be treated as untrusted actors. Granting an AI agent broad permissions to your APIs and data is a recipe for disaster.

The solution is to apply the same zero-trust framework. An AI agent is just another identity to be managed and authorized.

1. **Identity:** The AI Agent gets its own unique workload identity from the IdP, just like any other service. Its token might contain specific attributes, like `principal.type: "AI_AGENT"`.  
2. **Policy:** We write a highly restrictive Cerbos policy for the AI, enforcing the Principle of Least Privilege.

### Example: A policy for an AI agent

For an AI agent that generates HR reports, the policy can be highly restrictive. This example allows the agent to perform only a single, custom action (`read:aggregate`) and explicitly denies everything else, preventing it from reading raw records or performing any other action.

```
# Filename: policies/hr_report.yml
apiVersion: api.cerbos.dev/v1
resourcePolicy:
  version: "default"
  resource: "hr_report"
  rules:
    - actions: ["read:aggregate"]
      effect: EFFECT_ALLOW
      # This policy only applies to the specific AI agent roles
      roles:
        - "ai-reporting-agent"
```

<p>&nbsp;</p>

## Visibility and observability

A major challenge in microservices is understanding access flows. When a request fails, is it a bug, a network issue, or an authorization failure?

Cerbos provides clear visibility through two key mechanisms:

**Centralized policy & audit.** Cerbos offers a single source of truth for all authorization logic. The detailed [audit logs](https://www.cerbos.dev/features-benefits-and-use-cases/audit-logs) capture every decision, showing who (or what) was granted or denied access, to what resource, and which policy was responsible. This is crucial for compliance and security investigations.  

![Centralized policy & audit.png](https://stylish-appliance-1c1cc1c30d.media.strapiapp.com/Centralized_policy_and_audit_f1ed9f2154.png)

**Observability with OpenTelemetry.** Cerbos has native support for [OpenTelemetry](https://www.cerbos.dev/blog/transition-to-open-telemetry-enhanced-policy-testing-and-more-cerbos-v-0-32). This means authorization checks appear as spans in your distributed traces. In tools like Jaeger or Datadog, you can see the exact Cerbos policy evaluation as part of the overall request lifecycle, making it easy for operations and development teams to understand access flows and debug issues.  

![Observability with OpenTelemetry.png](https://stylish-appliance-1c1cc1c30d.media.strapiapp.com/Observability_with_Open_Telemetry_95dc8550c2.png)

By moving authorization logic into a dedicated, decoupled service like Cerbos, you can implement a true zero-trust model that scales with your architecture. This enables you to focus on building features, secure in the knowledge that you have granular, context-aware control over every user, service, and AI agent in your system.

*If you’re transitioning from a monolithic architecture to microservices, feel free to check out our ebook “[Monolith to microservices migration: 10 critical challenges to consider](https://solutions.cerbos.dev/monolith-to-microservices-migration-ebook)” to guide your migration.*

<p>&nbsp;</p>

## TL;DR:

Zero Trust for microservices is a security framework that assumes no user, service, or workload is inherently trustworthy. Every request must be verified and authorized, regardless of its origin. In a microservices architecture, this means applying fine-grained, context-aware controls between every service interaction. Instead of relying on a network perimeter, each call between services, APIs, or AI agents is explicitly authenticated and authorized in real time. With [Cerbos](https://www.cerbos.dev/product-cerbos-hub), this principle becomes practical: identity and authorization are decoupled from application code, enabling consistent, auditable policy enforcement across a distributed system.

## FAQ

### What is the fastest way to add Zero-Trust authorization to Kubernetes microservices?

The fastest way to add Zero-Trust authorization to Kubernetes microservices is to assign workload identities to every service and deploy a local Cerbos policy decision point (sidecar or host-local) next to each one. Use SPIFFE/SPIRE or your IdP to issue JWTs for workloads, keep policies in Git, apply a deny-by-default approach, and automate deployments via CI/CD. Handle coarse-grained authorization at the API gateway and enforce fine-grained rules within each service.

### Which authorization engines work well for Zero-Trust in microservices?

The best engines for Zero-Trust in microservices are decoupled, policy-as-code systems that externalize authorization from application code.

**Cerbos** offers human-readable YAML policies, excellent for workload and on-behalf-of user checks, and provides detailed audit trails.

### How can I secure service-to-service communication in a microservices architecture without adding high latency?

To secure service-to-service calls without increasing latency, use mTLS for service authentication and pass workload JWTs to prove identity. When acting on behalf of a user, include both the workload JWT and the user JWT. Deploy Cerbos locally (as a sidecar or node-local PDP) and enable caching for fast, low-latency decisions. Store commonly used attributes, like user roles or departments, near the decision point to eliminate remote lookups.

### Can a Zero-Trust policy engine such as Cerbos support 10M+ requests per day and 10k+ microservices while keeping p95 latency under 50 ms?

Yes, Cerbos can scale to millions of requests per day and thousands of microservices if deployed correctly. Run the policy decision point close to each service (sidecar or host-local) to minimize network overhead, keep policies and attributes in memory, and push incremental updates instead of full reloads. Most latency typically comes from network and data access, not from Cerbos policy evaluation itself.

### How should AI agents be governed when they call microservice APIs?

AI agents should be governed under the same Zero-Trust principles as other workloads. Assign each AI agent a unique identity and restrict its permissions using a specific, minimal Cerbos policy (for example, allow only the read:aggregate action on a single resource). Deny all other actions by default, log every access decision, and expand privileges gradually based on proven needs.

### How do I implement on-behalf-of authorization for user-initiated requests crossing multiple services?

To implement on-behalf-of authorization, forward two credentials with each request: the calling service’s workload JWT and the end user’s JWT. Cerbos evaluates both identities together to verify that the service is authorized to act on behalf of that user. This ensures that permissions are scoped correctly, prevents lateral movement, and provides complete audit visibility at every hop.

### What components make up a Zero-Trust microservices stack?

A complete Zero-Trust microservices stack includes:

* **Identity:** SPIFFE/SPIRE for workloads, OIDC/OAuth2 for user identities.

* **Authorization:** A decoupled policy engine (Cerbos) for fine-grained, context-aware decisions.

* **Gateway/Mesh:** Envoy, Istio, or Kong for mTLS, token forwarding, and coarse-grained guards.

* **Secrets:** Vault or Secrets Manager for credential and key management.

* **Observability:** OpenTelemetry with Jaeger or Datadog for tracing and auditing authorization flows.

### How can I avoid vendor lock-in for microservices authorization?

To avoid vendor lock-in, use open standards and self-hostable policy engines. Adopt JWT/OIDC for user tokens, SPIFFE for workload identities, and policy-as-code authorization solutions like Cerbos that can run anywhere. Store policies in Git, deploy via CI/CD pipelines, and keep the decision point independent from your application code so you can switch engines without major rewrites.
