Skip to content
This repository has been archived by the owner on Dec 1, 2018. It is now read-only.

Accessing the API Server from a pod using service account causes an error #29

Closed
akshayl opened this issue Apr 3, 2016 · 27 comments · Fixed by #95
Closed

Accessing the API Server from a pod using service account causes an error #29

akshayl opened this issue Apr 3, 2016 · 27 comments · Fixed by #95

Comments

@akshayl
Copy link

akshayl commented Apr 3, 2016

K8S Version: 1.2
Code:

api = HTTPClient(KubeConfig.from_service_account())
pods = Pod.objects(api).filter(namespace="gondor-system")
ready_pods = filter(operator.attrgetter("ready"), pods)

Error message:

SSLError: hostname '10.3.240.1' doesn't match either of 'kubernetes', 'kubernetes.default', 'kubernetes.default.svc', 'kubernetes.default.svc.cluster.local'
@brosner
Copy link
Contributor

brosner commented Apr 3, 2016

This is happening likely due to running on Python < 3.5. IP hostnames are not supported until Python 3.5. I am open to ideas on how to fix it as we are not generating the config. I am not a huge fan of version checking and replacement as we can't guanrantee hostnames.

@brosner
Copy link
Contributor

brosner commented Apr 4, 2016

One thing that occurs to me is that I added PYKUBE_KUBERNETES_SERVICE_HOST environment variable support to override KUBERNETES_SERVICE_HOST provided to the pod. This should give you the ability to do:

PYKUBE_KUBERNETES_SERVICE_HOST=kubernetes

which will work around the certificate checking against the IP that fails against Python < 3.5.

@jrydberg
Copy link

I'm getting this straight of the box with a kube configuration file created by gcloud.

Is there no way to get around this on python 2.7 system?

@brosner
Copy link
Contributor

brosner commented May 30, 2016

@jrydberg unfortunately there is nothing I am aware of that will fix it. The underlying issue is within Python. It may be possible to override the certificate checking mechanism to add IP hostname support to Python < 3.5, but I would hate to this at the risk of comprising security already being managed by Python.

mikebryant added a commit to ocadotechnology/aimmo that referenced this issue Jun 22, 2016
@zcarlson-signifai
Copy link

It turns out that pykube uses requests, which pulls in urllib3, which attempts to pull in match_hostname first from Python native SSL, then from backports, falling back on its own implementation if neither are available. However, the latest backports's match_hostname seems to be more complete than the native SSL match_hostname, allowing for IP addresses. You can monkey-patch this in your end script with the following, so long as "IP Address:" actually does show up in subjectAltNames:

import backports.ssl_match_hostname
import pykube

# Monkey-patch match_hostname with backports's match_hostname, allowing for IP addresses
# XXX: the exception that this might raise is backports.ssl_match_hostname.CertificateError
pykube.http.requests.packages.urllib3.connection.match_hostname = backports.ssl_match_hostname.match_hostname

@zcarlson-signifai
Copy link

Of course it should be noted that the 'real fix' is for the packaged version of urllib3 with requests to use backports.ssl_match_hostname over the native, if available. But in the short term...

@paultiplady
Copy link
Contributor

Feels like resorting to monkey-patching is not a user-friendly solution to this problem, nor is "use Python 3.5", so I've opened an issue at urllib3 to try to resolve the underlying issue.

Think there's probably a very simple change to that library that would get round this issue, but I might be missing something. Let's see what the urllib guys have to say (they are usually super-helpful).

@Lukasa
Copy link

Lukasa commented Jul 9, 2016

Hey folks! Just a FYI: I'm looking at working on this next week. It's slightly more complex than we'd like because the new match_hostname uses the ipaddress module, which we will also need to backport, but it's definitely on our radar.

@zcarlson-signifai
Copy link

@Lukasa You would? pip install ipaddress worked for me on python 2.7...

@paultiplady
Copy link
Contributor

@zcarlson-signifai I think the property they are trying to preserve is that pip install requests should work out of the box (including the new IP SAN handling), without the user having to know to pip install ipaddress as well.

@paultiplady
Copy link
Contributor

FTR the issue I raised at urllib3 was a dupe of this one: urllib3/urllib3#258

Linking here so that we can more easily see when it's resolved.

@JohnSimowitz
Copy link

monkey-patching with backports.match_hostname did not work for me... but fortunately there is a simpler approach. If you only need to communicate with the kubernetes master you can define your own match_hostname function.

def _MatchHostname(_, hostname):
  if hostname != os.environ['KUBERNETES_SERVICE_HOST']:
    raise ssl.CertificateError('Hostname [%s] not equal to [%s].',
        hostname, os.environ['KUBERNETES_SERVICE_HOST'])

Now monkey patch with this and it appears to work fine.

@victorgp
Copy link
Contributor

So it seems that this got fixed in urllib3, thanks @Lukasa ! now we just need to wait for a new version of 'requests'

