Skip to content

Commit

Permalink
Added more testcases for ssl support using MongoClient.connect with url
Browse files Browse the repository at this point in the history
  • Loading branch information
christkv committed Jan 18, 2013
1 parent e4d8a49 commit ae8282e
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 16 deletions.
3 changes: 2 additions & 1 deletion lib/mongodb/connection/connection.js
Expand Up @@ -108,7 +108,7 @@ Connection.prototype.start = function() {
try {
cleartext = tls.connect(this.socketOptions.port, this.socketOptions.host, tls_options, function() {
// If we have a ssl certificate validation error return an error
if(cleartext.authorizationError && validate_certificates) {
if(cleartext.authorizationError && validate_certificates) {
// Emit an error
return self.emit("error", cleartext.authorizationError, self, {ssl:true});
}
Expand Down Expand Up @@ -147,6 +147,7 @@ Connection.prototype.start = function() {
if(this.logger != null && this.logger.doDebug){
this.logger.debug("opened connection", this.socketOptions);
}

// Set options on the socket
this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout);
// Work around for 0.4.X
Expand Down
1 change: 1 addition & 0 deletions lib/mongodb/connection/server.js
Expand Up @@ -98,6 +98,7 @@ function Server(host, port, options) {
// Set default connection pool options
this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {};
if(this.disableDriverBSONSizeCheck) this.socketOptions.disableDriverBSONSizeCheck = this.disableDriverBSONSizeCheck;

// Set ssl up if it's defined
if(this.ssl) {
this.socketOptions.ssl = true;
Expand Down
8 changes: 4 additions & 4 deletions lib/mongodb/connection/url_parser.js
Expand Up @@ -127,12 +127,12 @@ exports.parse = function(url, options) {
throw new Error("uuidRepresentation not supported");
case 'ssl':
if(value == 'prefer') {
serverOptions.socketOptions.ssl = value;
replSetServersOptions.socketOptions.ssl = value;
serverOptions.ssl = value;
replSetServersOptions.ssl = value;
break;
}
serverOptions.socketOptions.ssl = (value == 'true');
replSetServersOptions.socketOptions.ssl = (value == 'true');
serverOptions.ssl = (value == 'true');
replSetServersOptions.ssl = (value == 'true');
break;
case 'replicaSet':
case 'rs_name':
Expand Down
24 changes: 19 additions & 5 deletions lib/mongodb/db.js
Expand Up @@ -1947,7 +1947,7 @@ Db.DEFAULT_URL = 'mongodb://localhost:27017/default';
/**
* Connect to MongoDB using a url as documented at
*
* www.mongodb.org/display/DOCS/Connections
* docs.mongodb.org/manual/reference/connection-string/
*
* Options
* - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
Expand Down Expand Up @@ -2019,10 +2019,24 @@ Db.connect = function(url, options, callback) {
// Connect to all servers and run ismaster
for(var i = 0; i < object.servers.length; i++) {
// Set up socket options
var _server_options = {socketOptions:{connectTimeoutMS:1000}, auto_reconnect:false};
// Add ssl if missing
if(object.server_options.socketOptions &&
object.server_options.socketOptions.ssl) _server_options.ssl = object.server_options.socketOptions.ssl;
var _server_options = {poolSize:1, socketOptions:{connectTimeoutMS:1000}, auto_reconnect:false};

// Ensure we have ssl setup for the servers
if(object.rs_options.ssl) {
_server_options.ssl = object.rs_options.ssl;
_server_options.ssl_validate = object.rs_options.ssl_validate;
_server_options.ssl_ca = object.rs_options.ssl_ca;
_server_options.ssl_cert = object.rs_options.ssl_cert;
_server_options.ssl_key = object.rs_options.ssl_key;
_server_options.ssl_pass = object.rs_options.ssl_pass;
} else if(object.server_options.ssl) {
_server_options.ssl = object.server_options.ssl;
_server_options.ssl_validate = object.server_options.ssl_validate;
_server_options.ssl_ca = object.server_options.ssl_ca;
_server_options.ssl_cert = object.server_options.ssl_cert;
_server_options.ssl_key = object.server_options.ssl_key;
_server_options.ssl_pass = object.server_options.ssl_pass;
}

// Set up the Server object
var _server = object.servers[i].domain_socket
Expand Down
2 changes: 1 addition & 1 deletion lib/mongodb/mongo_client.js
Expand Up @@ -78,7 +78,7 @@ MongoClient.prototype.db = function(dbName) {
/**
* Connect to MongoDB using a url as documented at
*
* www.mongodb.org/display/DOCS/Connections
* docs.mongodb.org/manual/reference/connection-string/
*
* Options
* - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
Expand Down
251 changes: 247 additions & 4 deletions test/auxilliary/ssl/mongo_client_ssl_test.js
Expand Up @@ -10,7 +10,9 @@ var testCase = require('nodeunit').testCase,
Collection = mongodb.Collection,
Server = mongodb.Server,
MongoClient = mongodb.MongoClient,
fs = require('fs'),
ServerManager = require('../../../test/tools/server_manager').ServerManager,
ReplicaSetManager = require('../../../test/tools/replica_set_manager').ReplicaSetManager,
Step = require("step");

var MONGODB = 'integration_tests';
Expand Down Expand Up @@ -68,14 +70,23 @@ exports.shouldCorrectlyValidateServerCertificate = function(test) {
var insertDocs = [];

// Start server
serverManager = new ServerManager({auth:false, purgedirectories:true, journal:true, ssl:ssl, ssl_server_pem: "../test/certificates/server.pem"})
serverManager = new ServerManager({
auth:false
, purgedirectories:true
, journal:true
, ssl:ssl
, ssl_server_pem: "../test/certificates/server.pem"
});

serverManager.start(true, function() {
// Read the ca
var ca = [fs.readFileSync(__dirname + "/../../certificates/ca.pem")];
// Connect and validate the server certificate
MongoClient.connect("mongodb://localhost:27017/test?ssl=true", {
ssl_validate:true
, ssl_ca:ca
MongoClient.connect("mongodb://server:27017/test?ssl=true&maxPoolSize=1", {
server: {
ssl_validate:true
, ssl_ca:ca
}
}, function(err, db) {
test.equal(null, err);
test.ok(db != null);
Expand All @@ -87,6 +98,238 @@ exports.shouldCorrectlyValidateServerCertificate = function(test) {
});
}

exports.shouldCorrectlyValidatePresentedServerCertificateAndPresentValidCertificate = function(test) {
if(process.env['JENKINS']) return test.done();
var db1 = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, poolSize:4, ssl:ssl}), {w:0, native_parser: (process.env['TEST_NATIVE'] != null)});
// All inserted docs
var docs = [];
var errs = [];
var insertDocs = [];

// Read the ca
var ca = [fs.readFileSync(__dirname + "/../../certificates/ca.pem")];
var cert = fs.readFileSync(__dirname + "/../../certificates/client.pem");
var key = fs.readFileSync(__dirname + "/../../certificates/client.pem");

// Start server
serverManager = new ServerManager({
auth:false
, purgedirectories:true
, journal:true
, ssl:ssl
, ssl_ca: '../test/certificates/ca.pem'
, ssl_crl: '../test/certificates/crl.pem'
, ssl_server_pem: "../test/certificates/server.pem"
, ssl_force_validate_certificates: true
, ssl_client_pem: cert
});

serverManager.start(true, function() {
// Connect and validate the server certificate
MongoClient.connect("mongodb://server:27017/test?ssl=true&maxPoolSize=1", {
server: {
ssl_validate:true
, ssl_ca:ca
, ssl_key:key
, ssl_cert:cert
, ssl_pass:'10gen'
}
}, function(err, db) {
test.equal(null, err);
test.ok(db != null);

db.close();
serverManager.killAll();
test.done();
});
});
}

exports.shouldValidatePresentedServerCertificateButPresentInvalidCertificate = function(test) {
if(process.env['JENKINS']) return test.done();
var db1 = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, poolSize:4, ssl:ssl}), {w:0, native_parser: (process.env['TEST_NATIVE'] != null)});
// All inserted docs
var docs = [];
var errs = [];
var insertDocs = [];

// Read the ca
var ca = [fs.readFileSync(__dirname + "/../../certificates/ca.pem")];
var cert = fs.readFileSync(__dirname + "/../../certificates/client.pem");
var key = fs.readFileSync(__dirname + "/../../certificates/client.pem");

// Start server
serverManager = new ServerManager({
auth:false
, purgedirectories:true
, journal:true
, ssl:ssl
, ssl_ca: '../test/certificates/ca.pem'
, ssl_crl: '../test/certificates/crl.pem'
, ssl_server_pem: "../test/certificates/server.pem"
, ssl_force_validate_certificates: true
, ssl_client_pem: cert
});

serverManager.start(true, function() {
// Read the ca
var cert = fs.readFileSync(__dirname + "/../../certificates/mycert.pem");
var key = fs.readFileSync(__dirname + "/../../certificates/mycert.pem");
// Connect and validate the server certificate
MongoClient.connect("mongodb://server:27017/test?ssl=true&maxPoolSize=1", {
server: {
ssl_validate:true
, ssl_ca:ca
, ssl_key:key
, ssl_cert:cert
, ssl_pass:'10gen'
}
}, function(err, db) {
test.ok(err != null);

serverManager.killAll();
test.done();
});
});
}

exports.shouldCorrectlyValidateServerCertificateReplSet = function(test) {
if(process.env['JENKINS']) return test.done();
var db1 = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, poolSize:4, ssl:ssl}), {w:0, native_parser: (process.env['TEST_NATIVE'] != null)});
// All inserted docs
var docs = [];
var errs = [];
var insertDocs = [];

var RS = new ReplicaSetManager({retries:120,
host: "server",
ssl:ssl,
ssl_server_pem: "../test/certificates/server.pem",
arbiter_count:1,
secondary_count:2,
passive_count:1});

RS.startSet(true, function(err, result) {
if(err != null) throw err;

// Read the ca
var ca = [fs.readFileSync(__dirname + "/../../certificates/ca.pem")];
// Connect and validate the server certificate
MongoClient.connect("mongodb://server:30000,server:30001/test?ssl=true&maxPoolSize=1", {
replSet: {
ssl_validate:true
, ssl_ca:ca
}
}, function(err, db) {
test.equal(null, err);
test.ok(db != null);

db.close();
RS.killAll();
test.done();
});
});
}

exports.shouldCorrectlySendCertificateToReplSetAndValidateServerCertificate = function(test) {
if(process.env['JENKINS']) return test.done();
var db1 = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, poolSize:4, ssl:ssl}), {w:0, native_parser: (process.env['TEST_NATIVE'] != null)});
// All inserted docs
var docs = [];
var errs = [];
var insertDocs = [];

// Read the ca
var ca = [fs.readFileSync(__dirname + "/../../certificates/ca.pem")];
var cert = fs.readFileSync(__dirname + "/../../certificates/client.pem");
var key = fs.readFileSync(__dirname + "/../../certificates/client.pem");

var RS = new ReplicaSetManager({retries:120,
host: "server",
ssl:ssl,
ssl_ca: '../test/certificates/ca.pem',
ssl_crl: '../test/certificates/crl.pem',
ssl_server_pem: "../test/certificates/server.pem",
ssl_force_validate_certificates: true,
ssl_client_pem: cert,

arbiter_count:1,
secondary_count:2,
passive_count:1});

RS.startSet(true, function(err, result) {
if(err != null) throw err;

// Connect and validate the server certificate
MongoClient.connect("mongodb://server:30000,server:30001/test?ssl=true&maxPoolSize=1", {
replSet: {
ssl_validate:true
, ssl_ca:ca
, ssl_key:key
, ssl_cert:cert
}
}, function(err, db) {
test.equal(null, err);
test.ok(db != null);

db.close();
RS.killAll();
test.done();
});
});
}

exports.shouldSendWrongCertificateToReplSetAndValidateServerCertificate = function(test) {
if(process.env['JENKINS']) return test.done();
var db1 = new Db(MONGODB, new Server("127.0.0.1", 27017, {auto_reconnect: false, poolSize:4, ssl:ssl}), {w:0, native_parser: (process.env['TEST_NATIVE'] != null)});
// All inserted docs
var docs = [];
var errs = [];
var insertDocs = [];

// Read the ca
var ca = [fs.readFileSync(__dirname + "/../../certificates/ca.pem")];
var cert = fs.readFileSync(__dirname + "/../../certificates/client.pem");
var key = fs.readFileSync(__dirname + "/../../certificates/client.pem");

var RS = new ReplicaSetManager({retries:120,
host: "server",
ssl:ssl,
ssl_ca: '../test/certificates/ca.pem',
ssl_crl: '../test/certificates/crl.pem',
ssl_server_pem: "../test/certificates/server.pem",
ssl_force_validate_certificates: true,
ssl_client_pem: cert,

arbiter_count:1,
secondary_count:2,
passive_count:1});

RS.startSet(true, function(err, result) {
if(err != null) throw err;

// Present wrong certificate
var cert = fs.readFileSync(__dirname + "/../../certificates/mycert.pem");
var key = fs.readFileSync(__dirname + "/../../certificates/mycert.pem");

// Connect and validate the server certificate
MongoClient.connect("mongodb://server:30000,server:30001/test?ssl=true&maxPoolSize=1", {
replSet: {
ssl_validate:true
, ssl_ca:ca
, ssl_key:key
, ssl_cert:cert
, ssl_pass:'10gen'
}
}, function(err, db) {
test.ok(err != null)

RS.killAll();
test.done();
});
});
}

/**
* Retrieve the server information for the current
* instance of the db client
Expand Down
2 changes: 1 addition & 1 deletion test/tools/replica_set_manager.js
Expand Up @@ -255,7 +255,7 @@ ReplicaSetManager.prototype.initNode = function(n, fields, callback) {

ReplicaSetManager.prototype.killAll = function(callback) {
exec('killall -9 mongod', function(err, stdout, stderr) {
return callback();
if(typeof callback == 'function') return callback();
});
}

Expand Down

0 comments on commit ae8282e

Please sign in to comment.