Skip to content

config: write api_key['BearerToken'] so v36+ SDK auth works#2585

Merged
k8s-ci-robot merged 2 commits into
kubernetes-client:masterfrom
Jmacek:fix-incluster-auth-v36-bearertoken-key
May 21, 2026
Merged

config: write api_key['BearerToken'] so v36+ SDK auth works#2585
k8s-ci-robot merged 2 commits into
kubernetes-client:masterfrom
Jmacek:fix-incluster-auth-v36-bearertoken-key

Conversation

@Jmacek
Copy link
Copy Markdown
Contributor

@Jmacek Jmacek commented May 21, 2026

What this PR does

Updates the in-cluster and kubeconfig loaders in kubernetes/base/config/, plus kubernetes_asyncio/config/incluster_config.py, to write the bearer token under api_key['BearerToken'] (the v36+ lookup key) instead of api_key['authorization'] (the v35 lookup key). Updates the corresponding test assertions to read the new key. Adds a regression test that exercises the end-to-end flow (Configuration → ApiClient → outgoing Authorization header) which the existing tests did not cover.

Why

v36 rewrote Configuration.auth_settings() to look up the bearer-token credential under api_key['BearerToken'], matching the OpenAPI security scheme name. This rename was declared a breaking change in the project CHANGELOG as part of the openapi-generator v6.6.0 upgrade. The hand-written loaders in kubernetes/base/config/ and kubernetes_asyncio/config/incluster_config.py were not updated to follow the rename - they still write api_key['authorization']. (Asyncio's kube_config.py already writes 'BearerToken', so it isn't affected.)

Net effect on v36: every call to load_incluster_config() (and load_kube_config() with a static token, including the async equivalents) produces a Configuration whose auth_settings() yields no bearer credential, so outgoing API requests are sent without an Authorization header and the apiserver treats them as system:anonymous. The failure mode is silent - no warning, no exception, just 401s from every API call.

See #2582 for the user-side report and a minimal repro.

Test plan

  • Added test_load_incluster_sets_request_authorization_header to kubernetes/base/config/incluster_config_test.py. It drives a real ApiClient.update_params_for_auth() against a freshly-loaded Configuration and asserts the resulting headers contain an Authorization entry - the end-to-end invariant that v36 broke.
  • Verified the new regression test fails on kubernetes==36.0.0 against the unfixed loader (AssertionError: 'authorization' not found in {}) and passes with the fix.
  • Verified all 103 sync tests in kubernetes/base/config/ and 72 async tests in kubernetes_asyncio/config/ pass on v36 with the change applied.

Fixes #2582

Fix `load_incluster_config()` and `load_kube_config()` (sync and async, with a static token) so requests carry an `Authorization` header on `kubernetes-client/python` v36+. Without this fix, in-cluster pods upgrading to v36 silently send unauthenticated requests and the apiserver rejects them as `system:anonymous`.

@k8s-ci-robot k8s-ci-robot added do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. labels May 21, 2026
@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented May 21, 2026

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: Jmacek / name: Jmacek (322667b)

@k8s-ci-robot k8s-ci-robot added the needs-kind Indicates a PR lacks a `kind/foo` label and requires one. label May 21, 2026
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

Welcome @Jmacek!

It looks like this is your first PR to kubernetes-client/python 🎉. Please refer to our pull request process documentation to help your PR have a smooth ride to approval.

You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. Here is the bot commands documentation.

You can also check if kubernetes-client/python has its own contribution guidelines.

You may want to refer to our testing guide if you run into trouble with your tests not passing.

If you are having difficulty getting your pull request seen, please follow the recommended escalation practices. Also, for tips and tricks in the contribution process you may want to read the Kubernetes contributor cheat sheet. We want to make sure your contribution gets all the attention it needs!

Thank you, and welcome to Kubernetes. 😃

@k8s-ci-robot k8s-ci-robot requested review from fabianvf and roycaihw May 21, 2026 17:10
@k8s-ci-robot k8s-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. labels May 21, 2026
@Jmacek Jmacek force-pushed the fix-incluster-auth-v36-bearertoken-key branch from f651938 to 322667b Compare May 21, 2026 17:12
@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. and removed do-not-merge/invalid-commit-message Indicates that a PR should not merge because it has an invalid commit message. do-not-merge/release-note-label-needed Indicates that a PR should not merge because it's missing one of the release note labels. cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. labels May 21, 2026
@Jmacek
Copy link
Copy Markdown
Contributor Author

Jmacek commented May 21, 2026

/kind bug

@k8s-ci-robot k8s-ci-robot added kind/bug Categorizes issue or PR as related to a bug. and removed needs-kind Indicates a PR lacks a `kind/foo` label and requires one. labels May 21, 2026
v36 rewrote Configuration.auth_settings() to look up the bearer-token
credential under api_key['BearerToken'], matching the OpenAPI security
scheme name. The in-cluster and kubeconfig loaders were not updated -
they still write api_key['authorization'], the v35 lookup key. The
same gap exists in kubernetes_asyncio/config/incluster_config.py.

As a result, on v36 every call to load_incluster_config() (and
load_kube_config() with a static token, including the async equivalents)
produces a Configuration whose auth_settings() yields no bearer
credential, so outgoing API requests are sent without an Authorization
header and the apiserver treats them as system:anonymous.

Write the token under both 'authorization' (v35) and 'BearerToken'
(v36+) in all three affected loaders so requests carry the expected
header. The old key is preserved as a backward-compatibility hedge for
any third-party code introspecting api_key['authorization'] directly.

Add a regression test in incluster_config_test that drives a real
ApiClient.update_params_for_auth() against a freshly-loaded
Configuration and asserts the resulting headers contain an Authorization
entry - the end-to-end invariant that v36 quietly broke.
@Jmacek Jmacek force-pushed the fix-incluster-auth-v36-bearertoken-key branch from 322667b to c3608a4 Compare May 21, 2026 18:29
client_configuration.ssl_ca_cert = self.ssl_ca_cert
if self.token is not None:
client_configuration.api_key['authorization'] = self.token
client_configuration.api_key['BearerToken'] = self.token
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Does it make sense to have 2 configurations with that same token?
Either one or the other would be fine. It has to be consistent everywhere.

Do we know why that BearerToken was introduced? What was the intention?

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.

I think this is related https://github.com/kubernetes-client/python/blob/master/CHANGELOG.md#breaking-change-from-upgrading-openapi-generator-to-v660. It was introduced in upstream client generator. Same question here. I think upstream did a replacement, rather than keeping both. cc @yliaog

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks both - the original intent of writing both keys was to hedge backward compatibility for any third-party code introspecting api_key['authorization'] directly. But since the rename was already documented as a breaking change in the v6.6.0 generator upgrade, aligning the loaders with that decision is the right call. Switching to a straight replacement.

Address review feedback: the openapi-generator v6.6.0 upgrade
declared this rename as a breaking change in the project CHANGELOG,
so the loaders should follow the rename rather than preserve the
v35 key for backward compatibility.

Removes the api_key['authorization'] write in all three affected
loaders (sync incluster, sync kube_config, async incluster) and
updates the corresponding test assertions to read 'BearerToken'.
@yliaog
Copy link
Copy Markdown
Contributor

yliaog commented May 21, 2026

thanks for the fix

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 21, 2026
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Jmacek, yliaog

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 21, 2026
@k8s-ci-robot k8s-ci-robot merged commit 46989af into kubernetes-client:master May 21, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configuration.auth_settings() returns empty dict in v36.0.0 - all BearerToken-authed requests go anonymous

5 participants