KubeCon India 2026 (Mumbai) — Day 2 Deep Dives

Zero Trust for Autonomous Agents — Isolating AI Workloads on Kubernetes

Day 2 · AI serving, gateways & agents · from the uploaded deck

Jun 19, 2026 · conferences · 25 min read · 5400 words advanced

Zero trust for autonomous agents — putting a wall around the robot.

conferences kubecon security zero-trust agents

Senthalan Kanagalingam (Technical Lead, WSO2 — 8+ years in enterprise IAM, now core maintainer of ThunderID) gave the most complete identity-and-isolation story of the day. The premise: an autonomous agent is a coworker that never sleeps, acts in microseconds, and is infinitely eager — and it can reach sub-agents, internal APIs, databases, external SaaS, and LLM providers. Under zero trust, "assume breach" stops being a precaution and becomes a description of an agent. The answer is to wrap each agent in a cell — WSO2's 2018 architecture pattern — with a hard boundary and a single gateway that acts as the policy enforcement point. On Kubernetes the cell is a namespace with default-deny network policy, mesh encryption, and an Envoy/Contour/Kgateway gateway. Then every edge — initiator→agent, agent→LLM, agent→tool, agent→agent — is gated with AuthN, AuthZ, and audit, using token exchange, intersection authorization (the user is the ceiling), CIBA for out-of-band human approval, and one trace ID that joins every hop, even the denials.

This is the security keystone of the Day 2 AI block. It builds directly on Day 1's Keycloak federated auth (DD09) and pairs with the agent-building talks DD10 / DD11 — they build the agent; this one contains it.

The newest coworker — and its reach

The framing was deliberately disarming: meet your newest coworker, an autonomous agent that's helpful, tireless, and self-directed — 0 sleep, microsecond speed, infinitely eager — running the classic observe → reason → act loop. Then the unsettling part: the agent's reach. A single agent can be invoked by users, systems, or other agents, and from there it can call sub-agents, internal systems (MCP servers, APIs, directories, databases, apps), external SaaS (Gmail, Maps, Sheets, Slack, GitHub…), and multiple LLM providers.

Why agents break the usual threat model. A normal microservice does a fixed, code-reviewed set of things. An agent decides at runtime, driven by a model, what to call next — and it has credentials to reach a huge surface. A prompt injection or a confused model isn't a crash; it's an eager, fast, well-connected insider taking actions. That's why the speaker said "assume breach" isn't a worst case for agents — it's the baseline.

Zero trust — the lens

Three principles, applied with an agent twist:

PrincipleMeaning
Verify explicitlyEvery request is authenticated and authorized on its own merits — no free pass for sitting inside the network.
Least privilegeGrant the minimum access needed — nothing more, and only for as long as it's needed.
Assume breachDesign as if the attacker is already in. Contain what any single compromise can reach.

As far as the wall — the cell

If the question is "how far can a compromised agent reach?", the answer should be "as far as the wall." That wall is the cell — a pattern WSO2's Asanka Abeysinghe and Paul Fremantle introduced in 2018: a decentralised way to group components into an independently deployable, immutable unit. Three properties:

  • A hard boundary — components inside are reached only through the cell, never directly.
  • A gateway — all traffic in or out passes one controlled entry point.
  • Bounded by domain — it maps to one business capability (DDD), owned by one team.
cell gateway Agent local tools local agents all traffic in/out passes the gateway cell = one domain, one team (DDD)

Fig 1 — the cell built around the agent: a hard boundary, a single gateway as the controlled entry point, bounded by one business domain.

At enterprise scale, cells compose: an Agent Cell talks to an Other Agent Cell (west-bound) and a Tool Cell (east-bound), takes invocations from users (north-bound), and reaches LLM providers and external systems (south-bound) — all inside an enterprise boundary, and every edge is gated with AuthN · AuthZ · Audit.

The cell in Kubernetes

The pattern maps cleanly onto cloud-native primitives — and this is the part most directly reusable:

