mirror of https://github.com/mongodb/mongo
125 lines
4.7 KiB
JavaScript
125 lines
4.7 KiB
JavaScript
// The TLSTest class is used to check if a shell with a certain TLS configuration
|
|
// can be used to connect to a server with a given TLS configuration.
|
|
// This is necessary because TLS settings are currently process global - so if the mongo shell
|
|
// started by resmoke.py has an TLS 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 'tlsMode'
|
|
* (preferTLS), tlsCertificateKeyFile ("jstests/libs/server.pem"), and tlsCAFile
|
|
* "jstests/libs/ca.pem").
|
|
*/
|
|
export function TLSTest(serverOpts, clientOpts) {
|
|
let canonicalServerOpts = function (userProvidedOpts) {
|
|
let canonical = Object.extend({}, userProvidedOpts || {});
|
|
|
|
if (!canonical.hasOwnProperty("tlsMode")) {
|
|
canonical.tlsMode = "preferTLS";
|
|
} else if (canonical.tlsMode === "disabled") {
|
|
// should not add further options if TLS is disabled
|
|
return canonical;
|
|
}
|
|
|
|
if (!canonical.hasOwnProperty("tlsCertificateKeyFile")) {
|
|
canonical.tlsCertificateKeyFile = "jstests/libs/server.pem";
|
|
}
|
|
if (!canonical.hasOwnProperty("tlsCAFile")) {
|
|
canonical.tlsCAFile = "jstests/libs/ca.pem";
|
|
}
|
|
return canonical;
|
|
};
|
|
|
|
this.serverOpts = MongoRunner.mongodOptions(canonicalServerOpts(serverOpts));
|
|
this.port = this.serverOpts.port;
|
|
resetDbpath(this.serverOpts.dbpath);
|
|
|
|
this.clientOpts = Object.extend({}, clientOpts || this.defaultTLSClientOptions);
|
|
this.clientOpts.port = this.port;
|
|
}
|
|
|
|
/**
|
|
* The default shell arguments for a shell with TLS enabled.
|
|
*/
|
|
TLSTest.prototype.defaultTLSClientOptions = {
|
|
"tls": "",
|
|
"tlsCertificateKeyFile": "jstests/libs/client.pem",
|
|
"tlsCAFile": "jstests/libs/ca.pem",
|
|
"eval": ";", // prevent the shell from entering interactive mode
|
|
};
|
|
|
|
/**
|
|
* The default shell arguments for a shell without TLS enabled.
|
|
*/
|
|
TLSTest.prototype.noTLSClientOptions = {
|
|
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.
|
|
*/
|
|
TLSTest.prototype.connectWorked = function () {
|
|
let connectTimeoutMillis = 3 * 60 * 1000;
|
|
|
|
let serverArgv = MongoRunner.arrOptions("mongod", this.serverOpts);
|
|
let clientArgv = MongoRunner.arrOptions("mongo", this.clientOpts);
|
|
|
|
let serverPID = _startMongoProgram.apply(null, serverArgv);
|
|
try {
|
|
// Don't run the hang analyzer because we don't expect connectWorked() to always succeed.
|
|
assert.soon(
|
|
function () {
|
|
return checkProgram(serverPID).alive && 0 === _runMongoProgram.apply(null, clientArgv);
|
|
},
|
|
"connect failed",
|
|
connectTimeoutMillis,
|
|
undefined,
|
|
{runHangAnalyzer: false},
|
|
);
|
|
} catch (ex) {
|
|
return false;
|
|
} finally {
|
|
_stopMongoProgram(this.port);
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* 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 immediately with true
|
|
* if a connection cannot be established using the configured client options.
|
|
*/
|
|
TLSTest.prototype.connectFails = function () {
|
|
const connectTimeoutMillis = 3 * 60 * 1000;
|
|
|
|
let waitForConnectClientOpts = this.noTLSClientOptions;
|
|
if (this.serverOpts.tlsMode === "requireTLS") {
|
|
waitForConnectClientOpts = this.defaultTLSClientOptions;
|
|
}
|
|
waitForConnectClientOpts.port = this.port;
|
|
|
|
const serverArgv = MongoRunner.arrOptions("mongod", this.serverOpts);
|
|
const failingClientArgv = MongoRunner.arrOptions("mongo", this.clientOpts);
|
|
const workingClientArgv = MongoRunner.arrOptions("mongo", waitForConnectClientOpts);
|
|
const serverPID = _startMongoProgram.apply(null, serverArgv);
|
|
|
|
// Wait until we can connect to mongod using the working client args
|
|
assert.soon(
|
|
function () {
|
|
return checkProgram(serverPID).alive && 0 === _runMongoProgram.apply(null, workingClientArgv);
|
|
},
|
|
"connect failed",
|
|
connectTimeoutMillis,
|
|
);
|
|
const result = _runMongoProgram.apply(null, failingClientArgv);
|
|
_stopMongoProgram(this.port);
|
|
return result !== 0;
|
|
};
|