1

The IT department in my company recently changed something (probably DPS) and now pip miserably fails because they're using a self-signed certificate.

I've tried to follow a number of solutions, mainly How to add a custom CA Root certificate to the CA Store used by pip in Windows?, but I'm still getting SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')) errors and have to resort to --trusted-host pypi.org.

  1. I've tried to follow How to add a custom CA Root certificate to the CA Store used by pip in Windows? to the letter. I've tried both the open_ssl and the browser methods.
  2. I've tried to copy the certificate file to a folder
  3. I've tried to install python-certifi-win32
  4. I've tried to explicitly use a certificate file
  5. I've tried exporting all my company's root certificates from the Windows certificate store and appending them to the cacert.pem file.

I still get a CERTIFICATE_VERIFY_FAILED error:

pip install -U black --cert="C:\Users\zbhhrc\certs\cacert.pem" -vvv
Using pip 20.2.4 from C:\Users\zbhhrc\Anaconda3\lib\site-packages\pip (python 3.8)
Non-user install because site-packages writeable
Created temporary directory: C:\Users\zbhhrc\AppData\Local\Temp\pip-ephem-wheel-cache-nq6jwf6e
Created temporary directory: C:\Users\zbhhrc\AppData\Local\Temp\pip-req-tracker-h3ul3bgj
Initialized build tracking at C:\Users\zbhhrc\AppData\Local\Temp\pip-req-tracker-h3ul3bgj
Created build tracker: C:\Users\zbhhrc\AppData\Local\Temp\pip-req-tracker-h3ul3bgj
Entered build tracker: C:\Users\zbhhrc\AppData\Local\Temp\pip-req-tracker-h3ul3bgj
Created temporary directory: C:\Users\zbhhrc\AppData\Local\Temp\pip-install-o8t0ufor
1 location(s) to search for versions of black:
* https://pypi.org/simple/black/
Fetching project page and analyzing links: https://pypi.org/simple/black/
Getting page https://pypi.org/simple/black/
Found index url https://pypi.org/simple
Getting credentials from keyring for https://pypi.org/simple
Getting credentials from keyring for pypi.org
Looking up "https://pypi.org/simple/black/" in the cache
Request header has "max_age" as 0, cache bypassed
Starting new HTTPS connection (1): pypi.org:443
Incremented Retry for (url='/simple/black/'): Retry(total=4, connect=None, read=None, redirect=None, status=None)
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)'))': /simple/black/
Starting new HTTPS connection (2): pypi.org:443
Incremented Retry for (url='/simple/black/'): Retry(total=3, connect=None, read=None, redirect=None, status=None)
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)'))': /simple/black/
Starting new HTTPS connection (3): pypi.org:443
Incremented Retry for (url='/simple/black/'): Retry(total=2, connect=None, read=None, redirect=None, status=None)
WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)'))': /simple/black/
Starting new HTTPS connection (4): pypi.org:443
Incremented Retry for (url='/simple/black/'): Retry(total=1, connect=None, read=None, redirect=None, status=None)
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)'))': /simple/black/
Starting new HTTPS connection (5): pypi.org:443
Incremented Retry for (url='/simple/black/'): Retry(total=0, connect=None, read=None, redirect=None, status=None)
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)'))': /simple/black/
Starting new HTTPS connection (6): pypi.org:443
Could not fetch URL https://pypi.org/simple/black/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: /simple/black/ (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)'))) - skipping

Any help is welcome!!

Edit:

I've run the suggested curl test:

curl -vv https://pypi.org/simple/black --cacert cacert.pem
* Expire in 0 ms for 6 (transfer 0x2b3b150)
* Expire in 1 ms for 1 (transfer 0x2b3b150)
* Expire in 3 ms for 1 (transfer 0x2b3b150)
* Expire in 2 ms for 1 (transfer 0x2b3b150)
* Expire in 12 ms for 1 (transfer 0x2b3b150)
* Expire in 16 ms for 1 (transfer 0x2b3b150)
* Expire in 4 ms for 1 (transfer 0x2b3b150)
* Expire in 50 ms for 1 (transfer 0x2b3b150)
* Expire in 50 ms for 1 (transfer 0x2b3b150)
* Expire in 50 ms for 1 (transfer 0x2b3b150)
*   Trying 151.101.64.223...
* TCP_NODELAY set
* Expire in 149927 ms for 3 (transfer 0x2b3b150)
* Expire in 200 ms for 4 (transfer 0x2b3b150)
* Connected to pypi.org (151.101.64.223) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: cacert.pem
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS alert, unknown CA (560):
* SSL certificate problem: unable to get issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

The output of openssl x509 -in cacert.pem -text:

openssl x509 -in cacert.pem -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            4b:35:e2:00:98:b9:2f:6a:32:79:9f:72:a6:25:15:e3
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O = ON Semiconductor, CN = USCO09
        Validity
            Not Before: Nov  2 21:56:33 2020 GMT
            Not After : Dec  4 21:56:33 2021 GMT
        Subject: CN = *.haxx.se
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    :crypto stuff:
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:*.haxx.se
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Subject Key Identifier:
                69:DE:D9:A3:E9:BE:30:1F:99:A2:98:8A:71:95:76:2D:CF:F1:BD:58
            X509v3 Basic Constraints:
                CA:FALSE
    Signature Algorithm: sha256WithRSAEncryption
         :moar crypto stuff:
-----BEGIN CERTIFICATE-----
:lots of crypto stuff:==
-----END CERTIFICATE-----
Leonardo
  • 1,533
  • 17
  • 28
  • To help with debugging, it might be worth taking python out of the picture and trying with `curl`. You can use curl to perform a GET request with your custom CA bundle eg `curl -vv https://pypi.org/simple/black --cacert cacert.pem`. Also this linked SO question mentions using the `openssl` tools to inspect the certificate authorities X.509 data https://serverfault.com/questions/643758/curl-with-custom-certificate – Josh Peak May 20 '21 at 20:55
  • `curl: (60) SSL certificate problem: unable to get issuer certificate` suggests there is a problem with the certificate in `cacert.pem` OR how IT has setup your specific MitM proxy. What is the output of `openssl x509 -in cacert.pem -text`? An alternative to explore is ask IT to put pypi.org on an exception list. Also I think the output of `echo quit | openssl s_client -showcerts -servername "curl.haxx.se" -connect curl.haxx.se:443 > cacert.pem` may need to be tidied up to only contain the `---- BEGIN CERTIFICATE ---- .... ---- END CERTIFICATE ----` sections and none of the cruft around them. – Josh Peak May 21 '21 at 03:36
  • I think I see the problem. I was expecting about 3-4 certificate entries. A certificate is like a passport in that it should be signed and issued by “the passport office” (Certificate Authority) to establish trust. So normally if you are behind a packet sniffing proxy you should also see the MitM self-signed certificates re-signing the request. So that file should list the certificates of all the authorities (passport offices) you trust for the duration of the request. From the other question, it mentions to grab a copy of the CAs that Mozilla publish. That one has 129 authorities. – Josh Peak May 23 '21 at 07:58
  • So the trust verification will require all of those 129 authorities from https://curl.se/docs/caextract.html and if you are behind a self-signed certificate you should merge yours into the caextract too. I’d be curious the result of the above diagnostic commands after trying that. Actually I’m pretty stumped after that sorry. You’re venturing into new frontiers I haven’t explored yet. – Josh Peak May 23 '21 at 08:01

0 Answers0