Disable Python requests SSL validation for an imported module - python

I'm running a Python script that uses the requests package for making web requests. However, the web requests go through a proxy with a self-signed cert. As such, requests raise the following Exception:
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)",)
I know that SSL validation can be disabled in my own code by passing verify=False, e.g.: requests.get("https://www.google.com", verify=False). I also know that if I had the certificate bundle, I could set the REQUESTS_CA_BUNDLE or CURL_CA_BUNDLE environment variables to point to those files. However, I do not have the certificate bundle available.
How can I disable SSL validation for external modules without editing their code?

Note: This solution is a complete hack.
Short answer: Set the CURL_CA_BUNDLE environment variable to an empty string.
Before:
$ python
import requests
requests.get('http://www.google.com')
<Response [200]>
requests.get('https://www.google.com')
...
File "/usr/local/lib/python2.7/site-packages/requests-2.17.3-py2.7.egg/requests/adapters.py", line 514, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)",)
After:
$ CURL_CA_BUNDLE="" python
import requests
requests.get('http://www.google.com')
<Response [200]>
requests.get('https://www.google.com')
/usr/local/lib/python2.7/site-packages/urllib3-1.21.1-py2.7.egg/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning)
<Response [200]>
How it works
This solution works because Python requests overwrites the default value for verify from the environment variables CURL_CA_BUNDLE and REQUESTS_CA_BUNDLE, as can be seen here:
if verify is True or verify is None:
verify = (os.environ.get('REQUESTS_CA_BUNDLE') or
os.environ.get('CURL_CA_BUNDLE'))
The environment variables are meant to specify the path to the certificate file or CA_BUNDLE and are copied into verify. However, by setting CURL_CA_BUNDLE to an empty string, the empty string is copied into verify and in Python, an empty string evaluates to False.
Note that this hack only works with the CURL_CA_BUNDLE environment variable - it does not work with the REQUESTS_CA_BUNDLE. This is because verify is set with the following statement:
verify = (os.environ.get('REQUESTS_CA_BUNDLE') or os.environ.get('CURL_CA_BUNDLE'))
It only works with CURL_CA_BUNDLE because '' or None is not the same as None or '', as can be seen below:
print repr(None or "")
# Prints: ''
print repr("" or None )
# Prints: None

I saw this hack only due to some trouble with my private CA.
The given hack with CURL_CA_BUNDLE='' will not longer work in 2022 with next minor release of requests (that means 2.28 ?).
Please refer to GH issue 6071 which was fixed 6 days before in Feb. 2022

Related

Having 'certificate verify failed' error when registering a model on Azure

