I am having difficulty connecting to mongo v2.6 using x509 certificates for authentication from Java/Groovy. I have built mongo with ssl and feel I have it configured correctly.
Our project has two applications that connect to Mongo - one written in NodeJS and one written in Java/Groovy. The NodeJS project is successfully able to authenticate using an X509 Certificate and query. Additionally, I am able to shell into mongo by specifying ssl and providing the PEM file on the command line. However, I am unable to connect to mongo using the Java Mongo Driver. I would greatly appreciate some assistance and here are the steps I have taken thus far:
Building MongoDB 2.6 to run with ssl using SCONS:
I have downloaded the 2.6 release of MongoDB from the mongodb github page
Then, built it with scons to include ssl
scons --64 --dd --ssl all
scons --ssl --prefix=/opt/mongo install
Generating Keys for Mongo::
I generated the following keys/certs
openssl req -new -newkey rsa:1024 -nodes -out myMongo.req -keyout myMongo.key -subj "/C=US/ST=myState/CN=myMongo/OU=myUnit/L=myLocation" -days 36500
openssl x509 -CA myCA.pem -CAkey myCa.key -CAserial myCa.srl -req -in myMongo.req -out myMongo.pem -days 36500
This gives me the following files:
- myMongo.key ( Containing a private key )
- myMongo.pem ( Containing a certificate )
- myMongo.req ( Containing a certificate request ) (I'm not sure if I need this one, and haven't used it yet )
In compliance with the mongo instructions, I concatenated the key and certificate together into 1 file
cat myMongo.key myMongo.pem > combined.pem
Following the mongo instructions for x509 configuration:
openssl x509 -in combined.pem -inform PEM -subject -nameopt RFC2253
which gives me the subject: "C=US,ST=myState,CN=myMongo,OU=myUnit,L=myLocation"
I then add that subject to the users on the database
db.getSiblingDB("$external").runCommand(
{
createUser: "C=US,ST=myState,CN=myMongo,OU=myUnit,L=myLocation",
roles: [
{ role: 'readWrite', db: 'mydbName' },
{ role: 'userAdminAnyDatabase', db: 'admin' }
],
writeConcern: { w: "majority" , wtimeout: 5000 }
}
)
In my mongod.conf file, I specify the following options:
sslMode = requireSSL
sslPEMKeyFile = /path/to/my/combined.pem
sslCAFile = /path/to/myCA.pem
At this point, I can launch
mongod --config /path/to/my/mongod.conf
after launching, I can only access the shell by specifying
mongo --ssl -- sslPEMKeyFile /path/to/my/combined.pem
Connecting to MongoDB from Java-Mongo-Driver version 2.12.0
I'm trying to follow the example given on the java-mongo-driver github page:
The code fails with an exception which we will offer up below, but it seems pretty strange that you would attempt to connect by just providing the DN in string format rather than actually attaching a certificate to the request. Doesn't that defeat the entire purpose of X509 to begin with? We looked at the Ruby example and they attach a pem file. My team understands java keystores and truststores, and will happily send that pem file along its merry way if that's what we're supposed to be doing. Additionally, when using the node driver we're absolutely specifying the location of the PEM file.
The final result is this. We can instantiate the MongoClient just fine, and we can even get a collection using the db object. When we attempt to query any collection in any way, we get back an exception whose message is "Unable to connect to any server."
It seems logical that the MongoClientOptions.Builder would allow us to add this information as that seems to be how it's done elsewhere. But we did an introspection of the class just in case it was missing from the documentation, and there's nothing in there that relates to x509 as far as we can tell.
I appreciate your help.