1

I have a python app that connects to google calendar when it opens. It stopped working at my job after infrastructure updated our security. Now, whenever I run it, it gives me this error

google.auth.exceptions.TransportError: HTTPSConnectionPool(host='oauth2.googleapis.com', port=443): Max retries exceeded with url: /token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)')))

I spoke with cybersecurity, and they sent me 2 .pem certificat to approve on my app, but they didn't said how to do it.

I researched a lot online, I tried this:

Import SSL 
ca_cert1_path = "V:\test2.pem"
ca_cert2_path = "V:\RootCA5.pem"
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_verify_locations(cafile=ca_cert1_path)
mcontext.load_verify_locations(cafile=ca_cert2_path)

but it didn't worked, still giving me the same error.

I also Tried this which gave me the same error again:

requests.get('https://oauth2.googleapis.com', verify=False)

Here is the complete error :

Traceback (most recent call last):
File "requests\adapters.py", line 449, in send
File "urllib3\connectionpool.py", line 725, in urlopen
File "urllib3\util\retry.py", line 439, in increment
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='oauth2.googleapis.com', port=443): Max retries exceeded with url: /token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "google\auth\transport\requests.py", line 181, in __call__
File "requests\sessions.py", line 530, in request
File "requests\sessions.py", line 643, in send
File "requests\adapters.py", line 514, in send
requests.exceptions.SSLError: HTTPSConnectionPool(host='oauth2.googleapis.com', port=443): Max retries exceeded with url: /token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)')))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "main.py", line 7, in <module>
File "main_controller.py", line 16, in __init__
File "quickstart.py", line 48, in initiate_calendar_service
File "google\oauth2\credentials.py", line 210, in refresh
File "google\oauth2\_client.py", line 248, in refresh_grant
File "google\oauth2\_client.py", line 105, in _token_endpoint_request
File "google\auth\transport\requests.py", line 186, in __call__
File "<string>", line 3, in raise_from
google.auth.exceptions.TransportError: HTTPSConnectionPool(host='oauth2.googleapis.com', port=443): Max retries exceeded with url: /token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)')))
[47456] Failed to execute script 'main' due to unhandled exception!

Any help would be appreciated