Today, I got an error when I wanted to register a new model on Azure work space. This error wasn't happening before! The only change that I have is the model itself but the code is the same:
from azureml.core import Workspace
from azureml.core.compute import AksCompute, ComputeTarget
from azureml.core.webservice import Webservice, AksWebservice
from azureml.core.image import Image
from azureml.core.model import Model
import azureml.core
from azureml.core.workspace import Workspace
from azureml.core.model import Model
ws = Workspace.from_config()
model_reg = Model.register(model_path = "./outputs/model_final",
model_name = "ModelX",
tags = {'area': "XXX", 'type': "deep"},
description = "Model 1",
workspace = ws)
And here is the error that I got:
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='xxx
.blob.core.windows.net', port=443): Max retries exceeded with url: /azureml/Loca
lUpload/190530T093046-fc5a89ca/tfModel.tar.gz?sv=2018-03-28&sr=b&sig=9FFnsaefR9w
PkR%2FvsMlnQYrA2wlnJG7Cu%2BP9%2FePPZEY%3D&st=2019-05-30T08%3A20%3A46Z&se=2019-05
-31T08%3A30%3A46Z&sp=rcw&comp=block&blockid=TURBd01EQXdNREF3TURBd01EQXdNREF3TURB
d01EQXdNREF3TURBd01EQSUzRA%3D%3D (Caused by SSLError(SSLError("bad handshake: Er
ror([('SSL routines', 'tls_process_server_certificate', 'certificate verify fail
ed')],)",),))
I tried to update all the python packages and even creating a new conda env with fresh installation of all packages, but still getting this error.
Any help or similar experience?
Just as reference, there may be two reasons cause this issue.
Network issue. The network environment for running this Python script changed. May now the script run through a proxy like Fiddler which not support or enable SSL/TLS feature, or some IP restrictions in your network cause it like the SO thread SSL Certificate error while doing a request via python.
The target site upgraded SSL version. You can follow the SO thread answer Django paypalrestsdk error - OpenSSL.SSL.Error: [('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')] to check.
Hope it helps.

Set verify_certs=False yet elasticsearch.Elasticsearch throws SSL error for certificate verify failed

self.host="KibanaProxy"
self.Port="443"
self.user="test"
self.password="test"
I need to suppress certificate validation. It works with curl when using option -k on command line. But while connecting using elasticsearch.Elasticsearch from Elasticsearch python module, it throws error.
_es2 = Elasticsearch([self.host], port=self.port, scheme="https", http_auth=(self.user, self.password), use_ssl=True, verify_certs=False)
_es2.info()
Error:
raise SSLError('N/A', str(e), e)
elasticsearch.exceptions.SSLError: ConnectionError([SSL: CERTIFICATE_VERIFY_FAILED]
certificate verify failed (_ssl.c:590)) caused by: SSLError([SSL:
CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590))```
Found it.
While reading this post https://github.com/elastic/elasticsearch-py/issues/275, i got to know about connection_class. Looked for some standard or predefined method related to it so found https://elasticsearch-py.readthedocs.io/en/master/transports.html
Solution:
from elasticsearch import RequestsHttpConnection
.....
_es2 = Elasticsearch([self.host], port=self.port, connection_class=RequestsHttpConnection, http_auth=(self.user, self.password), use_ssl=True, verify_certs=False)
print(es.ping())
$ ./sn.py
True
In addition to Sonali's answer, as of September 2022, the Python Elasticsearch client does not allow function parameter use_ssl=True
Adding only verify_certs=False parameter fixed my case:
Elasticsearch(hosts=[address], basic_auth=[user, password], verify_certs=False)
And es.ping() does not let you know what is the error, just returns False. In order to see the error details, you can use this single line of code
print(es.info())
TLS error caused by: TlsError(TLS error caused by: SSLError([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:997)))

SSLError( '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)'),)) in Python while accessing an url [duplicate]

This question already has an answer here:
SSL: CERTIFICATE_VERIFY_FAILED certificate verify failed
(1 answer)
Closed 4 years ago.
I am writing a script that will will update a macro enabled Excel file that is present in a given url.I am using Python3.6 for this work. I decided it to first download in a local copy then update the local copy and after updating push it back to the same url. But when I am writing code to download the file I am getting the error as-
(Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)'),))
the code that I am using is-
import requests
url = 'https://sharepoint.amr.ith.intel.com/sites/SKX/patchboard/Shared%20Documents/Forms/AllItems.aspx?RootFolder=%2Fsites%2FSKX%2Fpatchboard%2FShared%20Documents%2FReleaseInfo&FolderCTID=0x0120004C1C8CCA66D8D94FB4D7A0D2F56A8DB7&View={859827EF-6A11-4AD6-BD42-23F385D43AD6}/Copy of Patch_Release_Utilization'
r = requests.get(url)
open('Excel.xlsm', 'wb').write(r.content)
I have tried solution given in-Python requests SSL error - certificate verify failed
,but this is not working for me. How to resolve this problem?? Please help me with the solution if somebody has already tackled it.
EDIT:
I have tried using-
r=request.get(url,verify=False)
After doing this I am getting the warning as - "InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings" and also when I am trying to open the "Excel.xlsm" file so created I am getting the error message as- "Excel cannot open the file "Excel.xlsm" because the file format or file extensionis not valid.Verify that the file has not been corrupted and that the file extension matches the format of trhe file"
NOTE- I am trying to access the macro enabled Excel file(.xlsm) file
You can use the verify=False parameter to ignore verifying the SSL certificate, per the documentation:
r = requests.get(url, verify=False)

SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed while generating SMS from python script

I have my python script similar to below, Scripts works fine in my personal laptop.
import plivo
import sys
auth_id = "XXXXXX"
auth_token = "YYYYYYYYYYYY"
test = plivo.RestClient(auth_id, auth_token)
message_created = test.messages.create(
src='ZZZZZZ',
dst='+NNNNN',
text='Testing!!'
)
However while running the script in our organization PC's its throwing error
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.plivo.com', port=443): **Max retries exceeded with url**: /v1/Account/SXXXXXYW/Message/ (Cau
sed by SSLError(SSLError(1, u'[SSL: **CERTIFICATE_VERIFY_FAILED**] certificate verify failed (_ssl.c:590)'),))
I tried to add ssl._create_default_https_context = ssl._create_unverified_context and PYTHONHTTPSVERIFY=0 but unfortunately nothing works for me. Can anyone one help me how to resolve the error?
Try the solution from https://github.com/locustio/locust/issues/417
How to get rid from “SSL: CERTIFICATE_VERIFY_FAILED” Error
On Windows, Python does not look at the system certificate, it uses its own located at ?\lib\site-packages\certifi\cacert.pem.
The solution to your problem:
download the domain validation certificate as *.crt or *pem file
open the file in editor and copy it's content to clipboard
find your cacert.pem location: from requests.utils import
DEFAULT_CA_BUNDLE_PATH;
print(DEFAULT_CA_BUNDLE_PATH)
edit the cacert.pem file and paste your domain validation
certificate at the end of the file.
Save the file and enjoy requests!

Tweepy SSLError regarding ssl certificate

I am running a REST API (Search API) with Tweepy in Python. I worked the program at home and it's totally fine. But now I am working on this in different networks and I got the error message.
SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)
My code is like this.
auth = tweepy.AppAuthHandler(consumer_key, consumer_secret)
api = tweepy.API(auth,wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
I found this post
Python Requests throwing up SSLError
and set the following code (verify = false) may be a quick solution. Does anyone know how to do it or other ways in tweepy? Thank you.
In streaming.py, adding verify = False in line# 105 did the trick for me as shown below. Though it is not advisable to use this approach as it makes the connection unsafe. Haven't been able to come up with a workaround for this yet.
stream = Stream(auth, listener, verify = False)
I ran into the same problem and unfortunately the only thing that worked was setting verify=False in auth.py in Tweepy (for me Tweepy is located in /anaconda3/lib/python3.6/site-packages/tweepy on my Mac):
resp = requests.post(self._get_oauth_url('token'),
auth=(self.consumer_key,
self.consumer_secret),
data={'grant_type': 'client_credentials'},
verify=False)
Edit:
Behind a corporate firewall, there is a certificate issue. In chrome go to settings-->advanced-->certificates and download your corporate CA certificate. Then, in Tweepy binder.py, right under session = requests.session() add
session.verify = 'path_to_corporate_certificate.cer'
First, verify if you can access twitter just using a proxy configuration. If so, you can modify this line on your code to include a proxy URL:
self.api = tweepy.API(self.auth)
Adding verify=False will ignore the validation that has to be made and all the data will be transferred in plain text without any encryption.
pip install certifi
The above installation fixes the bad handshake and ssl error.
For anybody that might stumble on this like I did, I had a similar problem because my company was using a proxy, and the SSL check failed while trying to verify the proxy's certificate.
The solution was to export the proxy's root certificate as a .pem file. Then you can add this certificate to certifi's trust store by doing:
import certifi
cafile = certifi.where()
with open(r<path to pem file>, 'rb') as infile:
customca = infile.read()
with open(cafile, 'ab') as outfile:
outfile.write(customca)
You'll have to replace <path to pem file> with the path to the exported file. This should allow requests (and tweepy) to successfully validate the certificates.

Categories