Uploaded image for project: 'Python Driver'
  1. Python Driver
  2. PYTHON-1627

Unable to connect with PyMongo 3.7.1, x509 SSL Certificate, and SSH Tunnels

    • Type: Icon: Bug Bug
    • Resolution: Works as Designed
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 3.7.1
    • Component/s: API, Auth
    • Labels:
    • Environment:
      MacOS Sierra; Anaconda Python 2.7.15; PyMongo 3.7.1

      I am trying to connect to a MongoDB Database on another server domain. The only problem is that to connect to the server domain requires a specialized version of Kerberos. To overcome this, I was using SSH Tunnels to open a local port for PyMongo to interface with the database and we designed our Security Certificate specifically for this eventuality as a precaution. I know that the tunnel is functioning properly as the Mongo Shell and Robo 3T both are able to connect to the database and display the data. However, with PyMongo version 3.7.1, I get the following error:

       

      ServerSelectionTimeoutError: hostname '127.0.0.1' doesn't match either of '<redacted server1>', '<redacted server1 wildcard domain>', '127.0.0.1' 

      {{}}

       

      The certificate was setup with the explicit <server name> as well as *.server_domain.com in the DNS list for the x509 certificate in the event we had to move our MongoDB to another server location in the domain. We also added 127.0.0.1 for the few users located outside of the Domain who would need to use SSH Tunnels to access the database.

      Using PyMongo, we get the following error:

      from pymongo import MongoClient
      client = MongoClient('127.0.0.1', 27017, ssl_ca_certs='/Users/<user>/ssl_cert_location/mongodb.pem')
      db = client['admin']
      db.authenticate('<username>', '<password>')
      
      ---------------------------------------------------------------------------
      ServerSelectionTimeoutError               Traceback (most recent call last)
      <ipython-input-26-ca905a055830> in <module>()
      ----> 1 db.authenticate('<username>', '<password>')
      
      /Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/database.pyc in authenticate(self, name, password, source, mechanism, **kwargs)
         1272             self.name,
         1273             credentials,
      -> 1274             connect=True)
         1275
         1276         return True
      
      /Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/mongo_client.pyc in _cache_credentials(self, source, credentials, connect)
          607         if connect:
          608             server = self._get_topology().select_server(
      --> 609                 writable_preferred_server_selector)
          610
          611             # get_socket() logs out of the database if logged in with old
      
      /Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/topology.pyc in select_server(self, selector, server_selection_timeout, address)
          222         return random.choice(self.select_servers(selector,
          223                                                  server_selection_timeout,
      --> 224                                                  address))
          225
          226     def select_server_by_address(self, address,
      
      /Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/topology.pyc in select_servers(self, selector, server_selection_timeout, address)
          181         with self._lock:
          182             server_descriptions = self._select_servers_loop(
      --> 183                 selector, server_timeout, address)
          184
          185             return [self.get_server_by_address(sd.address)
      
      /Users/<user>/anaconda2/lib/python2.7/site-packages/pymongo/topology.pyc in _select_servers_loop(self, selector, timeout, address)
          197             if timeout == 0 or now > end_time:
          198                 raise ServerSelectionTimeoutError(
      --> 199                     self._error_message(selector))
          200
          201             self._ensure_opened()
      
      ServerSelectionTimeoutError: hostname '127.0.0.1' doesn't match either of '<redacted server1>', '<redacted server1 wildcard domain>', '127.0.0.1'
      

      The most important part of this error being hostname '127.0.0.1' doesn't match '127.0.0.1'. This makes zero sense to me as it clearly does match and both the Mongo Shell and Robo 3T have zero qualms using this x509 SSL Certificate for connecting to the Database.

      With the Mongo shell from outside the Domain, there does not seem to be an issue:

      $  pkinit -f <user>
           <user> PIN:  *****************
      
      $  /usr/local/ossh/bin/ssh -4K -nNT -L 27017:127.0.0.1:<mongo_port> <user>@<server1>
      
      $ ./mongo --host 127.0.0.1 --port 27017 --ssl --sslCAFile ~/ssl_cert_location/mongodb6.pem
      
          MongoDB shell version v4.0.1
          connecting to: mongodb://127.0.0.1:27017/
          MongoDB server version: 3.6.5
          WARNING: shell and server versions do not match
        MongoDB Enterprise > use admin
          switched to db admin
      

      So, the tunnel is functioning as it should and MongoDB does not have any issues with the SSL x509 Certificate. So that begs the question of why PyMongo cannot handle the given x509 Certificate? I am not using any leading or trailing dots in the list of hostnames which seems to be what all the threads concentrate on when searching for this error. I explicitly give the exact hostname that is listed as one of the Alternate DNS hostnames from the x509 certificate.

      I would greatly appreciate any help anyone can give me concerning this error. Thanks in advance.

      {{}}

            Assignee:
            shane.harvey@mongodb.com Shane Harvey
            Reporter:
            Dcossey014 David Cossey
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: