kubernetes-client / python

Official Python client library for kubernetes
http://kubernetes.io/
Apache License 2.0
6.75k stars 3.27k forks source link

Configure SSL CA CERTIFICATE with REQUESTS_CA_BUNDLE env var before certifi #1131

Open nirousseau opened 4 years ago

nirousseau commented 4 years ago

What is the feature and why do you need it:

The idea is to configure ssl_ca_cert using the REQUESTS_CA_BUNDLE env var before falling back to certifi if no specific configuration has been provided.

Some applications that are using kubernetes-client / python do not provide a parameter to client/configuration.py#L83. Using an env var before certifi will help such use cases.

Finally, it can be very useful in a container context, as we can pass this configuration via, once again, env vars.

Describe the solution you'd like to see:

In : client/rest.py#L70

At the moment, the code is the following :

        # ca_certs
        if configuration.ssl_ca_cert:
            ca_certs = configuration.ssl_ca_cert
        else:
            # if not set certificate file, use Mozilla's root certificates.
            ca_certs = certifi.where()

We can add a new condition of the form :

        # ca_certs
        if configuration.ssl_ca_cert:
            ca_certs = configuration.ssl_ca_cert
        elif 'REQUESTS_CA_BUNDLE' in os.environ:
            ca_certs = environ.get('REQUESTS_CA_BUNDLE')
        else:
            # if not set certificate file, use Mozilla's root certificates.
            ca_certs = certifi.where()

The env var REQUESTS_CA_BUNDLE seems to be a good candidate as it is a common practice.

Related issues:

palnabarun commented 4 years ago

@nirousseau Why not pass the ssl_ca_cert while initializing configuration?

import os
from kubernetes import client, config

client_configuration = client.configuration.Configuration()
client_configuration.ssl_ca_cert = os.environ.get('REQUESTS_CA_BUNDLE')

config.load_kube_config(client_configuration=client_configuration)

This creates a separation of concern and solves the problem at hand.

Also, changing anything in https://github.com/kubernetes-client/python/blob/master/kubernetes/client/rest.py requires a change in the OpenAPI generator since the module is automatically generated from OpenAPI spec.

nirousseau commented 4 years ago

@palnabarun Hello, thank your for your answer.

For more context, this proposal is connected with this issue from apache / airflow : https://github.com/apache/airflow/issues/8019.

I agree that the responsibility of setting this configuration belongs to the software that is using this library. But as a system administrator, I would like to change this setting, even if the developers of apache / airflow have not integrated the ability to change it.

I want to discuss the idea that both developers and system administrators should be able to change the value of the certificate authority path, or at least, its default value.

Currently : user_given_setting -> certifi.

Developer oriented.

Pros :

Cons :

I suggest : user_given_setting -> system_env -> certifi.

Developers + Operators can control the behavior.

Pros :

Cons :

Now, the question "should a library inspect its environment in order to set default settings ?" can be legitimately asked. This proposal adds more control to system administrators, but it can be a breaking change for systems that have this env var miss configured.

splashx commented 4 years ago

This code snippet:

import os
from kubernetes import client, config

client_configuration = client.configuration.Configuration()
client_configuration.ssl_ca_cert = os.environ.get('REQUESTS_CA_BUNDLE')

config.load_kube_config(client_configuration=client_configuration)

Unfortunately doesn't load the kube config config as expected - for example, the host is set as localhost instead of that of the kubeconfig/context.

fejta-bot commented 4 years ago

Issues go stale after 90d of inactivity. Mark the issue as fresh with /remove-lifecycle stale. Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle stale

fejta-bot commented 4 years ago

Stale issues rot after 30d of inactivity. Mark the issue as fresh with /remove-lifecycle rotten. Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta. /lifecycle rotten

palnabarun commented 4 years ago

/lifecycle frozen /assign

mhumpula commented 3 years ago

For anyone with custom CAs, trying to use this library: I was able to get away with this snippet

config.load_kube_config() # load everything from .kube/config
cc = client.Configuration.get_default_copy()
cc.ssl_ca_cert = os.environ.get('REQUESTS_CA_BUNDLE') # use proper CA list
client.Configuration.set_default(cc)

But still, this is kinda sad. The .kube/config already contains valid cluster CAs, so why does it work in golang but not in python? :thinking:

Stef16Robbe commented 1 month ago

This is still a necessary workaround sadly... For anyone else requiring it, do note that cc.ssl_ca_cert needs a filename, not the contents ^^, I misunderstood this at first.

tj-smith47 commented 1 month ago

Perhaps this is a pyright issue, but it is reading from the class definition of Configuration. Not sure if anyone else has experienced this warning, but a solution to the problem was posed by @palnabarun so posting it here despite being arguably a different topic. I would think this could be an instantiation kwarg and then the if ssl_ca_cert: approach could be used as it is with api_key and api_key_prefix.

Screenshot 2024-09-09 at 14 33 00