diff options
-rw-r--r-- | buildscripts/resmokeconfig/suites/ssl.yml | 3 | ||||
-rw-r--r-- | buildscripts/resmokeconfig/suites/ssl_special.yml | 3 | ||||
-rw-r--r-- | jstests/libs/ssl_test.js | 90 | ||||
-rw-r--r-- | jstests/ssl/ssl_crl.js | 50 | ||||
-rw-r--r-- | jstests/sslSpecial/ssl_mixedmode.js | 58 |
5 files changed, 127 insertions, 77 deletions
diff --git a/buildscripts/resmokeconfig/suites/ssl.yml b/buildscripts/resmokeconfig/suites/ssl.yml index e9c38958b25..a1885a707d5 100644 --- a/buildscripts/resmokeconfig/suites/ssl.yml +++ b/buildscripts/resmokeconfig/suites/ssl.yml @@ -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: diff --git a/buildscripts/resmokeconfig/suites/ssl_special.yml b/buildscripts/resmokeconfig/suites/ssl_special.yml index 41295e26616..340baad9534 100644 --- a/buildscripts/resmokeconfig/suites/ssl_special.yml +++ b/buildscripts/resmokeconfig/suites/ssl_special.yml @@ -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: diff --git a/jstests/libs/ssl_test.js b/jstests/libs/ssl_test.js new file mode 100644 index 00000000000..cfb899ab3d0 --- /dev/null +++ b/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; +}; diff --git a/jstests/ssl/ssl_crl.js b/jstests/ssl/ssl_crl.js index fd83c3979ef..96c12b91bb9 100644 --- a/jstests/ssl/ssl_crl.js +++ b/jstests/ssl/ssl_crl.js @@ -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()); diff --git a/jstests/sslSpecial/ssl_mixedmode.js b/jstests/sslSpecial/ssl_mixedmode.js index 701c5ea10d7..738aa26714f 100644 --- a/jstests/sslSpecial/ssl_mixedmode.js +++ b/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); @@ -55,4 +30,3 @@ testCombination("disabled", true, false); testCombination("allowSSL", true, true); testCombination("preferSSL", true, true); testCombination("requireSSL", true, true); - |