summaryrefslogtreecommitdiff
path: root/jstests/ssl/repl_ssl_split_horizon.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/ssl/repl_ssl_split_horizon.js')
-rw-r--r--jstests/ssl/repl_ssl_split_horizon.js363
1 files changed, 182 insertions, 181 deletions
diff --git a/jstests/ssl/repl_ssl_split_horizon.js b/jstests/ssl/repl_ssl_split_horizon.js
index d70980ebe88..b598e8b692d 100644
--- a/jstests/ssl/repl_ssl_split_horizon.js
+++ b/jstests/ssl/repl_ssl_split_horizon.js
@@ -1,190 +1,191 @@
(function() {
- 'use strict';
- // Create a temporary host file that creates two aliases for localhost that are in the
- // splithorizon certificate.
- // The aliases are 'splithorizon1' and 'splithorizon2'
- const hostsFile = MongoRunner.dataPath + 'split-horizon-hosts';
- writeFile(hostsFile, "splithorizon1 localhost\nsplithorizon2 localhost\n");
-
- // Check if HOSTALIASES works on this system (Will not work on Windows or OSX and may not work
- // on Linux)
- try {
- var rc =
- runMongoProgram("env", "HOSTALIASES=" + hostsFile, "getent", "hosts", "splithorizon1");
- } catch (e) {
+'use strict';
+// Create a temporary host file that creates two aliases for localhost that are in the
+// splithorizon certificate.
+// The aliases are 'splithorizon1' and 'splithorizon2'
+const hostsFile = MongoRunner.dataPath + 'split-horizon-hosts';
+writeFile(hostsFile, "splithorizon1 localhost\nsplithorizon2 localhost\n");
+
+// Check if HOSTALIASES works on this system (Will not work on Windows or OSX and may not work
+// on Linux)
+try {
+ var rc = runMongoProgram("env", "HOSTALIASES=" + hostsFile, "getent", "hosts", "splithorizon1");
+} catch (e) {
+ jsTestLog(
+ `Failed the check for HOSTALIASES support using env, we are probably on a non-GNU platform. Skipping this test.`);
+ removeFile(hostsFile);
+ return;
+}
+
+if (rc != 0) {
+ removeFile(hostsFile);
+
+ // Check glibc version to figure out of HOSTALIASES will work as expected
+ clearRawMongoProgramOutput();
+ var rc = runProgram("getconf", "GNU_LIBC_VERSION");
+ if (rc != 0) {
jsTestLog(
- `Failed the check for HOSTALIASES support using env, we are probably on a non-GNU platform. Skipping this test.`);
- removeFile(hostsFile);
+ `Failed the check for GLIBC version, we are probably on a non-GNU platform. Skipping this test.`);
return;
}
- if (rc != 0) {
- removeFile(hostsFile);
-
- // Check glibc version to figure out of HOSTALIASES will work as expected
- clearRawMongoProgramOutput();
- var rc = runProgram("getconf", "GNU_LIBC_VERSION");
- if (rc != 0) {
- jsTestLog(
- `Failed the check for GLIBC version, we are probably on a non-GNU platform. Skipping this test.`);
- return;
- }
-
- // Output is of the format: 'glibc x.yz'
- var output = rawMongoProgramOutput();
- var fields = output.split(" ");
- var glibc_version = parseFloat(fields[2]);
-
- // Fail this test if we are on GLIBC >= 2.2 and HOSTALIASES still doesn't work
- if (glibc_version < 2.2) {
- jsTestLog(`HOSTALIASES does not seem to work as expected on this system. GLIBC
+ // Output is of the format: 'glibc x.yz'
+ var output = rawMongoProgramOutput();
+ var fields = output.split(" ");
+ var glibc_version = parseFloat(fields[2]);
+
+ // Fail this test if we are on GLIBC >= 2.2 and HOSTALIASES still doesn't work
+ if (glibc_version < 2.2) {
+ jsTestLog(
+ `HOSTALIASES does not seem to work as expected on this system. GLIBC
version is ${glibc_version}, skipping this test.`);
- return;
- } else {
- assert(false, `HOSTALIASES does not seem to work as expected on this system. GLIBC
+ return;
+ } else {
+ assert(false,
+ `HOSTALIASES does not seem to work as expected on this system. GLIBC
version is ${glibc_version}`);
- }
}
-
- var replTest = new ReplSetTest({
- name: "splitHorizontest",
- nodes: 2,
- nodeOptions: {
- sslMode: "requireSSL",
- sslPEMKeyFile: "jstests/libs/splithorizon-server.pem",
- },
- host: "localhost",
- useHostName: false,
- });
-
- replTest.startSet({
- env: {
- SSL_CERT_FILE: 'jstests/libs/splithorizon-ca.pem',
- },
- });
-
- // Create some variables needed for our horizons, we're replacing localhost with the horizon
- // name, leaving the port the same (so we can connect)
- var node0 = replTest.nodeList()[0];
- var node1 = replTest.nodeList()[1];
- var node0localHostname = node0;
- var node1localHostname = node1;
- var node0horizonHostname = node0.replace("localhost", "splithorizon1");
- var node1horizonHostname = node1.replace("localhost", "splithorizon1");
- var node0horizonMissingHostname = node0.replace("localhost", "splithorizon2");
- var node1horizonMissingHostname = node1.replace("localhost", "splithorizon2");
-
- var config = replTest.getReplSetConfig();
- config.members[0].horizons = {};
- config.members[0].horizons.horizon_name = node0horizonHostname;
- config.members[1].horizons = {};
- config.members[1].horizons.horizon_name = node1horizonHostname;
-
- replTest.initiate(config);
-
- var checkExpectedHorizon = function(url, memberIndex, expectedHostname) {
- // Run isMaster in the shell and check that we get the expected hostname back
- var argv = [
- 'env',
- "HOSTALIASES=" + hostsFile,
- "SSL_CERT_FILE=jstests/libs/splithorizon-ca.pem",
- './mongo',
- url,
- '--eval',
- ("assert(db.runCommand({isMaster: 1})['hosts'][" + memberIndex + "] == '" +
- expectedHostname + "')")
- ];
- return runMongoProgram(...argv);
- };
-
- // Using localhost should use the default horizon
- var defaultURL = `mongodb://${node0localHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
- jsTestLog(`URL without horizon: ${defaultURL}`);
- assert.eq(checkExpectedHorizon(defaultURL, 0, node0localHostname),
- 0,
- "localhost does not return horizon");
- assert.eq(checkExpectedHorizon(defaultURL, 1, node1localHostname),
- 0,
- "localhost does not return horizon");
-
- // Using 'splithorizon1' should use that horizon
- var horizonURL = `mongodb://${node0horizonHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
- jsTestLog(`URL with horizon: ${horizonURL}`);
- assert.eq(checkExpectedHorizon(horizonURL, 0, node0horizonHostname),
- 0,
- "does not return horizon as expected");
- assert.eq(checkExpectedHorizon(horizonURL, 1, node1horizonHostname),
- 0,
- "does not return horizon as expected");
-
- // Using 'splithorizon2' does not have a horizon so it should return default
- var horizonMissingURL =
- `mongodb://${node0horizonMissingHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
- jsTestLog(`URL with horizon: ${horizonMissingURL}`);
- assert.eq(checkExpectedHorizon(horizonMissingURL, 0, node0localHostname),
- 0,
- "does not return localhost as expected");
- assert.eq(checkExpectedHorizon(horizonMissingURL, 1, node1localHostname),
- 0,
- "does not return localhost as expected");
-
- // Check so we can replSetReconfig to add another horizon
- config.version += 1;
- config.members[0].horizons.other_horizon_name = node0horizonMissingHostname;
- config.members[1].horizons.other_horizon_name = node1horizonMissingHostname;
-
- assert.adminCommandWorkedAllowingNetworkError(replTest.getPrimary(), {replSetReconfig: config});
-
- // Using 'splithorizon2' should now return the new horizon
- var horizonMissingURL =
- `mongodb://${node0horizonMissingHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
- jsTestLog(`URL with horizon: ${horizonMissingURL}`);
- assert.eq(checkExpectedHorizon(horizonMissingURL, 0, node0horizonMissingHostname),
- 0,
- "does not return horizon as expected");
- assert.eq(checkExpectedHorizon(horizonMissingURL, 1, node1horizonMissingHostname),
- 0,
- "does not return horizon as expected");
-
- // Change horizon to return a different port to connect to, so the feature can be used in a
- // port-forwarding environment
- var node0horizonHostnameDifferentPort = "splithorizon1:80";
- var node1horizonHostnameDifferentPort = "splithorizon1:81";
- config.version += 1;
- config.members[0].horizons.horizon_name = node0horizonHostnameDifferentPort;
- config.members[1].horizons.horizon_name = node1horizonHostnameDifferentPort;
-
- assert.adminCommandWorkedAllowingNetworkError(replTest.getPrimary(), {replSetReconfig: config});
-
- // Build the connection URL, do not set replicaSet as that will trigger the ReplicaSetMonitor
- // which will fail as we can't actually connect now (port is wrong)
- var horizonDifferentPortURL = `mongodb://${node0horizonHostname}/admin?ssl=true`;
- jsTestLog(`URL with horizon using different port: ${horizonDifferentPortURL}`);
- assert.eq(checkExpectedHorizon(horizonDifferentPortURL, 0, node0horizonHostnameDifferentPort),
- 0,
- "does not return horizon as expected");
- assert.eq(checkExpectedHorizon(horizonDifferentPortURL, 1, node1horizonHostnameDifferentPort),
- 0,
- "does not return horizon as expected");
-
- // Providing a config where horizons does not exist in all members is expected to fail
- config.version += 1;
- config.members[0].horizons.horizon_mismatch = node0.replace("localhost", "splithorizon3");
- assert.commandFailed(replTest.getPrimary().adminCommand({replSetReconfig: config}));
-
- // Providing a config where horizon hostnames are duplicated in members is expected to fail
- config.version += 1;
- config.members[1].horizons.horizon_mismatch = config.members[0].horizons.horizon_mismatch;
- assert.commandFailed(replTest.getPrimary().adminCommand({replSetReconfig: config}));
-
- // Two horizons with duplicated hostnames are not allowed
- config.version += 1;
- delete config.members[0].horizons.horizon_mismatch;
- delete config.members[1].horizons.horizon_mismatch;
- config.members[0].horizons.horizon_dup_hostname = config.members[0].horizons.horizon_name;
- config.members[1].horizons.horizon_dup_hostname = config.members[1].horizons.horizon_name;
- assert.commandFailed(replTest.getPrimary().adminCommand({replSetReconfig: config}));
-
- replTest.stopSet();
- removeFile(hostsFile);
+}
+
+var replTest = new ReplSetTest({
+ name: "splitHorizontest",
+ nodes: 2,
+ nodeOptions: {
+ sslMode: "requireSSL",
+ sslPEMKeyFile: "jstests/libs/splithorizon-server.pem",
+ },
+ host: "localhost",
+ useHostName: false,
+});
+
+replTest.startSet({
+ env: {
+ SSL_CERT_FILE: 'jstests/libs/splithorizon-ca.pem',
+ },
+});
+
+// Create some variables needed for our horizons, we're replacing localhost with the horizon
+// name, leaving the port the same (so we can connect)
+var node0 = replTest.nodeList()[0];
+var node1 = replTest.nodeList()[1];
+var node0localHostname = node0;
+var node1localHostname = node1;
+var node0horizonHostname = node0.replace("localhost", "splithorizon1");
+var node1horizonHostname = node1.replace("localhost", "splithorizon1");
+var node0horizonMissingHostname = node0.replace("localhost", "splithorizon2");
+var node1horizonMissingHostname = node1.replace("localhost", "splithorizon2");
+
+var config = replTest.getReplSetConfig();
+config.members[0].horizons = {};
+config.members[0].horizons.horizon_name = node0horizonHostname;
+config.members[1].horizons = {};
+config.members[1].horizons.horizon_name = node1horizonHostname;
+
+replTest.initiate(config);
+
+var checkExpectedHorizon = function(url, memberIndex, expectedHostname) {
+ // Run isMaster in the shell and check that we get the expected hostname back
+ var argv = [
+ 'env',
+ "HOSTALIASES=" + hostsFile,
+ "SSL_CERT_FILE=jstests/libs/splithorizon-ca.pem",
+ './mongo',
+ url,
+ '--eval',
+ ("assert(db.runCommand({isMaster: 1})['hosts'][" + memberIndex + "] == '" +
+ expectedHostname + "')")
+ ];
+ return runMongoProgram(...argv);
+};
+
+// Using localhost should use the default horizon
+var defaultURL = `mongodb://${node0localHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
+jsTestLog(`URL without horizon: ${defaultURL}`);
+assert.eq(checkExpectedHorizon(defaultURL, 0, node0localHostname),
+ 0,
+ "localhost does not return horizon");
+assert.eq(checkExpectedHorizon(defaultURL, 1, node1localHostname),
+ 0,
+ "localhost does not return horizon");
+
+// Using 'splithorizon1' should use that horizon
+var horizonURL = `mongodb://${node0horizonHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
+jsTestLog(`URL with horizon: ${horizonURL}`);
+assert.eq(checkExpectedHorizon(horizonURL, 0, node0horizonHostname),
+ 0,
+ "does not return horizon as expected");
+assert.eq(checkExpectedHorizon(horizonURL, 1, node1horizonHostname),
+ 0,
+ "does not return horizon as expected");
+
+// Using 'splithorizon2' does not have a horizon so it should return default
+var horizonMissingURL =
+ `mongodb://${node0horizonMissingHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
+jsTestLog(`URL with horizon: ${horizonMissingURL}`);
+assert.eq(checkExpectedHorizon(horizonMissingURL, 0, node0localHostname),
+ 0,
+ "does not return localhost as expected");
+assert.eq(checkExpectedHorizon(horizonMissingURL, 1, node1localHostname),
+ 0,
+ "does not return localhost as expected");
+
+// Check so we can replSetReconfig to add another horizon
+config.version += 1;
+config.members[0].horizons.other_horizon_name = node0horizonMissingHostname;
+config.members[1].horizons.other_horizon_name = node1horizonMissingHostname;
+
+assert.adminCommandWorkedAllowingNetworkError(replTest.getPrimary(), {replSetReconfig: config});
+
+// Using 'splithorizon2' should now return the new horizon
+var horizonMissingURL =
+ `mongodb://${node0horizonMissingHostname}/admin?replicaSet=${replTest.name}&ssl=true`;
+jsTestLog(`URL with horizon: ${horizonMissingURL}`);
+assert.eq(checkExpectedHorizon(horizonMissingURL, 0, node0horizonMissingHostname),
+ 0,
+ "does not return horizon as expected");
+assert.eq(checkExpectedHorizon(horizonMissingURL, 1, node1horizonMissingHostname),
+ 0,
+ "does not return horizon as expected");
+
+// Change horizon to return a different port to connect to, so the feature can be used in a
+// port-forwarding environment
+var node0horizonHostnameDifferentPort = "splithorizon1:80";
+var node1horizonHostnameDifferentPort = "splithorizon1:81";
+config.version += 1;
+config.members[0].horizons.horizon_name = node0horizonHostnameDifferentPort;
+config.members[1].horizons.horizon_name = node1horizonHostnameDifferentPort;
+
+assert.adminCommandWorkedAllowingNetworkError(replTest.getPrimary(), {replSetReconfig: config});
+
+// Build the connection URL, do not set replicaSet as that will trigger the ReplicaSetMonitor
+// which will fail as we can't actually connect now (port is wrong)
+var horizonDifferentPortURL = `mongodb://${node0horizonHostname}/admin?ssl=true`;
+jsTestLog(`URL with horizon using different port: ${horizonDifferentPortURL}`);
+assert.eq(checkExpectedHorizon(horizonDifferentPortURL, 0, node0horizonHostnameDifferentPort),
+ 0,
+ "does not return horizon as expected");
+assert.eq(checkExpectedHorizon(horizonDifferentPortURL, 1, node1horizonHostnameDifferentPort),
+ 0,
+ "does not return horizon as expected");
+
+// Providing a config where horizons does not exist in all members is expected to fail
+config.version += 1;
+config.members[0].horizons.horizon_mismatch = node0.replace("localhost", "splithorizon3");
+assert.commandFailed(replTest.getPrimary().adminCommand({replSetReconfig: config}));
+
+// Providing a config where horizon hostnames are duplicated in members is expected to fail
+config.version += 1;
+config.members[1].horizons.horizon_mismatch = config.members[0].horizons.horizon_mismatch;
+assert.commandFailed(replTest.getPrimary().adminCommand({replSetReconfig: config}));
+
+// Two horizons with duplicated hostnames are not allowed
+config.version += 1;
+delete config.members[0].horizons.horizon_mismatch;
+delete config.members[1].horizons.horizon_mismatch;
+config.members[0].horizons.horizon_dup_hostname = config.members[0].horizons.horizon_name;
+config.members[1].horizons.horizon_dup_hostname = config.members[1].horizons.horizon_name;
+assert.commandFailed(replTest.getPrimary().adminCommand({replSetReconfig: config}));
+
+replTest.stopSet();
+removeFile(hostsFile);
})();