Per-Agent Identity in the Mesh
For the Mitrity Mesh Authorizer to apply a specific agent's policy to a request, it has to know which agent made it. Inside the mesh, a workload's identity is its Kubernetes namespace + ServiceAccount, presented as a verifiable SPIFFE identity over mutual TLS. This page covers how you bind a MITRITY agent to that mesh identity, how the Authorizer resolves it, and the two rules that keep it safe: STRICT mTLS is mandatory, and unmapped identities are denied by default.
The resolution chain
When a governed request reaches the Authorizer, it resolves the caller from the bottom up:
Workload runs as namespace + ServiceAccount
│ Istio mTLS
▼
SPIFFE source.principal
spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>
│ (namespace + ServiceAccount → bound agent)
▼
MITRITY agent
│
▼
that agent's mission profile + policy → allow / deny / inject credentials
The link in the middle -- mapping the namespace and ServiceAccount to a MITRITY agent -- is the binding you create in the dashboard. Once it exists, the Authorizer applies exactly that agent's policy to its mesh traffic, the same way Mitrity Gateway and Mitrity MCP Sidecar apply it for that agent's MCP traffic.
The mesh trust domain is a property of your environment, not of the individual agent -- you do not set it per agent. You bind only the namespace and the ServiceAccount.
Binding an agent to a namespace + ServiceAccount
You set an agent's mesh identity when you create the agent, or edit it later -- both forms have a Mesh Identity section with two fields:
| Field | What to enter | Format |
|---|---|---|
| Namespace | The Kubernetes namespace the agent's workload runs in (e.g. payments) | DNS-1123 label -- lowercase letters, digits, and hyphens; must start and end with an alphanumeric; 63 chars max |
| ServiceAccount | The Kubernetes ServiceAccount the workload runs as (e.g. checkout-bot) | DNS-1123 subdomain -- lowercase letters, digits, hyphens, and dots; 253 chars max |
Together, namespace + ServiceAccount uniquely identifies one workload identity in the mesh. The granularity is intentionally namespace + ServiceAccount (not the ServiceAccount name alone) so that the same ServiceAccount name in two different namespaces never collides.
Both fields, or neither
Mesh identity is optional -- an agent that is not part of a service mesh leaves both fields empty (it shows as Not mesh-bound on the agent's detail page). But if you set one, you must set the other: a half-filled binding can never resolve a SPIFFE identity, so the form rejects setting only the namespace or only the ServiceAccount.
To bind an agent
- Go to Agents, then either Register Agent (for a new agent) or open an existing agent and choose Edit.
- In the Mesh Identity section, enter the workload's Namespace and ServiceAccount.
- Save. The agent's detail page now shows its mesh identity as
namespace/ServiceAccount.
The binding is pushed to the Mesh Authorizer with the agent's mission profile, so the Authorizer can resolve namespace + ServiceAccount → agent locally on the request path -- there is no extra lookup per request.
One mesh identity per agent. Each agent binds to a single
namespace + ServiceAccount, and eachnamespace + ServiceAccountmaps to a single agent within a tenant. If two workloads need different policies, give them different ServiceAccounts and bind each to its own agent.
STRICT mTLS is required
Envoy only populates the caller's SPIFFE identity (source.principal) when the request arrived over mutual TLS. Without it, there is no identity to resolve:
- Under STRICT mTLS, every governed request carries the caller's verified SPIFFE identity. The Authorizer resolves it to the bound agent and applies that agent's policy.
- Under PERMISSIVE mTLS or plaintext, the SPIFFE identity is empty. With no identity, the Authorizer cannot govern the request against any declared mission, so it fails closed (deny).
This is why STRICT mTLS is mandatory for every governed namespace -- not a recommendation. The chart pins STRICT on the governed namespace by default. If every request is being denied, an empty identity from missing STRICT mTLS is the most common cause -- confirm STRICT is in force. See Deploy in Istio for how the chart sets this and how to verify it.
Unmapped identity is denied by default
A request can arrive with a perfectly valid SPIFFE identity that simply does not match any bound agent -- for example, a workload running in a governed namespace whose ServiceAccount you have not bound to an agent yet. The Authorizer denies these by default.
The reasoning is fail-safe: if a request reached the Authorizer at all, it is inside a governed selector, which means you intended to govern it. An identity the platform cannot map to an agent is an identity it cannot evaluate against a declared mission -- so the secure default is to deny rather than silently allow.
- Default -- deny on unmapped identity. Use this in production. Any workload in a governed namespace must be bound to an agent (or excluded from the governed selector) before its traffic will be allowed.
- Permissive rollout (opt-in). During a phased migration you can switch the Authorizer to allow resolved-but-unmapped identities so you can bind agents incrementally without blocking unbound workloads. Treat this as a temporary escape hatch and return to deny for production.
A missing identity (no mTLS) always fails closed regardless of this setting -- the deny-on-unmapped behavior is specifically about a valid identity that does not resolve to a bound agent.
Agent-to-agent delegation chains
When one bound agent calls another inside the mesh (an agent-to-agent, or A2A, hop), the Authorizer additionally evaluates the delegation chain -- the path of agents that handed off to one another -- for cycles, excessive depth, and privilege escalation. That evaluation depends on the delegation-chain identifier propagating across the hop in the x-mitrity-delegation-chain-id request header.
If an A2A hop drops that header, the Authorizer treats it as a downgrade-bypass attempt -- it can no longer reason about the chain -- and fails closed (deny). Make sure your agents propagate the x-mitrity-delegation-chain-id header on calls to other agents so legitimate delegation chains are evaluated and allowed. See Delegation Chains for the chain model.
Related Documentation
- Mesh Enforcement (Istio) -- the concept and identity model
- Deploy in Istio -- install, STRICT mTLS, and scoping
- Mesh Egress Allowlist -- the opt-in egress allowlist for outbound traffic
- Delegation Chains -- agent-to-agent delegation-chain governance
- Core Concepts -- agents, mission profiles, and policies