Python (pip) throwing [SSL: CERTIFICATE_VERIFY_FAILED] even if certificate chain updated
<p>This is a followup to a <a href="http://stackoverflow.com/q/39356413/827480">previous SO post</a>.</p>

<p>I am using Windows/cygwin and I have the need for python to understand a custom CA certificate, as the network infrastructure resigns all SSL requests with its own certificate.</p>

<p>If I try to run <code>pip search SimpleHTTPServer</code>, I get the following error message:</p>

<pre><code>...
  File "c:\users\erbe\appdata\local\programs\python\python35-32\lib\ssl.py", line 633, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)
</code></pre>

<p>I have tried to add the certificates to my list of trusted certificates by doing the following:</p>

<ol>
<li>Copy my .pem file to /etc/pki/ca-trust/source/anchors</li>
<li><code>update-ca-trust extract</code></li>
</ol>

<p>I have verified that this works as I can now point to the generated PEM file and run pip successfully:  <code>pip --cert /usr/local/ssl/cert.pem search SimpleHTTPServer</code>:</p>

<pre><code>$ pip --cert tls-ca-bundle.pem search SimpleHTTPServer
ComplexHTTPServer (0.1)      - A Multithreaded Python SimpleHTTPServer
SimpleTornadoServer (1.0)    - better SimpleHTTPServer using tornado
rangehttpserver (1.2.0)      - SimpleHTTPServer with support for Range requests
</code></pre>

<p>However, I want this to work without having to specify the certificate manually every time.  I am hoping to update the certificate chain that python uses:</p>

<pre><code>$ python -c "import ssl; print(ssl.get_default_verify_paths())"
DefaultVerifyPaths(cafile=None, capath=None, openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/local/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/local/ssl/certs')
</code></pre>

<p>I have verified that through a series of symlinks, that /usr/local/ssl/cert.pem points to the same file.  However, if I execute <code>pip</code>, I still get the <code>[SSL: CERTIFICATE_VERIFY_FAILED]</code> error message.</p>

<p>I uninstalled the Windows version of python, and reinstalled the Cygwin version of python.  With it, I ran <code>easy_install-2.7 pip</code>.  Now at least I am able to execute pip with the full certificate path without an error message:</p>

<pre><code>$ pip --cert /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem search simpleHttpServer
LittleHTTPServer (0.5.0)     - Little bit extended SimpleHTTPServer
SimpleHTTP404Server (0.2.0)  - A Python SimpleHTTPServer, but serves 404.html if a page is not found.
django-localsrv (0.1.2)      - Django app for serving static content from different sources (files, strings, urls, etc.) at custom paths,
</code></pre>

<p>Just to be safe, I also tried updating the SSL_CERT_DIR varaible to point to /etc/pki/ca-trust-extracted/pem and set the SSL_CERT_FILE to /etc/pki/ca-trust-extracted/pem/tls-ca-bundle.pem but these do not work:</p>

<pre><code>$ set | grep SSL
SSL_CERT_DIR=/etc/pki/ca-trust/extracted/pem
SSL_CERT_FILE=/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem

$ python -c "import ssl; print(ssl.get_default_verify_paths())"
DefaultVerifyPaths(cafile='/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem', capath='/etc/pki/ca-trust/extracted/pem', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/ssl/certs')


$ pip search simpleHttpServer
Exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/pip-8.1.2-py2.7.egg/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  ...
  ...
  File "/usr/lib/python2.7/site-packages/pip-8.1.2-py2.7.egg/pip/_vendor/requests/adapters.py", line 477, in send
    raise SSLError(e, request=request)
SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
</code></pre>

<p>What am I doing wrong?  Is this a cygwin vs Windows problem?  Which PEM files do I need to update?  </p>

<p>You can add pip command line option defaults to its configuration file. In windows, it should be located under %APPDATA%\pip\pip.ini.</p>

<p>To add a certificate, put the following lines in the file:</p>

<pre><code>[global]
cert = windows path to your certificate
</code></pre>

python windows ssl https cygwin