Skip to content

load_incluster_config() sets api_key['authorization'] but auth_settings() expects api_key['BearerToken'] in v36 #2584

Closed

Description

@arghaffari

What happened

After upgrading from kubernetes==35.0.0 to kubernetes==36.0.0, all API calls from pods using load_incluster_config() fail with 401 Unauthorized. The Bearer token is never sent in the Authorization header.

Root cause

In v36, Configuration.auth_settings() (auto-generated) checks for api_key['BearerToken']:

def auth_settings(self):
    auth = {}
    if 'BearerToken' in self.api_key:
        auth['BearerToken'] = {
            'type': 'api_key',
            'in': 'header',
            'key': 'authorization',
            'value': self.get_api_key_with_prefix('BearerToken'),
        }
    return auth

But InClusterConfigLoader._set_config() (manually maintained in kubernetes/base/) still sets the old key:

def _set_config(self, client_configuration):
    client_configuration.host = self.host
    client_configuration.ssl_ca_cert = self.ssl_ca_cert
    if self.token is not None:
        client_configuration.api_key['authorization'] = self.token  # <-- old key

Since auth_settings() looks for 'BearerToken' and load_incluster_config sets 'authorization', the token is never picked up by ApiClient.update_params_for_auth(), so no Authorization header is sent.

In v35, auth_settings() checked for 'authorization', so both sides agreed and everything worked.

How to reproduce

# Inside a pod with a service account
from kubernetes import client, config

config.load_incluster_config()
v1 = client.CoreV1Api()
v1.list_namespaced_pod('default', limit=1)
# => kubernetes.client.exceptions.UnauthorizedException: (401)

Verified that the token itself is valid — a direct urllib.request call with the same token from /var/run/secrets/kubernetes.io/serviceaccount/token returns 200.

Expected behavior

load_incluster_config() should set api_key['BearerToken'] (matching what auth_settings() expects), or auth_settings() should check for api_key['authorization'] (matching what load_incluster_config sets).

Environment

  • Kubernetes cluster version: 1.31
  • Python version: 3.13.12
  • kubernetes client version: 36.0.0 (works fine on 35.0.0)

Activity

  1. MatanKoby commented on May 21, 2026

    @MatanKoby

    Happened to me too.
    Modifiying lines 528-530 in file kubernetes/base/config/kube_config.py:

    def _set_config(self, client_configuration): if 'token' in self.__dict__: client_configuration.api_key['authorization'] = self.token

    into

    def _set_config(self, client_configuration): if 'token' in self.__dict__: client_configuration.api_key['authorization'] = self.token client_configuration.api_key['BearerToken'] = self.token

    is an instant fix for me.

    EDIT: Downgrading to v35 is obviously a better fix till a fix is merged, just to mention.

  2. exherb commented on May 21, 2026

    @exherb

    crazy bug.

  3. faust64 commented on May 21, 2026

    @faust64

    EDIT: Downgrading to v35 is obviously a better fix till a fix

    ... or 33.1.0, if you were impacted by the no_proxy regression that should finally be fixed in 36.0.0.

    or give up and rewrite your code using reliable libraries, like requests ...

  4. saviomuniz commented on May 21, 2026

    @saviomuniz

    We had a similar issue, while trying to run a PATCH to a Pod using default service account. RBAC was properly set. Downgrading to 35.0.0 also fixed the issue for us
    {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Unauthorized","reason":"Unauthorized","code":401}

  5. roycaihw commented on May 21, 2026

    @roycaihw
    Member

    This is a duplicate of #2582 and is being fixed in #2585

  6. yliaog commented on May 26, 2026

    @yliaog
    Contributor

    https://github.com/kubernetes-client/python/releases/tag/v36.0.1 has been released, it should fix the issue. Could you please give it a try?

  7. soheilxor commented on May 28, 2026

    @soheilxor

    I can confirm that the fix worked on our cluster.

  8. yliaog commented on Jun 1, 2026

    @yliaog
    Contributor

    https://github.com/kubernetes-client/python/releases/tag/v36.0.2 has been released, please check if it helps fix the problem.

  9. yliaog commented on Jun 1, 2026

    @yliaog
    Contributor

    /close

  10. k8s-ci-robot commented on Jun 1, 2026

    @k8s-ci-robot
    Contributor

    @yliaog: Closing this issue.

    Details

    In response to this:

    /close

    Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

  11. amolpratap-singh commented on Aug 29, 2026

    @amolpratap-singh

    Application-level defensive approach

    We encountered the same class of in-cluster authentication failure in a Python 3.13-based Kubernetes application.

    After investigating the behavior described in this issue, I implemented an application-level defensive approach where the Kubernetes ApiClient is constructed explicitly instead of relying entirely on load_incluster_config().

    The implementation explicitly configures:

    • Kubernetes API server from KUBERNETES_SERVICE_HOST / KUBERNETES_SERVICE_PORT
    • ServiceAccount Bearer token from /var/run/secrets/kubernetes.io/serviceaccount/token
    • Kubernetes CA certificate from /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    • TLS certificate verification enabled

    The important part is that the Bearer token is configured using the authentication key expected by the generated client configuration, rather than relying on the implicit mapping performed by load_incluster_config().

    I have documented the approach and added unit tests here:

    https://github.com/amolpratap-singh/kubernetes-incluster-auth

    This is not intended as a replacement for the upstream fix. It is an application-level defensive pattern for applications that want explicit control over in-cluster authentication and early validation of ServiceAccount credentials.

    Hopefully this is useful to others who encounter similar authentication regressions during Kubernetes Python client upgrades.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions