Skip to content

fix(auth): restore default passthrough of Authorization header to cluster#1084

Merged
manusa merged 1 commit into
containers:mainfrom
nader-ziada:fix-cluster-auth-token
Apr 22, 2026
Merged

fix(auth): restore default passthrough of Authorization header to cluster#1084
manusa merged 1 commit into
containers:mainfrom
nader-ziada:fix-cluster-auth-token

Conversation

@nader-ziada

@nader-ziada nader-ziada commented Apr 21, 2026

Copy link
Copy Markdown
Collaborator

This PR restores the v0.0.60 auth-forwarding behavior that regressed after the Entra ID / OBO work (#953). The Authorization header is always forwarded to the cluster when present and kubeconfig credentials are used as fallback when absent. require_oauth controls only whether the token is mandatory and validated, not whether it is forwarded.

  • Default behavior: The server forwards the Authorization header to the Kubernetes cluster when present, and uses kubeconfig credentials when absent. No configuration is needed for this.

  • require_oauth = true: Makes the Authorization header mandatory and validates the token (expiry, audience, and optionally OIDC signature verification if authorization_url is set). Requests without a valid token are rejected.

  • cluster_auth_mode = "kubeconfig": Forces the server to always use kubeconfig credentials, ignoring any Authorization header. Use this when cluster authentication is managed separately (e.g., via a ServiceAccount).

Notes beyond strict v0.0.60 restoration

  • The HTTP authorization middleware now also extracts the Authorization: Bearer … header into the request context when require_oauth=false. v0.0.60 did not do this in the HTTP layer — it relied solely on the MCP middleware, which left SSE clients + raw tokens broken (SSE transport does not propagate headers via req.GetExtra().Header). This addition is small, additive hardening that makes raw-token forwarding work for SSE clients as well, consistent with the existing require_oauth=true handling of the same transport gap.

  • Manager.Derived() no longer returns the "oauth token required" error when invoked with no Bearer token in context under require_oauth=true; it falls back to kubeconfig instead. In the HTTP flow this path is unreachable (the authorization middleware already returns 401 first), so dependents are unaffected. Restoring this defense-in-depth guard and broadening integration coverage is tracked as a follow-up.

Comment thread pkg/config/config.go Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this message is a little misleading with these changed, maybe we can switch to:
token exchange requires require_oauth=true (token exchange depends on OAuth-validated tokens)

Comment thread pkg/kubernetes/manager.go
…ster

the Authorization header is always forwarded to the cluster when present
and kubeconfig credentials are used as fallback when absent.
require_oauth controls only whether the token is mandatory and validated,
not whether it is forwarded.

Signed-off-by: Nader Ziada <nziada@redhat.com>

@manusa manusa left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thx!

@manusa manusa added this to the 0.1.0 milestone Apr 22, 2026
@manusa
manusa merged commit e3e608c into containers:main Apr 22, 2026
11 checks passed
manusa added a commit to marcnuri-forks/kubernetes-mcp-server that referenced this pull request Apr 22, 2026
…n coverage

Follow-up to containers#1084. Addresses the two items intentionally left out of that PR
to keep the original fix minimal.

- Restore the "oauth token required" error in Manager.Derived() when
  require_oauth=true and no Bearer token is in context. The HTTP middleware
  already rejects token-less requests with 401, so this is defense-in-depth
  for STDIO / internal paths and preserves the operator contract that
  require_oauth=true never silently falls through to kubeconfig credentials.
- Revert the two kubeconfig_derived_test.go cases flipped in containers#1084 back to
  asserting the error.
- Add an SSE counterpart to TestAuthorizationRawPassthrough: the
  require_oauth=false raw-token-to-backend path was only exercised on
  StreamableHTTP, but the middleware-extracts-then-bridges flow is what SSE
  depends on and is new relative to v0.0.60.
- Add TestAuthorizationClusterAuthModeKubeconfigDropsClientToken: locks in
  the stsExchangeTokenInContext clear behavior at the HTTP level (previously
  only covered at the unit level).
- Add two TestClusterAuthMode cases asserting token exchange settings
  (token_exchange_strategy / sts_audience) without require_oauth=true are
  rejected with the reworded "token exchange requires require_oauth=true"
  error.

Mild API-surface note: adds IsRequireOAuth() to the BaseConfig interface via
a new RequireOAuthProvider. In-tree only *StaticConfig satisfies BaseConfig
(RequireOAuth already exists on it); downstream out-of-tree implementers
would need to add the method.

Signed-off-by: Marc Nuri <marc@marcnuri.com>
matzew pushed a commit that referenced this pull request Apr 22, 2026
…n coverage (#1088)

Follow-up to #1084. Addresses the two items intentionally left out of that PR
to keep the original fix minimal.

- Restore the "oauth token required" error in Manager.Derived() when
  require_oauth=true and no Bearer token is in context. The HTTP middleware
  already rejects token-less requests with 401, so this is defense-in-depth
  for STDIO / internal paths and preserves the operator contract that
  require_oauth=true never silently falls through to kubeconfig credentials.
- Revert the two kubeconfig_derived_test.go cases flipped in #1084 back to
  asserting the error.
- Add an SSE counterpart to TestAuthorizationRawPassthrough: the
  require_oauth=false raw-token-to-backend path was only exercised on
  StreamableHTTP, but the middleware-extracts-then-bridges flow is what SSE
  depends on and is new relative to v0.0.60.
- Add TestAuthorizationClusterAuthModeKubeconfigDropsClientToken: locks in
  the stsExchangeTokenInContext clear behavior at the HTTP level (previously
  only covered at the unit level).
- Add two TestClusterAuthMode cases asserting token exchange settings
  (token_exchange_strategy / sts_audience) without require_oauth=true are
  rejected with the reworded "token exchange requires require_oauth=true"
  error.

Mild API-surface note: adds IsRequireOAuth() to the BaseConfig interface via
a new RequireOAuthProvider. In-tree only *StaticConfig satisfies BaseConfig
(RequireOAuth already exists on it); downstream out-of-tree implementers
would need to add the method.

Signed-off-by: Marc Nuri <marc@marcnuri.com>
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.

3 participants