python: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate | Rancher EKS Cluster
What happened (please include outputs or screenshots):
Here’s me using kubectl. I’m just expecting the equiv. Python to work.
→ export KUBECONFIG=~/.kube/config
→ kubectl get no
NAME                                         STATUS   ROLES    AGE   VERSION
ip-10-122-0-141.us-west-2.compute.internal   Ready    <none>   23h   v1.20.11-eks-f17b81
ip-10-122-16-82.us-west-2.compute.internal   Ready    <none>   23h   v1.20.11-eks-f17b81
My attempt at doing the same thing in Python and getting different results.
>>> import kubernetes
>> kubernetes.config.load_config()
>>> v1 = kubernetes.client.CoreV1Api()
>>> v1.list_node()
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(                                                                                                                                           File "/usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py", line 386, in _make_request
    self._validate_conn(conn)                                                                                                                                                        File "/usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py", line 1040, in _validate_conn
    conn.connect()                                                                                                                                                                   File "/usr/local/lib/python3.9/dist-packages/urllib3/connection.py", line 414, in connect
    self.sock = ssl_wrap_socket(                                                                                                                                                     File "/usr/local/lib/python3.9/dist-packages/urllib3/util/ssl_.py", line 449, in ssl_wrap_socket
    ssl_sock = _ssl_wrap_socket_impl(                                                                                                                                                File "/usr/local/lib/python3.9/dist-packages/urllib3/util/ssl_.py", line 493, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)                                                                                                            File "/usr/lib/python3.9/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(                                                                                                                                             File "/usr/lib/python3.9/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/lib/python3.9/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()                                                                                                                                                    ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)
                                                                                                                                                                                   During handling of the above exception, another exception occurred:
OK, doesn’t work. Let’s try loading the kube_config directly.
>>> import os
>>> os.path.exists(os.environ["KUBECONFIG"])
True
>> kubernetes.config.load_kube_config(os.environ["KUBECONFIG"])
>> v1 = kubernetes.client.CoreV1Api()
>>> v1.list_node()  
# SAME ERROR AS ABOVE
OK, digging through Github issues I came across #1622 which leads to #36 I can try that…
>>> from kubernetes import client
>>> from kubernetes import config                                                                                                                                                 
>>> from kubernetes.client.api import core_v1_api
>>> config.load_config()
>>> configuration = client.Configuration()
>>> configuration.assert_hostname = False
>>> configuration.verify_ssl = True
>>> client.Configuration.set_default(configuration)
>>>
>>> v1 = core_v1_api.CoreV1Api()
>>> v1.list_node()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api/core_v1_api.py", line 16844, in list_node
    return self.list_node_with_http_info(**kwargs)  # noqa: E501
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api/core_v1_api.py", line 16951, in list_node_with_http_info
    return self.api_client.call_api(
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api_client.py", line 348, in call_api
    return self.__call_api(resource_path, method,
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api_client.py", line 180, in __call_api
    response_data = self.request(
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/api_client.py", line 373, in request
    return self.rest_client.GET(url,
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/rest.py", line 240, in GET
    return self.request("GET", url,
  File "/usr/local/lib/python3.9/dist-packages/kubernetes/client/rest.py", line 213, in request
    r = self.pool_manager.request(method, url,
  File "/usr/local/lib/python3.9/dist-packages/urllib3/request.py", line 74, in request
    return self.request_encode_url(
  File "/usr/local/lib/python3.9/dist-packages/urllib3/request.py", line 96, in request_encode_url
    return self.urlopen(method, url, **extra_kw)
  File "/usr/local/lib/python3.9/dist-packages/urllib3/poolmanager.py", line 376, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py", line 692, in urlopen
    conn = self._get_conn(timeout=pool_timeout)
  File "/usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py", line 281, in _get_conn
    return conn or self._new_conn()
  File "/usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py", line 235, in _new_conn
    conn = self.ConnectionCls(
  File "/usr/local/lib/python3.9/dist-packages/urllib3/connection.py", line 130, in __init__
    _HTTPConnection.__init__(self, *args, **kw)
TypeError: __init__() got an unexpected keyword argument 'assert_hostname'
OK, what if we just disable SSL verify instead?
>>> from kubernetes import client
>>> from kubernetes import config
>>> from kubernetes.client.api import core_v1_api
>>> config.load_config()
>>> configuration = client.Configuration()
>>> configuration.verify_ssl = False
>>> client.Configuration.set_default(configuration)
>>> v1 = core_v1_api.CoreV1Api()
>>> v1.list_node()
...
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=80): Max retries exceeded with url: /api/v1/nodes (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f245a5701f0>: Failed to establish a new connection: [Errno 111] Connection refused'))
I can’t actually get this client to work in any way that I can try…
What you expected to happen:
Anything to work.
How to reproduce it (as minimally and precisely as possible):
Many examples above.
Anything else we need to know?:
Environment:
- Kubernetes version (
kubectl version): 
→ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.4", GitCommit:"e6c093d87ea4cbb530a7b2ae91e54c0842d8308a", GitTreeState:"clean", BuildDate:"2022-02-16T12:30:48Z", GoVersion:"go1.17.6", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20+", GitVersion:"v1.20.11-eks-f17b81", GitCommit:"f17b810c9e5a82200d28b6210b458497ddfcf31b", GitTreeState:"clean", BuildDate:"2021-10-15T21:46:21Z", GoVersion:"go1.15.15", Compiler:"gc", Platform:"linux/amd64"}
WARNING: version difference between client (1.23) and server (1.20) exceeds the supported minor version skew of +/-1
- OS (e.g., MacOS 10.13.6):
 
→ uname -a
Linux 7CWL5Y2 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- Python version (
python --version) 
# python3 --version
Python 3.9.2
- Python client version (
pip list | grep kubernetes) 
# pip list | grep kubernetes
kubernetes          20.13.0
I originally tried the very latest of this library, but I decided to test a downgrade to see if v23 would work too. I downgraded to have the client version match the server version.
About this issue
- Original URL
 - State: closed
 - Created 2 years ago
 - Reactions: 3
 - Comments: 26 (3 by maintainers)
 
Thanks, I had the same problem as well and wanted to keep kubectl working.
I generate my client now like this until this is fixed:
I also encountered this problem, following is some debug info which might be useful, seems like a problem with urllib3
Reproduction steps:
USERNAME=<YOUR KUBECTL CONFIG USER NAME>CLUSTER=<YOUR KUBECTL CONFIG CLUSTER NAME>CACERT=<FILE TO STORE THE CA CERTIFICATE IN>TOKEN="$(kubectl config view --raw "-ojsonpath={.users[?(@.name=='${USERNAME}')].user.token}")"kubectl config view --raw "-ojsonpath={.clusters[?(@.name=='${CLUSTER}')].cluster['certificate-authority-data']}" | base64 -d > $CACERTSERVER="$(kubectl config view --raw "-ojsonpath={.clusters[?(@.name=='${CLUSTER}')].cluster.server}")"curl -H "authorization: Bearer ${TOKEN}" "${SERVER}/api/v1/nodes" --cacert $CACERTpython3 -c "import urllib3; urllib3.PoolManager(ca_certs='${CACERT}').request('GET', '${SERVER}/api/v1/nodes', headers={'authorization': 'Bearer ${TOKEN}'})"Expected
Actual
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='***', port=443): Max retries exceeded with url: ****/api/v1/nodes (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1131)')))Just to help any others who come across this, I had a similar error message while using ansible with the
kubernetes.coremodules.Likely not the same cause as above, but the certificate that I provided in
certificate-authority-datawas not self-signed. Our internal setup used:worker)cluster)department).company).company(self).The value of
certificate-authority-datain my ~/.kube/config was effectively set to:This doesn’t make valid certificate chain, but usage of an intermediary as your
certificate-authority-datadoes work with kubectl and any tooling based on kubernetes/client-goI resolved my issue by setting
certificate-authority-datato something more like:this wouldn’t be ideal for inter-worker communication (broadens the trust scope a great deal), but it will be fine for my local config.
I wouldn’t be surprised if other tooling (a la
kubeadm) will generate a similar config if configured to get its certificates from an issuer like vault.Only thing left that is curious to me is why it didn’t resolve the root certificate from the operating store (since
companyis present in my trust store), but that’s an investigation for another day.Hope this helps someone 😃
The client just does not seem to read
certificate-authority-dataat all and then (obviously) fails to connect.EDIT: It does seem to read it correctly but somehow it’s broken for some clusters. With a remote cluster on AKS it works just fine. The broken cluster is an in LAN cluster created with kubeadm.
The one difference I can detect is that AKS uses 4096 bits RSA and kubeadm uses 2048 and the kubeadm CA cert has the following extra extensions:
And it connects to a nonstandard port, which might also cause the issue.
Has no effect which is curious
there seem to be issues in your use of the client library, could you try the given example in https://github.com/kubernetes-client/python#examples?