feat(auth): add Dex OIDC authenticator for A2A endpoint#2056
Closed
QuentinBisson wants to merge 8 commits into
Closed
feat(auth): add Dex OIDC authenticator for A2A endpoint#2056QuentinBisson wants to merge 8 commits into
QuentinBisson wants to merge 8 commits into
Conversation
GET /api/substrate/status returned 500 on clusters without the ate.dev CRDs installed because listSubstrateCRs listed WorkerPool/ActorTemplate unconditionally, propagating the REST mapper NoKindMatchError as a server error. Gate the CRD listing loop on AteClient != nil. When substrate is not configured (the common case), there is nothing to list and no CRD calls are made. When substrate is configured, a missing CRD is a legitimate misconfiguration and the error is surfaced as before. Reported in giantswarm/giantswarm#36845. Signed-off-by: QuentinBisson <quentin@giantswarm.io>
- Merge the two consecutive AteClient != nil blocks into one - Use noMatchKubeClient in the not-configured test so the test would fail if the gate were removed (the error would propagate as 500 rather than the guarded nil path) - Remove extra blank line before stubAteControl Signed-off-by: QuentinBisson <quentin@giantswarm.io>
… NoMatchError CRD presence (WorkerPool/ActorTemplate) and gRPC client availability (AteClient) are independent axes. Gating listSubstrateCRs on AteClient != nil caused two bugs: - CRDs present but ate-api not deployed: WorkerPools/ActorTemplates silently omitted even though the CRs exist, Enabled reported false. - CRDs absent but AteClient set: List calls reached the API server and 500'd instead of degrading gracefully. Guard each KubeClient.List with meta.IsNoMatchError: on NoMatch return empty + found=false with no error. controller-runtime's dynamic RESTMapper reloads on NoMatch automatically, so substrate installed after kagent boots is picked up on the next request without a restart. Compute Enabled from observed reality: crdsPresent || AteClient != nil. Three new cases covered by tests: - NoCRDs + no gRPC client -> 200, Enabled:false - NoCRDs + gRPC client set -> 200, Enabled:true, actors populated - CRDs present + no gRPC -> 200, Enabled:true, WorkerPools populated Signed-off-by: QuentinBisson <quentin@giantswarm.io>
Revert 149a2d7. The IsNoMatchError guard is overcomplicated for this use case. Keeping the original approach (gate CRD listing on AteClient != nil) and will improve with a startup CRD discovery check separately. Signed-off-by: QuentinBisson <quentin@giantswarm.io>
Validate incoming Dex JWTs (sig/iss/aud/exp) via auto-refreshed JWKS cache. Reject unauthenticated A2A requests. Forward the verified Bearer token and resolved user ID to agent pods so the Python ADK session-state headers channel carries the human identity into MCP calls. New --auth-mode=dex-oidc requires --auth-dex-issuer and --auth-dex-client-id. The client ID must also be added to muster's trustedAudiences.
Contributor
Author
|
Wrong approach — kagent already runs behind oauth2-proxy with trusted-proxy mode. The A2A endpoint uses the same path as the UI. No code change needed; the only task is registering the Dex client for the A2A audience. |
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.
What
Adds
--auth-mode=dex-oidcto the kagent controller, implementing full Dex JWT validation (signature via JWKS, issuer, audience, expiry) on the A2A endpoint.Why
The A2A endpoint previously had no real authentication for human callers. The
unsecureandtrusted-proxymodes both accept identity without verifying it. For human-facing A2A sessions driven by a Dex OIDC token (e.g. thegiantswarm-adconnector on glean), the server must validate the token and reject unauthenticated requests.How
DexAuthenticator(go/core/internal/httpserver/auth/dex_authn.go): fetches the OIDC discovery document at{issuer}/.well-known/openid-configuration, registers the JWKS URI in alestrrat-go/jwx/v2auto-refresh cache (15 min default, minimum enforced by httprc), and validates each request's Bearer token against it. User identity defaults to theemailclaim, falling back tosub.UpstreamAuth: forwards the originalAuthorization: Bearer <dex-token>andX-User-Idheaders to agent pods. The Python A2A SDK capturesstate['headers']; kagent's Python executor writes them to ADK session state underHEADERS_STATE_KEY, making the token available tocreate_header_providerfor MCP calls whenallowed_headersincludes"authorization".--auth-dex-issuerand--auth-dex-client-id. Both are required when--auth-mode=dex-oidcis set.Operator note
The Dex client ID passed via
--auth-dex-client-id(e.g.kagent-a2a) must be added to muster'strustedAudiences. Today onlydex-k8s-authenticatoris listed. On glean the human connector isgiantswarm-adand the existing client iskagent.Tests
15 table-driven tests in
dex_authn_test.go(valid token with groups, sub fallback, missing header, non-Bearer, expired, wrong issuer, wrong audience, garbage, upstream forwarding, discovery failure cases). Existingauth_mode_test.goupdated and extended withdex-oidcvalidation cases.