Skip to content

Commit

Permalink
SERVER-19113 rewrite ssl_crl.js and ssl_mixedmode.js to not depend on…
Browse files Browse the repository at this point in the history
… legacy DBClientConnection behavior
  • Loading branch information
amidvidy committed Jun 30, 2015
1 parent fec53e8 commit 2186037
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 77 deletions.
3 changes: 0 additions & 3 deletions buildscripts/resmokeconfig/suites/ssl.yml
Expand Up @@ -2,9 +2,6 @@ selector:
js_test:
roots:
- jstests/ssl/*.js
exclude_files:
# SERVER-19113
- jstests/ssl/ssl_crl.js

# ssl tests start their own mongod's.
executor:
Expand Down
3 changes: 0 additions & 3 deletions buildscripts/resmokeconfig/suites/ssl_special.yml
Expand Up @@ -2,9 +2,6 @@ selector:
js_test:
roots:
- jstests/sslSpecial/*.js
exclude_files:
# SERVER-19113
- jstests/sslSpecial/ssl_mixedmode.js

# ssl tests start their own mongod's.
executor:
Expand Down
90 changes: 90 additions & 0 deletions jstests/libs/ssl_test.js
@@ -0,0 +1,90 @@
// The SSLTest class is used to check if a shell with a certain SSL configuration
// can be used to connect to a server with a given SSL configuration.
// This is necessary because SSL settings are currently process global - so if the mongo shell
// started by resmoke.py has an SSL configuration that's incompatible with a server created with
// MongoRunner, it will not be able to connect to it.

/**
* A utility for checking if a shell configured with the specified command line options can
* connect to a server with the specified command line options.
*
* The 'serverOpts' and 'clientOpts' objects are in the form of
* {'cmdLineParam': 'value', ...}. For flag arguments, the empty string is used as the value.
*
* For serverOpts a few defaults are set if values are not provided: specifically 'sslMode'
* (preferSSL), sslPEMKeyFile ("jstests/libs/server.pem"), and sslCAFile
* "jstests/libs/ca.pem").
*/
function SSLTest(serverOpts, clientOpts) {

var canonicalServerOpts = function(userProvidedOpts) {
var canonical = Object.extend({}, userProvidedOpts || {});

if (!canonical.hasOwnProperty("sslMode")) {
canonical.sslMode = "preferSSL";
} else if (canonical.sslMode === "disabled") {
// should not add further options if SSL is disabled
return canonical;
}

if (!canonical.hasOwnProperty("sslPEMKeyFile")) {
canonical.sslPEMKeyFile = "jstests/libs/server.pem";
}
if (!canonical.hasOwnProperty("sslCAFile")) {
canonical.sslCAFile = "jstests/libs/ca.pem";
}
return canonical;
};

this.port = allocatePorts(1)[0];
this.serverOpts = MongoRunner.mongodOptions(canonicalServerOpts(serverOpts));
resetDbpath(this.serverOpts.dbpath);

this.clientOpts = Object.extend({}, clientOpts || this.defaultSSLClientOptions);

// Add our allocated port to the options objects.
this.serverOpts.port = this.port;
this.clientOpts.port = this.port;
}

/**
* The default shell arguments for a shell with SSL enabled.
*/
SSLTest.prototype.defaultSSLClientOptions = {
"ssl": "",
"sslPEMKeyFile": "jstests/libs/client.pem",
"sslAllowInvalidCertificates": "",
"eval": ";" // prevent the shell from entering interactive mode
};

/**
* The default shell arguments for a shell without SSL enabled.
*/
SSLTest.prototype.noSSLClientOptions = {
eval: ";" // prevent the shell from entering interactive mode
};

/**
* Starts a server with the parameters passed to the fixture constructor and then attempts to
* connect with a shell created with the configured options. Returns whether a connection
* was successfully established.
*/
SSLTest.prototype.connectWorked = function() {
var connectTimeoutMillis = 30000;

var serverArgv = MongoRunner.arrOptions("mongod", this.serverOpts);
var clientArgv = MongoRunner.arrOptions("mongo", this.clientOpts);

var serverPID = _startMongoProgram.apply(null, serverArgv);
try {
assert.soon(function() {
return checkProgram(serverPID) &&
(0 === _runMongoProgram.apply(null, clientArgv));
}, "connect failed", connectTimeoutMillis);
} catch (ex) {
return false;
} finally {
_stopMongoProgram(this.port);
}
return true;
};
50 changes: 21 additions & 29 deletions jstests/ssl/ssl_crl.js
Expand Up @@ -4,32 +4,24 @@
// Note: crl_expired.pem is a CRL with no revoked certificates, but is an expired CRL.
// crl.pem is a CRL with no revoked certificates.