@yuefengz
Copy link

yuefengz commented Oct 9, 2016

I am still having the issue, with a local config file, with python 2.7, with urllib3 installed from its source. Is this because of my python version?

@Lukasa
Copy link

Lukasa commented Oct 12, 2016

@YuefengZhou You need to install some extra third-party dependencies. Did you install urllib3[secure]?

@yuefengz
Copy link

@Lukasa Yes. I have installed it and and I have just run pip2 install --upgrade urllib3[secure] again but still failed.

@victorgp
Copy link
Contributor

@Lukasa how can just by installing third party libraries this work? if requests have 'urllib3' embedded in its code, although we installed the right urllib3 version, requests will use its embedded one.

@Lukasa
Copy link

Lukasa commented Oct 12, 2016

@victorgp Depends on the source. For pip installed versions of Requests, simply updating urllib3 doesn't work.

@yejw5
Copy link

yejw5 commented Oct 27, 2016

Thanks @zcarlson-signifai and pykube.http.requests.packages.urllib3.connection.match_hostname = backports.ssl_match_hostname.match_hostname worked for me.

But now the package has changed and we could not find requests in pykube/http.py. Is there any way for us to fix it when we still have hostname '10.3.240.1' doesn't match either issue in Python 2.7?

@mcapuccini
Copy link

If you modify your kubeconfig file, and put the API server hostname instead of the IP address it is going to work

@yejw5
Copy link

yejw5 commented Nov 2, 2016

@mcapuccini Many thanks! This works for me perfectly.

@philographer
Copy link

@mcapuccini how can i change the server hostname??

@mcapuccini
Copy link

@yoohoogun114 if you open the kubeconfig file, it should be something like::

server: X.X.X.X

You need to change X.X.X.X to a hostname (if you are using minikube, don't forget to add the hostname in /etc/hosts)

@victorgp
Copy link
Contributor

That solution doesn't work if you are using GCP.

The SSL certs of the k8s masters only have SAN for kubernetes.default and kubernetes.default.svc.cluster.local therefore you cannot set the domain you want.

A workaround is to set in your kubeconfig file the server name as kubernetes.default.svc.cluster.local and fake the DNS in /etc/hosts making that domain point to the GCP cluster ip

@paultiplady
Copy link
Contributor

With the latest version of Requests, I believe this issue is resolved. I've put up a PR with a change that requires the fixed requests version (#95), if anyone wants to give that a try that would be helpful.

Or you should be able to just do pip install --upgrade requests>=2.12.0 to get the appropriate version, though you'll get a spurious warning without the PR mentioned above.

BrentDorsey pushed a commit to BrentDorsey/kubernetes-ec2-autoscaler that referenced this issue Apr 2, 2017
pykube 0.15.0 resolves the host name issue
     * cluster.py : Removed "HACK kelproject/pykube#29 (comment)" and "Monkey-patch" code
     * requirements.txt : removed backports.ssl_match_hostname and replaced pykube git pull with pykube 0.15.0 release version

Refactored scaling-controller.yaml Replication Controller example to autoscaler-dep.yaml Deployment, Deployments provide declarative updates for Pods and Replica Sets (the next-generation Replication Controller).

Added an example secret yaml named autoscaler-secret.yaml

Updated README.md to reflect the changes, fixed the namespace issue in README.md and scaling-controller.yaml to be "kube-system" instead of "system".
vicki-c pushed a commit to openai/kubernetes-ec2-autoscaler that referenced this issue Apr 12, 2017
pykube 0.15.0 resolves the host name issue
     * cluster.py : Removed "HACK kelproject/pykube#29 (comment)" and "Monkey-patch" code
     * requirements.txt : removed backports.ssl_match_hostname and replaced pykube git pull with pykube 0.15.0 release version

Refactored scaling-controller.yaml Replication Controller example to autoscaler-dep.yaml Deployment, Deployments provide declarative updates for Pods and Replica Sets (the next-generation Replication Controller).

Added an example secret yaml named autoscaler-secret.yaml

Updated README.md to reflect the changes, fixed the namespace issue in README.md and scaling-controller.yaml to be "kube-system" instead of "system".
@yejw5
Copy link

yejw5 commented May 18, 2017

After added certificate to kubernetes, the issue exception: hostname 'X.X.X.X' doesn't match either of 'k8s-master', 'kubernetes' ... appears again. I tried the ways of upgrading requests and urllib3, installing ipaddress metioned above. But only modifying kuberconfig and /etc/hosts as @victorgp said work fine for me. It seems tricky. Is there other ways to solve this problem?

@trulyshelton
Copy link

trulyshelton commented Jun 28, 2017

I managed to make it work by updating the backports.ssl_match_hostname module.
Anyone who can't solve the issue through the above solutions may try add backports.ssl-match-hostname>=3.5.0.1 to the requirements.

The reason seems to be that an outdated version of backports.ssl_match_hostname would not check against IP.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.