rubymongodbsslmongodb-ruby

Connecting to Mongod via Ruby driver using SSL returns Mongo::ConnectionFailure


I want to use SSL with MongoDB. It's not enabled by default so one has to compile from source with the necessary options. I followed the official documentation and got the v2.6.4 binary built and running nicely on a freshly deployed server running Ubuntu 14.04. All good so far.

Next I set up mongod as described in the official docs. I did follow their example of using a self-certified key for testing purposes. And the relevant part of the config looks like:

...
net:
   bindIp: 127.0.0.1
   port: 27017
   ssl:
      mode: requireSSL
      PEMKeyFile: /opt/mongo/security/mongodb.pem
...

If I then run the client and specify to use SSL I connect fine. ($ mongo --ssl). FWIW if I try without the --ssl argument then it doesn't connect.

Ok, time to link up via Ruby. I'm on the same server and I try the following ruby script:

require 'rubygems'
require 'mongo'

client = Mongo::MongoClient.new('localhost', 27017, {:ssl => true})

Nope. It's not having it:

/home/test/.rvm/gems/ruby-1.9.3-p547/gems/mongo-1.11.1/lib/mongo/mongo_client.rb:422:in `connect': Failed to connect to a master node at localhost:27017 (Mongo::ConnectionFailure)
from /home/test/.rvm/gems/ruby-1.9.3-p547/gems/mongo-1.11.1/lib/mongo/mongo_client.rb:661:in `setup'
from /home/test/.rvm/gems/ruby-1.9.3-p547/gems/mongo-1.11.1/lib/mongo/mongo_client.rb:177:in `initialize'
from test_mongo_ssl.rb:8:in `new'
from test_mongo_ssl.rb:8:in `<main>'

So best to make sure that there's nothing wrong with the default connection without SSL. I disable SSL on mongod and restart. Then try the ruby script again, this time without the ssl option:

...
client = Mongo::MongoClient.new('localhost', 27017)

And it's fine. Therefore I feel I've narrowed it down to the ruby driver & ssl, but beyond that there's little else to go on.

EDIT I tried their Python driver on the same server and used their example program:

from pymongo import MongoClient
c = MongoClient(host="localhost", port=27017, ssl=True)

And that did connect OK. So at least I can feel fairly confident that the mongod is configured properly and the issue lies somewhere within the Mongo Ruby driver. Quite possibly a bug in their current driver (v1.11.1).

UPDATE I've also had success connecting via ssl using the node.js driver:

var mongo = require('mongodb');
var database = new mongo.Db("my_database", new mongo.Server("127.0.0.1", 27017, {ssl:true} ), {w:0});
database.open(function(err, db) {
    if(err) throw err;
    db.authenticate('user', 'password', function(err, result) {
      var collection = db.collection('foo');
      collection.findOne(function(err, item) {
      if(err) throw err;
        console.log(item);
        db.close();
      });
    });
});

There it seems to be increasingly likely that there's either a bug in the ruby driver, or the documentation is incomplete and not explaining accurately how to use SSL connections. Therefore I've opened a new issue on MongoDB's issue tracker to hopefully get to the bottom of this.


Solution

  • Rather embarrassingly, the solution to this issue was my /etc/hosts file had a typo for the localhost entry:

    127.0.0.1   localhost.localdomain locahost
    

    As you can see, it's missing the second letter L in "localhost". (I suspect it went missing during an accidental vim gesture.) Therefore to resolve I just had to reinstate the missing "l":

    127.0.0.1   localhost.localdomain localhost
    

    It's still a mystery as to why the Python sample worked correctly. And it's because of that I didn't twig earlier that it was a problem with the hosts file.