I am trying to set up passwordless authentication between Meteor.js apps and Mongo server.
To do that, I need to present pem and crt files to the connection. MONGO_URL connection string takes only parameters about how to perform auth, but no references to files with certs. I assume, I need to pass in the cert file to connection as a parameter. Similar as described in here.
How to do it in Meteor.js?
Basically I want to achieve equivalent of doing:
mongo mongo.example.com/example -ssl -sslPEMKeyFile client.pem --sslCAFile server.crt
and then as described here
db.getSiblingDB("$external").auth(
{
mechanism: "MONGODB-X509",
user: "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry"
}
)
this works fine when using mogo client, but within Meteor I have so far only gotten to the point of understanding that I would most likely need to use connection string below (or something similar)
MONGO_URL=mongodb://mongo.example.com:27017/example?ssl=true&authSource=$external&authMechanism=MONGODB-X509
but question remains - how to pass certificates to the connection?
Update: there is answer that deals with the issue using native noddejs mongo driver. question is - how to port this to Meteor.
Update 2015-12-31: I have accepted the answer that points to using different connection object when defining the Collection. It is a hassle to do it for each collection separately, but it seems to be the only way this is doable right now. Also, if need arises, probably some MySslCollection can be created, that others can use to inherit connection details. This has not been tested.
As pointed out by another answer, the options here have changed as of version 1.4 and you can now call
Mongo.setConnectionOptions({ ... });
please see the documentation for more details.
This was a fun rabbit hole... I think I have found one solution/workaround to your problem (there may be others).
The quick description of my workaround is to specify the mongodb server options when creating your collections. This must be done on the server code only to avoid handing out your ssl key/cert. Like so:
new Mongo.Collection("collection_name", {
connection: DDP.connect("mongodb://mongo.example.com:27017/example?ssl=true&authSource=$external&authMechanism=MONGODB-X509", {
server: {
sslCert:[CERT_CONTENTS],
sslKey:[KEY_CONTENTS],
sslValidate:false
}
})
});
Hacky methods
Since you asked if there is a way to do this without adding the options to every collection created I decided to take another look. I have not tested these methods, but they seem sound, if very hacky.
1) Set up a function to run on the connection status using undocumented options argument passthru in the reconnect method. https://github.com/meteor/meteor/blob/master/packages/ddp-client/livedata_connection.js#L996
Tracker.autorun(function () {
var status = Meteor.status();
if(status == 'failed')
Meteor.reconnect({
server: {
sslCert:[CERT_CONTENTS],
sslKey:[KEY_CONTENTS],
sslValidate:false
}
});
});
2) Monkey patch the default connection code (this I am less sure of working since I haven't taken the time to understand when the mongo internal code for this actually gets set in the first place). https://github.com/meteor/meteor/blob/dc3cd6eb92f2bdd1bb44000cdd6abd1e5d0285b1/packages/mongo/remote_collection_driver.js
MongoInternals.defaultRemoteCollectionDriver = _.once(function () {
var connectionOptions = {
server: {
sslCert:[CERT_CONTENTS],
sslKey:[KEY_CONTENTS],
sslValidate:false
}
};
var mongoUrl = process.env.MONGO_URL;
if (process.env.MONGO_OPLOG_URL) {
connectionOptions.oplogUrl = process.env.MONGO_OPLOG_URL;
}
if (! mongoUrl)
throw new Error("MONGO_URL must be set in environment");
return new MongoInternals.RemoteCollectionDriver(mongoUrl, connectionOptions);
});
The journey to these answers:
Starting from the answer you linked, I found where Meteor creates its MongoDB connection: https://github.com/meteor/meteor/blob/dc3cd6eb92f2bdd1bb44000cdd6abd1e5d0285b1/packages/mongo/mongo_driver.js#L173
Then I found where that was getting called: https://github.com/meteor/meteor/blob/3d2282d9ad0b570b913a70d215cd968019d912df/packages/mongo/remote_collection_driver.js#L4
Tracking down where that got called led me to the fact that Collections instantiate the connection: https://github.com/meteor/meteor/blob/15cdbca24888bfdff3ad43c1891a1719c09b3dc5/packages/mongo/collection.js#L102
I could see from there that some options can override the use of the default Mongo connnection that has no options specified. Looking in the Meteor docs for collections http://docs.meteor.com/#/full/mongo_collection shows:
Options
connection Object
The server connection that will manage this collection. Uses the default connection if not specified. Pass the return value of calling DDP.connect to specify a different server. Pass null to specify no connection. Unmanaged (name is null) collections cannot specify a connection.
So looking at the docs for DDP.connect http://docs.meteor.com/#/full/ddp_connect we reach a dead end since it only takes a url... but wait... after searching through the code on github I can see that DDP.connect does take an options param: https://github.com/meteor/meteor/blob/master/packages/ddp-client/livedata_connection.js#L1641
Thus concludes our quest.
Both of the previous answers are correct (craigts, user1887896), however I'd like to add:
Mongo.setConnectionOptions
might actually be used, as there is little documentation available).accounts-base
), you must ensure your call to Mongo.setConnectionOptions
happens before they are loaded.
.meteor/packages
, i.e. placing danwild:set-connection-options
at the top of the file.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With