Skip to content

feat: --vks-auth passthrough — every VKS call runs as the caller#40

Merged
vks-team merged 5 commits into
mainfrom
feat/user-token-passthrough
Jul 14, 2026
Merged

feat: --vks-auth passthrough — every VKS call runs as the caller#40
vks-team merged 5 commits into
mainfrom
feat/user-token-passthrough

Conversation

@vks-team

Copy link
Copy Markdown
Contributor

What

Per-user VKS access (phase 2). The AgentBase Gateway now forwards the inbound user's IAM bearer token in Authorization (replacing gateway→server auth); with --vks-auth passthrough the server uses that token for every VKS/vServer call — per-user projects, permissions, and results.

Stacked on #38 (needs the kubeconfig/gate changes there). Retarget to main after #38 merges.

Design (as decided in review)

  1. Token arrives in Authorization → incompatible combos fail fast (passthrough+stdio, passthrough+--auth-mode api-key).
  2. No token → 401 + WWW-Authenticate at the middleware; never a silent service-account fallback. A rejected user token raises immediately — no retry under a different identity.
  3. Cache isolation by caller identity (sha256-16 of the token; service otherwise):
    • DiscoveryCache prefixes every key (one choke point covers all 8 discovery tools + cluster locate)
    • K8sClientCache keys (identity, cluster_id) — user A's kubernetes client can never serve user B
    • _require_project_id resolves + caches per (identity, region); a passthrough user never inherits the service account's GRN_PROJECT_ID
  4. IAM user tokens hit VKS/vServer directly (confirmed).

Also

Verification

  • 13 new tests (token propagation, no-fallback-401, identity hashing, middleware ×4, cache isolation ×4, flag validation).
  • Real E2E over streamable-http: tokenless → 401; /health open; a real IAM token in Authorization → initialize (addendum shows PASSTHROUGH) + list_clusters returns data through the forwarded-token path.
  • vks-mcp-server 278, mcp-core 18, lint clean.

Remaining before rollout: one real request through the AgentBase Gateway once deployed (contract measured earlier with --auth-debug).

@vks-team
vks-team changed the base branch from fix/field-test-issues to main July 14, 2026 07:34
tytv2 added 2 commits July 14, 2026 14:35
The AgentBase Gateway now forwards the inbound user's IAM bearer token
in the Authorization header (replacing gateway->server auth). In
passthrough mode the server uses THAT token for every VKS/vServer call
— per-user projects, permissions, and results, instead of the shared
service account.

- mcp-core: user_token_var contextvar (request-scoped, safe under
  concurrency) + current_identity() (short sha256, never the raw
  token). BaseClient sends the user token when set; a rejected user
  token (401) raises immediately and NEVER retries with the service
  account (privilege confusion).
- vks: --vks-auth service-account|passthrough (env GRN_MCP_VKS_AUTH).
  UserTokenPassthroughMiddleware requires a Bearer token on every
  request (401 + WWW-Authenticate otherwise; /health stays open) and
  scopes it to the request context. Fail-fast on nonsensical combos:
  passthrough+stdio, passthrough+--auth-mode api-key (both would fight
  over the Authorization header).
- Cache isolation per caller identity: DiscoveryCache prefixes every
  key; K8sClientCache keys (identity, cluster_id) — user A's kubernetes
  client is never served to user B; _require_project_id resolves and
  caches the project per (identity, region) and never lets a
  passthrough user inherit the service account's GRN_PROJECT_ID.
- Bonus: cluster_locate had no TTL_CONFIG entry since the derive-zone
  work, so it was never actually cached — added (1800s).
- Runtime-mode addendum states the VKS identity (PASSTHROUGH per-user
  vs shared service account); docs drop "per-user is a future phase".

Verified end-to-end over real streamable-http: tokenless request ->
401; real IAM token in Authorization -> initialize + list_clusters
through the forwarded-token code path. 278 + 18 tests.
…ics)

- vks README: GRN_MCP_VKS_AUTH in the env table, an HTTP-transport example,
  and an "Upstream VKS identity" section separating inbound auth (who may
  call the server) from upstream identity (whose credentials hit VKS).
- vks CLAUDE.md: passthrough example in the server-flags block.
- mcp-core README: http module row notes user_token_var/current_identity.
@vks-team
vks-team force-pushed the feat/user-token-passthrough branch from 90c53d0 to 1b28bcf Compare July 14, 2026 07:36
tytv2 added 3 commits July 14, 2026 16:09
…ount, else 401

Simplification decided in review: the AgentBase Gateway forwards the
caller's IAM token in Authorization, so the server needs exactly one
rule, no flags:

1. Request carries a Bearer token -> every VKS/vServer call runs as
   THAT caller (per-user projects/permissions; a rejected user token is
   surfaced, never retried as the service account; caches isolated per
   caller identity).
2. No token, service-account credentials configured (~/.greenode or
   GRN_CLIENT_ID/GRN_CLIENT_SECRET) -> the shared service account.
3. Neither -> 401 + WWW-Authenticate.

Removed: --auth-mode (none/api-key/jwt), --api-key, the five --jwt-*/
--resource-url flags, BearerTokenMiddleware, the auth_verifier module
(+ its tests), --vks-auth/GRN_MCP_VKS_AUTH, GRN_MCP_API_KEY and
GRN_MCP_JWT_* env vars. Kept: --auth-debug diagnostics.

New: the server boots credential-less on the HTTP transport
(passthrough-only deployments behind the Gateway; boot note printed);
stdio without credentials fails fast with a clear message. The
runtime-mode addendum describes the per-request identity. Docs rewritten
around the single behavior.

BREAKING CHANGE: --auth-mode/--api-key/--jwt-* CLI flags and the
GRN_MCP_API_KEY/GRN_MCP_JWT_*/GRN_MCP_VKS_AUTH env vars are gone;
deployments using api-key/jwt inbound auth must drop those settings.

Verified E2E over streamable-http: with token (per-user path), without
token (service-account fallback), and credential-less boot -> 401.
@vks-team
vks-team merged commit 7e700f1 into main Jul 14, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant