Repository navigation
egress policy: add an RFC 8693 token exchange source to CredentialHeader - #3334
Open
Max Thompson (thompsonmax) wants to merge 3 commits into
Open
Max Thompson (thompsonmax) wants to merge 3 commits into
Max Thompson (thompsonmax) wants to merge 3 commits into
Conversation
This was referenced Oct 27, 2026
Max Thompson (thompsonmax)
force-pushed
the
token-exchange-api
branch
from
October 27, 2026 21:04
aab5517 to
5b9c715
Compare
Max Thompson (thompsonmax)
marked this pull request as ready for review
November 13, 2026 19:02
A replace_headers entry can now set token_exchange, naming an RFC 8693 token endpoint, an audience, and scopes. The egress gateway will exchange the actor's JWT there and inject the returned access token. ateapi requires token_url to be https with a DNS hostname and no userinfo, query, or fragment. It also rejects a policy unless one of its https rules allows the token_url's host and port, so the endpoint stays within what the policy already allows. EgressPolicyTemplate gets the same check. The gateway does not exchange tokens yet and denies a request that carries a token_exchange header with a 500. Without that case the entry would reach the credential provider with an empty URI. Signed-off-by: Max Thompson <maxthomp@google.com>
TestSecretLikeFieldsAreLabeled flags fields whose names look like credentials. token_exchange holds an endpoint, an audience, and scopes, and token_url can carry no userinfo or query, so neither holds a secret. The token URL check now skips headers that use another source, and the token_url doc names the DNS hostname rule. The http-rule test case now fails on the protocol alone, and the scopes limits have test cases. Signed-off-by: Max Thompson <maxthomp@google.com>
Each token_exchange entry costs a pass over every rule when ateapi checks that an https rule allows its token URL. A policy with thousands of entries could cost seconds of CPU. Reject more than 16, the same bound as one rule's replace_headers, before running the check. Signed-off-by: Max Thompson <maxthomp@google.com>
Max Thompson (thompsonmax)
force-pushed
the
token-exchange-api
branch
from
November 13, 2026 19:32
dd240f9 to
6c3b6d8
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1661.
CredentialHeader.token_exchange(TokenExchangeSource:token_url,audience,scopes) as a third union member, the same way egress policy: add an actor JWT value source to CredentialHeader #1960 addedactor_jwt.token_urlwith a DNS hostname and no userinfo, query, or fragment. It also rejects anEgressPolicyor golden egress policy unless one of itshttpsrules allows thetoken_url's host and port, so the gateway reaches nothing the policy doesn't already allow. The check runs the gateway's own matcher,egresspolicy.CompileandEvaluateRequest.token_exchangeheader with a 500. Without that case, a gateway without--credential-provider-namewould ask its provider for the entry's empty URI.The policy names the endpoint inline, which replaces the per-install provider list #1661 first proposed. A policy can have at most 16
token_exchangeentries, since each costs a pass over every rule at admission. Agentgateway already denies the unknown source with a 403. The user guide still lists two sources; it gets updated with the e2e PR, once the gateway injects the token.Testing: unit tests for validation (policies and templates) and for the gateway's 500 on both legs. Each new case fails without its check. A module-wide
go test -race ./...passes exceptcmd/ateworker-microvm/internal/child, which fails on main on macOS too, and an atelet registry test that timed out under load and passes alone.hack/verify-all.shpasses.AI use: AI-assisted (Claude Code) for code, tests, and docs. I reviewed and tested it.