Key takeaways: The last mile problem is translating a verified zero trust delegation token into credentials that external resources will accept while preserving the permission intersection. This is solved by a credential gateway that validates the token, computes the permission intersection, and translates it into short-lived, service-specific credentials.
In Parts 1 and 2 of this series on implementing zero trust for AI agents on RedHat OpenShift, we built a complete zero trust identity flow: delegation with permission intersection, traceable through nested JWT act claims, authenticated by SPIFFE and token exchange. Every hop is verified, every agent is scoped.
But here’s what kept nagging me during development: all of this works because we control both sides of the conversation. The document-service is our code—it validates our JWTs, queries our policy engine, and enforces our permission model. Real-world agents don’t just talk to services we wrote. They need to read files from S3, fetch code from GitHub, post messages to Slack, query databases. Each of these services has its own authentication mechanism, its own credential format, and its own permission model.
This is the last mile problem: translating a verified zero trust delegation token into credentials that an external service will actually accept, while also preserving the permission intersection.
The credential gateway
The solution is a credential gateway—a service that sits between your zero trust identity layer and external resources. It does three things:
- Validates the incoming JWT and extracts the delegation chain from nested act claims
- Queries the policy engine to compute the permission intersection for the specific target service
- Translates the intersection into service-specific credentials via backend adapters
JWT with ┌─────────────────────────────┐ Service-specific
act claims ──────►│ Credential Gateway │──────► credentials
│ │
│ Validate → OPA → Adapter │
└──────────────┬──────────────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
AWS STS GitHub App Vault/OpenBao
(session (scoped (dynamic DB,
policy) install SSH certs)
token)
The gateway is the only component that holds master credentials (IAM role ARNs, GitHub App keys, database root passwords). Agents never see these—they receive short-lived, scoped credentials that enforce the permission intersection.
What makes this pattern work is that the gateway reuses the infrastructure we already built. JWT validation is the same as in the document service. The OPA query is the same policy engine, extended with service-specific rules. The delegation chain extraction is the same act claim parsing. The only new piece is the adapter that translates the intersection into credentials the target service accepts.
AWS S3: where permission intersection is native
We picked S3 as the first credential gateway target for a specific reason: AWS STS session policies already implement permission intersection natively.
When you call AssumeRole with a session policy, AWS computes:
Effective permissions = IAM role policy ∩ Session policy
This is exactly our model. If the IAM role grants access to finance/* and engineering/*, and the session policy (computed from the agent intersection) only allows engineering/*, the STS session can only access engineering/*. AWS enforces this—not our code.
Here’s the concrete flow when Alice delegates to summarizer-tech to read from S3:
- The agent presents Alice’s delegated JWT to the credential gateway.
- The gateway extracts the chain: Alice →
summarizer-tech. - OPA computes the intersection: Alice’s departments [
engineering, finance] ∩summarizer-tech‘s capabilities [finance, engineering] → [engineering, finance]. - The gateway calls STS
AssumeRolewith an inline session policy scoped to the intersection—onlys3://data/engineering/*ands3://data/finance/*. - The agent receives temporary AWS credentials (access key, secret key, session token) valid for a short window (15 minutes in our demo, configurable up to 12 hours via STS).
- The agent uses these credentials to access S3—any attempt to read outside the scoped prefixes gets an
AccessDeniedfrom AWS itself.
Now consider Carol delegating to summarizer-tech. Carol has [hr], the agent has [finance, engineering]. The intersection is empty—the gateway returns a 403 before ever calling STS. No credentials are issued.
The beauty of this approach is that even if something goes wrong in our code, AWS is the backstop. The session policy is evaluated by AWS on every S3 request. A bug in our gateway can’t grant more access than the session policy allows.
The pattern repeats, the adapters change
S3 was the first step, but the credential gateway architecture is designed to support multiple backends. The pattern is always the same: validate JWT, compute intersection, translate to credentials. Only the adapter changes.
Each service type has a natural fit:
| Target service | Credential mechanism | How intersection is enforced |
|---|---|---|
| AWS S3 | STS session policy | Natively by AWS (implemented) |
| GitHub | App installation token | Scoped to repository subset |
| PostgreSQL | Dynamic user via Vault/OpenBao | Restricted SQL GRANT privileges on specific tables |
| SSH | Signed certificate | Limited principals and hosts |
| Slack | Proxy-based filtering | Gateway filters API calls |
Some of these are cleaner than others. GitHub App installation tokens can be scoped to specific repositories—a direct translation of the permission intersection. Databases can get dynamic, short-lived users with restricted grants, ideally through OpenBao (the open source fork of HashiCorp Vault) which has built-in secrets engines for this. For services like Slack that don’t support fine-grained credential scoping, the gateway acts as a filtering proxy—intercepting API calls and blocking those outside the intersection.
We’re also watching Biscuit tokens as a longer-term option. Biscuit supports attenuation: any token holder can add restrictions but never expand permissions. This maps directly to delegation chains: each hop attenuates the token further, and the permission intersection is cryptographically enforced in the token itself. Adoption is early, but the model is a natural fit.
The key insight from building the S3 adapter: look for services where the permission intersection can be enforced by the target system, not just by your gateway. AWS does this with session policies. The more you can push enforcement to the target, the smaller your trust surface.
Wrapping up the series
The last mile is where zero trust meets the real world. Token exchange gives you verified identity with delegation context. The credential gateway translates that into something each external service understands while preserving the permission intersection that keeps agents scoped to least privilege.
The architectural bet is straightforward: one gateway, one policy engine, many adapters. Start with the services where intersection enforcement is native (like AWS STS), then work outward to services that need proxy-based filtering or dynamic credential generation.
Looking back across all three posts, the pieces compose into a consistent model:
- Part 1 established the principle: agents reduce permissions, never expand them. The permission intersection pattern makes this structural, not aspirational.
- Part 2 wired the identity plumbing: SPIFFE for workload identity, token exchange for delegation context, Kagenti for agent lifecycle. All standards based, all composable.
- Part 3 tackled the last mile: translating zero trust delegation tokens into real-world credentials, starting with AWS S3, where the intersection is enforced natively.
None of these pieces required inventing new protocols or building custom identity systems. SPIFFE, RFC 8693, OPA, STS session policies—they all existed. The work was in composing them into a coherent system where AI agents can operate safely under delegation, with every permission traceable and every credential scoped.
As we add more credential adapters—GitHub, databases, service meshes—we’ll share what we learn.
This post is part of a series on implementing zero trust for AI agents on OpenShift:
- Part 1: Why delegation beats impersonation
- Part 2: Wiring zero trust identity—SPIFFE, token exchange, and Kagenti
- Part 3: The last mile—from Zero Trust tokens to real-world resources
More documentation is available in our zero trust agent demo on GitHub.