Cell conceptKubernetes implementation
The cellA Kubernetes namespace
Hard boundaryNetworkPolicy, default-deny — Cilium, Antrea, or Kube-OVN
ConfidentialityEncrypted traffic — Istio, Cilium, or Linkerd (mTLS)
The gatewayAn ingress/egress gateway as the PEP (policy enforcement point) — Envoy Gateway, Contour, or Kgateway
Default-deny is the load-bearing idea. In a normal cluster, pods can talk to anything by default. Flip that: a NetworkPolicy that denies all traffic, then the only allowed paths are the ones you declared. Now a compromised agent literally cannot open a connection the platform didn't pre-authorise — the blast radius is capped by the network itself, not by the agent behaving. The gateway then becomes the single PEP where identity and policy are checked. (This is the same Cilium/eBPF machinery as Day 2's Zero Trust for Fintech talk.)

Administration — declared up front

The cell only works if its allowances are declarative, set at deploy time, not invented at runtime:

  • Connections declared — allowed paths compile to NetworkPolicy.
  • Permission map per action — the gate never guesses; each action has an explicit permission.
  • Registered in the IDP — the agent has an identity with an owner, an auth mechanism, and a lifecycle kill switch.
  • Policies in the engine — dynamic policy evaluation per request.
  • Secrets stay in the vault — the agent holds references, never the credentials themselves.

Gating every edge

The heart of the talk: each kind of boundary crossing gets its own gating recipe. The agent never holds secrets or makes the trust decision — the gateway does.

