Skip to content

Add ext.cattle.io/v1 token support - #632

Merged
pmatseykanets merged 10 commits into
rancher:mainfrom
pmatseykanets:ext-cattle-token-support
Aug 5, 2026
Merged

Add ext.cattle.io/v1 token support#632
pmatseykanets merged 10 commits into
rancher:mainfrom
pmatseykanets:ext-cattle-token-support

Conversation

@pmatseykanets

@pmatseykanets pmatseykanets commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Issue: rancher/rancher#55988

Problem

Rancher will migrate session tokens from management.cattle.io/v3 to ext.cattle.io/v1. When this lands, /v1-public/login will begin returning ext.cattle.io/v1 Token objects. Current CLI versions parse the login response as a v3.Token and would fail to extract the bearer from an ext.Token-shaped response.

The kubectl command also looks up the current user and validates the kubeconfig token via the v3.Token API only, so looking up an ext.Token would return 404 and stale-kubeconfig detection would surface the error instead of regenerating the config.

Solution

Accept both response shapes from /v1-public/login and route token lookups through v3 with an ext.cattle.io/v1 fallback.

  • A parser detects v3 vs ext.cattle.io/v1 response shape via apiVersion and kind, then unmarshals into a single internal type.
  • Basic and OAuth login paths return that shared type.
  • User-id resolution and token validation try v3 first and fall back to the ext.cattle.io/v1. Tokens whose id carries the ext/ prefix skip the v3 attempt.
  • The kubectl subcommand uses the new lookup helpers.
  • 401 and 403 from the ext.cattle.io/v1 API are treated the same as 404 so kubeconfig regeneration still runs for v3-tokened users whose credentials the ext authenticator does not accept.

The SAML login path is unchanged. The SamlToken CRD used for the poll response is a transport envelope that carries an encrypted bearer string, and that encryption is agnostic to the underlying token shape (v3 name:value or ext ext/name:value).

The basic and OAuth login paths returned a v3 Norman Token directly. With session tokens about to migrate to ext.cattle.io/v1 server-side, the CLI needs to accept both response shapes from /v1-public/login.

A parser detects the shape via apiVersion and kind, then unmarshals into a single internal type that carries the bearer token, expires-at, and user id.
The basic and OAuth login paths returned a v3 Norman Token, mixing the protocol shape into the cred-building code.

These paths now return the shared internal type, and the cred builder reads only its bearer token, expires-at, and user id. The SAML path stays on v3 because the corresponding server endpoint stays on v3.
The OAuth login tests asserted only the v3 token shape and did not exercise the new ext-token branch in the response parser.

The existing table-driven test gains an ext-shaped case with the corresponding bearer-token assertion, and a new test exercises the parser plus cred-building pipeline for both shapes with and without an expires-at field.
Token lookups hit only the v3 Management API. Once session tokens start being issued by the ext.cattle.io/v1 API, those lookups would 404.

An HTTP helper now fetches tokens from the ext.cattle.io/v1 API. The user-id resolution and token-validation helpers try v3 first and fall back to the ext API; tokens whose id carries the ext/ prefix skip the v3 attempt entirely. Test stubs use function types so the mocks stay minimal.
…command

The kubectl command resolved the current user and validated the kubeconfig token by calling the v3 Token API directly, with no fallback for ext-issued tokens.

Both lookups now route through the shared helpers that try v3 first and fall back to the ext.cattle.io/v1 API. The local v3-only validation function and its dependent imports are removed.
A stale or deleted v3 token id surfaced a raw 404 from the ext API after fallback. A v3-tokened user with a stale kubeconfig also saw a hard 401 or 403 from the ext authenticator instead of getting the kubeconfig regenerated.

The user-id lookup now wraps the underlying error with the failing token id so the failure is debuggable. Token validation treats 401 and 403 from the ext API the same as 404 and falls through to kubeconfig regeneration. Two new comments explain why the bearer token keeps any ext/ prefix and why a second HTTP client is needed alongside Norman's master client.
Comment thread cmd/token.go Outdated
Comment thread cmd/token.go Outdated

@andreas-kupries andreas-kupries left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

comment nits

@pmatseykanets
pmatseykanets marked this pull request as ready for review July 31, 2026 17:24
@pmatseykanets
pmatseykanets requested a review from a team as a code owner July 31, 2026 17:24
@pmatseykanets pmatseykanets self-assigned this Jul 31, 2026
andreas-kupries
andreas-kupries previously approved these changes Aug 3, 2026
bigkevmcd
bigkevmcd previously approved these changes Aug 3, 2026

@bigkevmcd bigkevmcd left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Some nits around the use of contexts but otherwise, looks good.

Comment thread cmd/token.go
//
// IMPORTANT: do not wrap the returned *clientbase.APIError with fmt.Errorf("%w", ...) —
// clientbase.IsNotFound uses a direct type assertion (err.(*APIError)), not errors.As,
// so any wrap will make IsNotFound return false and break the v3-to-ext fallback contract.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't think you need to wait 'til this lands (if it does) to land your changes.

rancher/norman#870

Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Comment thread cmd/token_test.go Outdated
Switched all context.Background() calls in cmd/token_test.go to
t.Context(), and removed underscores from test functions.
@pmatseykanets
pmatseykanets merged commit 709f81c into rancher:main Aug 5, 2026
1 check passed
@pmatseykanets
pmatseykanets deleted the ext-cattle-token-support branch August 5, 2026 16:36
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