// This test should allow the user to connect with client.pem certificate.
var md = MongoRunner.runMongod({sslMode: "requireSSL",
sslPEMKeyFile: "jstests/libs/server.pem",
sslCAFile: "jstests/libs/ca.pem",
sslCRLFile: "jstests/libs/crl.pem"});


var mongo = runMongoProgram("mongo", "--port", md.port, "--ssl", "--sslAllowInvalidCertificates",
"--sslPEMKeyFile", "jstests/libs/client.pem",
"--eval", ";");

// 0 is the exit code for success
assert(mongo==0);


// This test ensures clients cannot connect if the CRL is expired.
md = MongoRunner.runMongod({sslMode: "requireSSL",
sslPEMKeyFile: "jstests/libs/server.pem",
sslCAFile: "jstests/libs/ca.pem",
sslCRLFile: "jstests/libs/crl_expired.pem"});


mongo = runMongoProgram("mongo", "--port", md.port, "--ssl", "--sslAllowInvalidCertificates",
"--sslPEMKeyFile", "jstests/libs/client.pem",
"--eval", ";");

// 1 is the exit code for failure
assert(mongo==1);

load("jstests/libs/ssl_test.js");

var testUnrevoked = new SSLTest(
// Server option overrides
{
sslMode: "requireSSL",
sslCRLFile: "jstests/libs/crl.pem"
}
);

assert(testUnrevoked.connectWorked());

var testRevoked = new SSLTest(
// Server option overrides
{
sslMode: "requireSSL",
sslCRLFile: "jstests/libs/crl_expired.pem"
}
);

assert(!testRevoked.connectWorked());
58 changes: 16 additions & 42 deletions jstests/sslSpecial/ssl_mixedmode.js
@@ -1,50 +1,25 @@
// Test the --sslMode parameter
// This tests runs through the 8 possible combinations of sslMode values
// and SSL-enabled and disabled shell respectively. For each combination
// expected behavior is verified.
// expected behavior is verified.

var SERVER_CERT = "jstests/libs/server.pem"
var CA_CERT = "jstests/libs/ca.pem"
var CLIENT_CERT = "jstests/libs/client.pem"

var baseName = "jstests_mixed_mode_ssl"
port = allocatePorts(1)[0];
load("jstests/libs/ssl_test.js");

function testCombination(sslMode, sslShell, shouldSucceed) {
if (sslMode == "disabled") {
MongoRunner.runMongod({port: port});
}
else {
MongoRunner.runMongod({port: port,
sslMode: sslMode,
sslAllowInvalidCertificates: "",
sslPEMKeyFile: SERVER_CERT,
sslCAFile: CA_CERT});
}

var mongo;
if (sslShell) {
mongo = runMongoProgram("mongo", "--port", port, "--ssl",
"--sslPEMKeyFile", CLIENT_CERT,
"--sslAllowInvalidCertificates",
"--eval", ";");
}
else {
mongo = runMongoProgram("mongo", "--port", port,
"--eval", ";");
}

if (shouldSucceed) {
// runMongoProgram returns 0 on success
assert.eq(0, mongo, "Connection attempt failed when it should succeed sslMode:" +
sslMode + " SSL-shell:" + sslShell);
}
else {
// runMongoProgram returns 1 on failure
assert.eq(1, mongo, "Connection attempt succeeded when it should fail sslMode:" +
sslMode + " SSL-shell:" + sslShell);
}
MongoRunner.stopMongod(port);

var serverOptionOverrides = {sslMode: sslMode};

var clientOptions = sslShell ?
SSLTest.prototype.defaultSSLClientOptions :
SSLTest.prototype.noSSLClientOptions;

var fixture = new SSLTest(serverOptionOverrides, clientOptions);

print("Trying sslMode: '" + sslMode +
"' with sslShell = " + sslShell +
"; expect connection to " + (shouldSucceed ? "SUCCEED" : "FAIL"));

assert.eq(shouldSucceed, fixture.connectWorked());
}

testCombination("disabled", false, true);
Expand All @@ -55,4 +30,3 @@ testCombination("disabled", true, false);
testCombination("allowSSL", true, true);
testCombination("preferSSL", true, true);
testCombination("requireSSL", true, true);

0 comments on commit 2186037

Please sign in to comment.