BTW, the app works on ANY personnal pc. The code ISN'T the problem. It doesn't work on any pc connected at my job (under my job's network).

  • the lazy, somewhat less secure solution is verify=False – Carbon Jun 12 '23 at 00:25
  • Does this answer your question? [Python error using SSL certificate with proxy](https://stackoverflow.com/questions/45991724/python-error-using-ssl-certificate-with-proxy) – jordanm Jun 12 '23 at 00:26
  • @Carbon I also tried this, it didn't worked out. It still gave me the same error – user22057918 Jun 12 '23 at 00:30
  • Do you actually have code that works with one certificate, yet? How confident are you that the issue is with the code, rather than *the certificate*? (Where the error message says "certificate verify failed: self signed certificate in certificate chain", exactly what do you suppose this means?) – Karl Knechtel Jun 12 '23 at 00:31
  • @jordanm How to verify 2 certificates instead of one? And which URL should I add instead of "url"? r = requests.get(url, proxies=PROXIES, auth=PROXY_AUTH, verify = '../static/crawlera-ca.crt', allow_redirects=False) – user22057918 Jun 12 '23 at 00:31
  • @KarlKnechtel the code works because i tried it on 5-6 personal pc's, and they always run. The app simply doesnt work on any PC under my work network. – user22057918 Jun 12 '23 at 00:32

2 Answers2

0

If you don't want to run an un-secure connection with verify=False, you can force-feed a private key and certificate via their paths as per the documentation:

import requests

# If your certificates already contain their private key:
cert='/where/is/the/file/client.pem'

# Or if they are not: cert = ('/path/client.cert', '/path/client.key')

result = requests.get('https://my_url.com', cert=cert)

You have to know what your cert files contain, but those files are important security features and absolutely should not be shared on the internet. If you don't know just ask the people who generated them for you.

As to why you have 2 files:

  • either you are pinging different URLs and need both of them
  • or what seems more likely seeing the naming of the second PEM file, they also gave you the certificate of the Certificate Authority, and you won't be needing that one.
scr
  • 853
  • 1
  • 2
  • 14
0

Possible cause

If your script works on all computers except for any computer belonging to your company, that could be because of its security policy that might inspect your SSL/TLS connections by doing something similar to a Man in the Middle (here is some doc about it by Checkpoint).

Issues with in-script exceptions

As some people here already said, adding exceptions in your script might not be the safest option. Furthermore, if you need to run this script on several computers and each one has to trust different certificates, are you going to import each certificate in your script ? You could end up with more lines of importing certificates than 'real' code.

Certificate importation systemwide

The good practice in this case would be importing on each computer the certificates it should trust. If the system trusts them, then your script should too. This way, you also remove any error you could have because of the self signed root certificate.

Linux

Here is how to do it depending on your Linux system, to quote the article for Debian:

  • Copy PEM files to /usr/local/share/ca-certificates
  • Create the /usr/local/share/ca-certificates directory if not yet present
  • Copy the PEM files created in the previous step into the directory, change the file name suffix to *.crt.
  • Integrate certificates into the system's certificate set: update-ca-certificates

Windows

For Windows, here is the official procedure, but I find it to be less pertinent than this unofficial one in your case:

  • .\certutil.exe -addstore -f "Root" 'C:\Users\path\to\cert.pem'

Make your script work with the imported certs

Linux

You can then make sure your Python script takes the system certificates by exporting an environment variable: export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt, as explained here: Python Requests - How to use system ca-certificates (debian/ubuntu)?

Windows

In Windows, you can install the pip-system-certs module (see here) to make Python automatically use system certs:

pip install pip_system_certs
  • Hello. Thanks for your reply. "Copy PEM files to /usr/local/share/ca-certificates". What is the path for Windows? – user22057918 Jun 12 '23 at 14:57
  • You're right, I presumed you were on Linux. I added instructions for Windows. – The Coding Penguin Jun 12 '23 at 15:00
  • thanks for the edit, now that I added all the .pem, how to "Make your script work with the imported certs" ? that is also linux isnt it? Thanks again! – user22057918 Jun 12 '23 at 15:22
  • In Windows there is a special module to install, I added it too :) – The Coding Penguin Jun 12 '23 at 15:40
  • So, if all the "Good certificates" are already installed in my mmc, and i installed the special module in my code (pip_system_certs), and i compile the code, and open the .exe on my work pc, it should work? – user22057918 Jun 12 '23 at 15:50
  • Also, It says, on the doc, that it won't work with pyinstaller. I use pyinstaller to create the executable. They say that i have to add "import pip_system_certs.wrapt_requests" but once i do, it's greyed out because i don't use it in the code. Would it still work? – user22057918 Jun 12 '23 at 15:56
  • I am not familiar with PyInstaller, but if I understand the documentation correctly, you just need to import the module, not necessarily to use it. That makes it greyed out in most editors indeed, but the fact that it is greyed out is not an error per se. That's also confirmed here: https://gitlab.com/alelec/pip-system-certs/-/issues/7 . Make sure to write the import instruction at the very top of your program. – The Coding Penguin Jun 12 '23 at 16:05
  • ok, i did it . the good news is, it doesnt raise as much errors anymore. The only error i am having now is : ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076) – user22057918 Jun 12 '23 at 16:26
  • i have the .pem our organization use. I just can't seem to add it to my code without problem, and i don't know which URL to add. I'm hitting google API's. Which url should I add ? google.com? – user22057918 Jun 12 '23 at 17:09
  • Check if your certificates are correctly imported in your computer: if you access the URL you hit with your script within a browser, do you get a warning about the certificate? If so, the importation could have gone wrong. – The Coding Penguin Jun 13 '23 at 07:59