Initiator → Agent

  • The gateway trusts an IDP; every request carries a valid token.
  • Real-time authorization — the policy engine decides per request.
  • The token never reaches the agent — the agent gets only a reference token. (So a compromised agent can't replay the real credential.)
  • The gateway can do the OAuth dance, so the agent is security-protocol agnostic.

Agent → AI providers

  • Provider & model allow-list — only approved models, declared at setup.
  • Vault-injected credentials — the agent never holds a standing API key.
  • Usage limits & budgets, plus PII redaction & guardrails — sensitive data filtered at the gate before it leaves to a third-party model.
  • An attributed audit trail — who, which model, what.

Agent → Tool: where the confused deputy dies

This is the cleverest section. When an agent calls a tool on a user's behalf, the danger is the confused deputy: the agent has broad privileges and could be tricked into using them for a user who shouldn't have them. The gating:

  • Allow-list first — not on the agent's list → deny.
  • Token exchange — mint a downscoped token (sub = the user, act = the agent).
  • Intersection authorizationuser ∩ agent ∩ policy. The user is the ceiling.
  • The confused deputy dies here — the check is "does the user have this scope?", not "does the agent?"
  • Authorization failure → escalate — insufficient scope or insufficient consent.
"The user is the ceiling," explained. The agent might be allowed to call the payroll API in general. But on Alice's behalf it can only do what Alice can do — the effective permission is the intersection of what the user can do, what the agent is allowed to do, and what policy permits. Token exchange (RFC 8693) encodes this: the new token's sub is the user and act is the agent, so the tool authorises against the user's rights while keeping a record that the agent acted. That's how you kill the confused-deputy problem instead of hoping the agent behaves.

Human in the loop — user present

When the tool gate answers "need more scope or consent," the challenge flows back to the user, up the same path it came:

  1. Tool gateway returns 403 insufficient_scope.
  2. The challenge propagates back through the agent's gateway (another 403).
  3. The gateway initiates an auth-code flow with the required scope — the gateway drives the screen, not the agent.
  4. The user consents to the IDP; a new token with the added scope is minted; the call replays.

Crucially, the agent only ever hears "blocked → pending → approved" — it never touches the consent flow or the token.

Human in the loop — user away (CIBA)

But agents often run in the background, with the user offline. There's no browser session to step up. The answer is CIBA (Client-Initiated Backchannel Authentication, an OpenID standard for out-of-band approval):

  • The tool gate returns 403 insufficient_scope; the gateway initiates CIBA.
  • A push goes to the user's device — approve / deny / timeout.
  • The gate polls, then decides: approved → new token → retry.
  • Reserved for high-stakes actions only — not every call needs a human.

Agent → Agent: delegation that can only narrow

Agent-to-agent is mostly like agent-to-tool, with token exchange for downscoping and act-chaining. The token carries a nested act claim recording the full delegation chain:

{
  "sub": "alice",
  "act": {
    "sub": "analytics_agent",
    "act": { "sub": "reporting_agent" }
  },
  "scope": "write_report"
}

Two rules make this safe: authority can only narrow, never widen (each hop downscopes), and the ingress gateway performs its own check rather than trusting the caller. So a three-agent chain ends with strictly less authority than it started — and every link is attributable to Alice.

Audit — one cross-boundary sweep

Because every edge passes a gateway, the system is observable by default. The deck's audit stack: collect & enrich with OpenTelemetry, Fluentd, Hubble; metrics & traces with Prometheus, Jaeger, Thanos. The key property:

One trace ID joins both layers — even denials. The same trace ID spans the application calls and the network layer, so a dropped packet (a default-deny block) shows up in the same trace as the request that tried to make it, with full attribution back to the user. You get the forensic chain for what happened and what was prevented — which is exactly what you need when assuming breach. (Compare Day 1's agent observability (DD11): this adds the network/identity layer to the reasoning layer.)

What the pattern buys you

The closing split made the value concrete for two audiences:

Platform engineers — "security you can operate"Developers — "security you don't write"
Policy lives at the platform, not in agent codeNever touch a token or a credential
Blast radius capped by default-denyOn-behalf-of, step-up, CIBA — all from the platform
One kill switch — suspend the identity, tokens dieDeclare tool → action → scope, get authz
One trace — the full forensic chainSwap models — security isn't in the prompt

The one-line thesis: developers build the agent — the platform builds the trust.

Concrete threats → which control catches them

The pattern is easier to trust when you map each defence to the attack it stops. None of these rely on the agent behaving correctly — that's the point.

AttackWhat goes wrongControl that stops it
Prompt injection → exfiltrationA poisoned input convinces the model to POST data to an attacker endpoint.Default-deny NetworkPolicy — the connection isn't on the declared allow-list, so the packet is dropped at the cell wall regardless of what the model "decided."
Confused deputyAgent with broad rights is tricked into acting for a user who lacks them.Token exchange + intersection authz — the tool checks the user's scope (sub=user), not the agent's. User is the ceiling.
Stolen agent credentialAn attacker pops the agent pod and grabs its token.The agent only ever holds a reference token; real tokens live at the gateway, secrets in the vault. Nothing replayable to steal.
Privilege creep via delegationA chain of agents accumulates more authority than any single user granted.Act-chaining where authority can only narrow, plus a fresh ingress check at every hop. The chain ends with strictly less than it started.
Silent over-reachAn agent quietly does something high-stakes nobody approved.CIBA out-of-band approval for high-stakes actions; one trace ID with full attribution makes even denials auditable.
Data leak to a third-party modelPII ends up in a prompt sent to an external LLM provider.PII redaction + guardrails at the agent→AI gate, model allow-list, and an attributed audit trail of who sent what to which model.
Where teams get this wrong. The common failure is putting the security logic in the agent — having the agent check scopes, hold tokens, decide whether to escalate. That collapses the moment the agent is compromised, because the thing enforcing the rules is the thing under attacker control. The whole architecture is built on the opposite assumption: the agent is untrusted, so every decision (authn, authz, redaction, escalation, audit) happens at the gateway/platform, where the agent can't reach it. If you find yourself writing auth code inside the agent, you've left the pattern.

Choosing the pieces

The pattern names categories, not products. The realistic options for each cell primitive:

RoleOptionsHow to choose
Boundary (NetworkPolicy)Cilium, Antrea, Kube-OVNCilium if you also want L7 policy and Hubble flow visibility (and it pairs with the fintech talk's eBPF story); Antrea/Kube-OVN if that's already your CNI.
Confidentiality (mTLS)Istio, Linkerd, Cilium meshLinkerd for the lightest operational weight; Istio if you need its richer policy/telemetry; Cilium mesh to avoid a sidecar entirely.
Gateway / PEPEnvoy Gateway, Contour, KgatewayWhichever you can configure to do the OAuth dance and call your policy engine per request — the PEP role matters more than the brand.
Identity / token exchangeKeycloak, ThunderID, any RFC 8693 IDPMust support token exchange (RFC 8693) and CIBA. This is non-negotiable — the whole intersection-authz story depends on it.

FAQ

What is a "cell" and why use it for agents?

A cell (WSO2, 2018) is an independently deployable unit with a hard boundary and a single gateway — components inside are reachable only through that gateway, and it's bounded by one business domain. For agents it answers "how far can a compromise reach?" with "as far as the wall." On Kubernetes the cell is a namespace with default-deny NetworkPolicy and a gateway acting as the policy enforcement point.

How does this stop the confused-deputy problem?

By intersection authorization with token exchange. When the agent calls a tool for a user, the gateway mints a downscoped token (sub = user, act = agent) and the tool authorises against the user's rights — "the user is the ceiling." The agent's broad privileges can't be borrowed to exceed what the actual user is allowed to do.

What is CIBA and when is it used?

CIBA (Client-Initiated Backchannel Authentication) is an OpenID Connect standard for out-of-band approval. When an agent runs in the background with no user session and hits an insufficient_scope, the gateway pushes an approve/deny prompt to the user's device, polls for the result, and on approval mints a new token and retries. It's reserved for high-stakes actions — not every call needs a human.

Why does the token never reach the agent?

Because the agent is the most likely thing to be compromised (prompt injection, a confused model). The gateway holds the real token and hands the agent only a reference, so a compromised agent can't exfiltrate or replay a live credential. Secrets likewise stay in the vault — the agent holds references, never the keys.

How do agent-to-agent delegation chains stay safe?

Token exchange with a nested act claim records the full chain (e.g. alice → analytics_agent → reporting_agent), authority can only narrow at each hop, and every ingress gateway re-checks rather than trusting the caller. The chain ends with strictly less authority than it began, fully attributable to the original user.

Isn't a gateway in front of every call a performance problem?

It adds a hop, but the work is cheap relative to an agent's actual cost. The expensive part of an agent call is the LLM inference (hundreds of milliseconds to seconds); a token check and policy evaluation at the gateway is sub-millisecond to low-millisecond. The gateway also lets you cache token-exchange results and short-circuit allow-list denials before any network round-trip. The latency budget is dominated by the model, not the PEP.

How is this different from a normal service mesh with mTLS?

A service mesh gives you the transport half — mutual TLS, default-deny, traffic encryption. That's necessary but not sufficient for agents. This pattern adds the identity and intent half: token exchange so calls carry the acting user, intersection authorization so the user is the ceiling, CIBA for human approval, and act-chaining for delegation. The mesh stops an unauthorised connection; the gateway stops an unauthorised action. Agents need both.

Can I retrofit this onto agents already in production?

Mostly yes, because the design deliberately keeps security out of the agent code — so you're adding platform layers, not rewriting agents. The order that usually works: (1) put each agent in its own namespace and flip on default-deny NetworkPolicy; (2) front it with a gateway and move token handling there; (3) register the agent identity in the IDP and pull secrets into a vault (agent holds references); (4) introduce token exchange and intersection authz at the tool gates; (5) wire one trace ID across both layers. Each step shrinks blast radius on its own.

What happens when the IDP or gateway is down?

By design the system fails closed: no valid token or no reachable PEP means the call is denied, not waved through. That's the correct behaviour under "assume breach" — availability of an agent action is less important than not authorising an unverified one. In practice you make the gateway and IDP highly available (they're standard cloud-native components) rather than relaxing the check, and you reserve CIBA/step-up for high-stakes actions so a consent outage doesn't block routine work.

Takeaways

  • For agents, "assume breach" is a description, not a precaution. Fast, eager, broadly-connected, model-driven — contain accordingly.
  • Wrap each agent in a cell — hard boundary + single gateway PEP, mapped to a Kubernetes namespace with default-deny NetworkPolicy and mesh mTLS.
  • Declare everything up front — connections compile to NetworkPolicy, permissions per action, identity in the IDP with a kill switch, secrets in the vault (agent holds references).
  • Gate every edge. Reference tokens to the agent, model allow-lists, token exchange + intersection authz (the user is the ceiling) to kill the confused deputy, CIBA for offline human approval, act-chaining that only narrows.
  • One trace ID joins app and network layers — even denials — so you get full forensic attribution for what happened and what was blocked.
  • Developers build the agent; the platform builds the trust.

Next in Day 2 — Service Networking Within Air-Gapped Environments, on running cloud-native with no internet.

References

← prev: inference observability next: air-gapped networking →
© cvam — written in plaintext, served warm