J'ai rencontré un bug vraiment étrange qui a à voir avec SSL et python à google.com (ou plus généralement je pense avec les domaines qui ont plusieurs chaînes de certificats). Chaque fois que j'essaie de faire une demande à https://*.google.com/whatever
J'obtiens l'erreur suivante:
SSLError: ("bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)",) while doing GET request to URL: https://google.com/
J'ai traversé de nombreux cerceaux en essayant de faire fonctionner cela et j'ai recours à la publication sur Stack Overflow maintenant que je ne sais pas quoi faire. Voici ce que j'ai essayé:
J'ai remarqué que date
a renvoyé une date avec 2 minutes de retard sur le temps réel (ce qui pourrait invalider mon certificat). J'ai corrigé cela en supposant qu'il validerait le certificat. Cela n'a pas résolu le problème.
J'ai découvert que Python 2.7.9 a rétroporté certaines bibliothèques SSL de Python 3. J'ai mis à niveau de Python 2.7.6 vers 2.7.9 en supposant les mises à jour (qui incluent les correctifs répertoriés dans ce fil: https://serverfault.com/questions/692110/error-with-python2-as-a-https-client-with-an-nginx -server-and-ssl-certificate-ch ) le corrigerait. Pas de chance, même erreur.
Définir évidemment verify=False
fonctionne, mais nous ne voulons pas bouger sur la sécurité, nous devons obtenir verify=True
travailler.
curl https://google.com
fonctionne également comme prévu. C'est ainsi que je sais que cela a à voir avec Python.
$ python -V
Python 2.7.9
$ pip list | grep -e requests
requests (2.9.1)
$ uname-a # ubuntu 14.04
Linux staging.example.com 3.13.0-48-generic #80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
C'est uniquement pour les domaines Google via https. Voici un exemple:
$ ipython
Python 2.7.9 (default, Jan 6 2016, 21:37:32)
Type "copyright", "credits" or "license" for more information.
IPython 4.0.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import requests
In [2]: requests.get('https://facebook.com', verify=True)
Out[2]: <Response [200]>
In [3]: requests.get('https://stackoverflow.com', verify=True)
Out[3]: <Response [200]>
In [4]: requests.get('https://spotify.com', verify=True)
Out[4]: <Response [200]>
In [5]: requests.get('http://google.com', verify=True) # notice the http
Out[5]: <Response [200]>
In [6]: requests.get('https://google.com', verify=True)
---------------------------------------------------------------------------
SSLError Traceback (most recent call last)
<ipython-input-6-a7fff1831944> in <module>()
----> 1 requests.get('https://google.com', verify=True)
/example/.virtualenv/example/lib/python2.7/site-packages/requests/api.pyc in get(url, params, **kwargs)
65
66 kwargs.setdefault('allow_redirects', True)
---> 67 return request('get', url, params=params, **kwargs)
68
69
/example/.virtualenv/example/lib/python2.7/site-packages/requests/api.pyc in request(method, url, **kwargs)
51 # cases, and look like a memory leak in others.
52 with sessions.Session() as session:
---> 53 return session.request(method=method, url=url, **kwargs)
54
55
/example/.virtualenv/example/lib/python2.7/site-packages/requests/sessions.pyc in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
466 }
467 send_kwargs.update(settings)
--> 468 resp = self.send(prep, **send_kwargs)
469
470 return resp
/example/.virtualenv/example/lib/python2.7/site-packages/requests/sessions.pyc in send(self, request, **kwargs)
574
575 # Send the request
--> 576 r = adapter.send(request, **kwargs)
577
578 # Total elapsed time of the request (approximately)
/example/.virtualenv/example/lib/python2.7/site-packages/requests/adapters.pyc in send(self, request, stream, timeout, verify, cert, proxies)
445 except (_SSLError, _HTTPError) as e:
446 if isinstance(e, _SSLError):
--> 447 raise SSLError(e, request=request)
448 Elif isinstance(e, ReadTimeoutError):
449 raise ReadTimeout(e, request=request)
SSLError: ("bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)",)
J'ai trouvé une solution. Il semble y avoir un problème majeur dans la version de certifi
qui était en cours d'exécution. J'ai découvert cela à partir de ce (très long) problème GitHub: https://github.com/certifi/python-certifi/issues/26
TL; DR
pip uninstall -y certifi && pip install certifi==2015.04.28