26

Trying to connect to Azure CosmosDB mongo server results into an SSL handshake error.

I am using Python3 and Pymongo to connect to my Azure CosmosDB. The connection works fine if I run the code with Python27 but causes the below error when using Python3:

import pymongo
from pymongo import MongoClient
import json
import sys

def check_server_status(client, data):
   '''check the server status of the connected endpoint'''
   db = client.result_DB
   server_status = db.command('serverStatus')
   print('Database server status:')
   print(json.dumps(server_status, sort_keys=False, indent=2, separators=(',', ': ')))
   coll = db.file_result
   print (coll)
   coll.insert_one(data)

def main():
    uri = "mongodb://KEY123@backend.documents.azure.com:10255/?ssl=true&replicaSet=globaldb"
    client = pymongo.MongoClient(uri)
    emp_rec1 = {
        "name":"Mr.Geek",
        "eid":24,
        "location":"delhi"
        }
    check_server_status(client, emp_rec1)

if __name__ == "__main__":
    main()

Running this on Python3 results into below error:

pymongo.errors.ServerSelectionTimeoutError: SSL handshake failed: backendstore.documents.azure.com:10255: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)

Here is my successful output when I run the same code with Python27:

Database server status: { "_t": "OKMongoResponse", "ok": 1 } Collection(Database(MongoClient(host=['backend.documents.azure.com:10255'], document_class=dict, tz_aware=False, connect=True, ssl=True, replicaset='globaldb'), u'result_DB'), u'file_result')

abhinav singh
  • 1,024
  • 1
  • 12
  • 34
  • 4
    **VERY IMPORTANT**: several answers here suggest using `ssl_cert_reqs=ssl.CERT_NONE` or `tlsAllowInvalidCertificates=True`. They DON'T solve the issue, but just silence the error by connecting without any certificate validation, which is insecure. If you want to do that for testing, fine, but do not, I repeat, **DO NOT USE** in production environments under any circumstance! – Victor Schröder Feb 01 '23 at 23:58

9 Answers9

30

On Windows you can do like this

pip install certifi

Then use it in code:

import certifi
ca = certifi.where()

client = pymongo.MongoClient(
"mongodb+srv://username:password@cluster0.xxxxx.mongodb.net/xyzdb?retryWrites=true&w=majority", tlsCAFile=ca)
Ankit Parmar
  • 449
  • 5
  • 8
16

Solved the problem with this change:

client = pymongo.MongoClient(uri, ssl_cert_reqs=ssl.CERT_NONE)
abhinav singh
  • 1,024
  • 1
  • 12
  • 34
  • 6
    Does this just mean it doesn't use a TLS handshake? It doesn't seem like the greatest idea for something in production. – axme100 Feb 04 '20 at 21:47
  • 2
    That's fine for testing and perhaps in a development scenario when you know what you're connecting to. This isn't what I'd call a solution however. – Douglas Plumley Oct 06 '20 at 19:02
  • 1
    awesome solution to `ServerSelectionTimeoutError` ! of course that this is mostly used in testing and dev propose, do not leave this solution to production! – adir abargil Oct 14 '21 at 14:37
11

The section Troubleshooting TLS Errors of the PyMongo offical document `TLS/SSL and PyMongo introduces the issue as below.

TLS errors often fall into two categories, certificate verification failure or protocol version mismatch. An error message similar to the following means that OpenSSL was not able to verify the server’s certificate:

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

This often occurs because OpenSSL does not have access to the system’s root certificates or the certificates are out of date. Linux users should ensure that they have the latest root certificate updates installed from their Linux vendor. macOS users using Python 3.6.0 or newer downloaded from python.org may have to run a script included with python to install root certificates:

open "/Applications/Python <YOUR PYTHON VERSION>/Install Certificates.command"

Users of older PyPy and PyPy3 portable versions may have to set an environment variable to tell OpenSSL where to find root certificates. This is easily done using the certifi module from pypi:

$ pypy -m pip install certifi
$ export SSL_CERT_FILE=$(pypy -c "import certifi; print(certifi.where())")

You can try to follow the description above to fix your issue, which seems to be for Linux and Mac Users. On Windows, I can not reproduce your issue in Python 3.7 and 3.6. If you have any concern, please feel free to let me know.

Anas Tiour
  • 1,344
  • 3
  • 17
  • 33
Peter Pan
  • 23,476
  • 4
  • 25
  • 43
  • Thanks for the answer! For anyone trying to connect through Djongo, this was the only solution that worked for me. I'm on MacOs, Django 1.3, Django 2.2 BTW – José Ripoll Dec 23 '21 at 20:24
  • *Very important* is to open a new shell when running it the next time. I happened to stumble over another SO answer that mentioned it for Windows. Could've wasted many an hour if I missed it. – aydow Sep 15 '22 at 14:41
6

Faced the same issue when trying to connect mongodb from Digital Ocean, Solved by using this function with params in MongoClient:

def get_client(host,port,username,password,db):
      return MongoClient('mongodb://{}:{}/'.format(host,port),
                         username=username,
                         password=password,
                         authSource=db,
                         ssl=True,ssl_cert_reqs=ssl.CERT_NONE)

client = get_client("host-ip","port","username","password","db-name")
Aayush Bajaj
  • 89
  • 1
  • 3
4

On Mac Mojave 10.14.6 , I used (PyMongo 3.10 and python 3.7), to solve:

flask pymongo pymongo.errors.ServerSelectionTimeoutError [SSL: CERTIFICATE_VERIFY_FAILED]

Execute in terminal:

sudo /Applications/Python\ 3.7/Install\ Certificates.command

If you use other python version, only change versión number (In my case, i have Python 3.7)

3
cluster = MongoClient(
    "url",
    ssl=True,
    ssl_cert_reqs=ssl.CERT_NONE,
)
buddemat
  • 4,552
  • 14
  • 29
  • 49
  • 2
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Yunnosch Sep 12 '21 at 10:05
3

By default pymongo relies on the operating system’s root certificates.

It could be that Atlas itself updated its certificates or it could be that something on your OS changed. “certificate verify failed” often occurs because OpenSSL does not have access to the system’s root certificates or the certificates are out of date. For how to troubleshoot see TLS/SSL and PyMongo — PyMongo 3.12.0 documentation 107.

pls Try :

client = pymongo.MongoClient(connection, tlsCAFile=certifi.where())

and dont forget to install certifi

0

import ssl

Simply importing this fixed my issue. On my macbook, it worked fine on windows PC

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 27 '23 at 00:46
-1

On mac Monterey, I used pymongo 3.12.1 and virtual environment

To solve, use

ssl_cert_reqs=CERT_NONE

with mongodb url

Flair
  • 2,609
  • 1
  • 29
  • 41