15
votes

I'm maintaining a Python mini-app that uses requests + HTTPS.

The app worked until the IP address of the hostname in the HTTPS URL changed (legitimately). If I point my browser to the URL I can retrieve it fine.

Where does Python/requests keep the analog of ssh's known_hosts and how do I clear it for this host?

$ python --version
Python 2.7.3

$ cat foo.py 
import requests
url = "https://somehost/resource.json"
requests.get(url, timeout=5, config={'danger_mode': True})

$ source venv/bin/activate
$ python foo.py 
Traceback (most recent call last):
  File "foo.py", line 3, in <module>
    requests.get(url, timeout=5, config={'danger_mode': True})
  File "/home/dfukdev/corsair-scripts/alfred/venv/local/lib/python2.7/site-packages/requests/api.py", line 65, in get
return request('get', url, **kwargs)
  File "/home/dfukdev/corsair-scripts/alfred/venv/local/lib/python2.7/site-packages/requests/safe_mode.py", line 39, in wrapped
return function(method, url, **kwargs)
  File "/home/dfukdev/corsair-scripts/alfred/venv/local/lib/python2.7/site-packages/requests/api.py", line 51, in request
return session.request(method=method, url=url, **kwargs)
  File "/home/dfukdev/corsair-scripts/alfred/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 241, in request
r.send(prefetch=prefetch)
  File "/home/dfukdev/corsair-scripts/alfred/venv/local/lib/python2.7/site-packages/requests/models.py", line 641, in send
raise SSLError(e)
requests.exceptions.SSLError: [Errno 1] _ssl.c:504: error:14090086:SSL     routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
3
I'm not sure why the certificate is not valid, but as a workaround you can use requests.get(url, timeout=5, config={'danger_mode': True}, verify=False) to ignore the SSL certificate as mentionned in the Requests advanced usage documentation.user2629998
@AndréDaniel has that config been removed? I don't see it on the linked page and my python claims it to be unknown. And verify=False alone doesn't seem to do the trick...codeling
@RandolphCarter I just looked at the page and it's still there, search for "SSL Cert" (I'd love to give you a direct link but I'm on my phone and can't really do so)...user2629998
@AndréDaniel ah yes, the Verify is still there. I had missed a second reqeuests.get statement in my script throwing that error as well ;). config={'danger_mode': True} is not required anymore however - if I read this correctly it is now default. Thanks for your lightning fast response!codeling

3 Answers

6
votes

You're using an ancient version of requests. You'll get a more helpful message if you upgrade to 2.0 and if your site has a certificate mismatch you may be able to fix it by specifying the system certificates which will be able to verify an intermediate certificate. You can also just have requests not verify your certificate as Andre suggested.

2
votes

It turned out that during the server upgrade mentioned in the question an incorrectly-signed certificate was installed. HTTPS in the browser worked because of the root certificate differences between the Windows browser machine and Ubuntu Python client. HTTPS via a browser from the same Ubuntu machine on which Python was run revealed the certificate problem details.

The IP change had little to do with the problem except to confuse things.

Promoting my comment to an answer as:

  1. this answered my question
  2. this question is getting enough traffic I'd like to share the knowledge.
0
votes

If the above doesn't work, and you find out it is local, then this solution worked for me...

Essentially run the Install Certificates.command file within Python folder.

https://www.dev2qa.com/how-to-fix-python-error-certificate-verify-failed-unable-to-get-local-issuer-certificate-in-mac-os/