summaryrefslogtreecommitdiff
path: root/jstests/replsets
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/replsets')
-rw-r--r--jstests/replsets/disable_cluster_time_gossiping_in_unreadable_state.js73
-rw-r--r--jstests/replsets/read_concern_uninitated_set.js10
2 files changed, 79 insertions, 4 deletions
diff --git a/jstests/replsets/disable_cluster_time_gossiping_in_unreadable_state.js b/jstests/replsets/disable_cluster_time_gossiping_in_unreadable_state.js
new file mode 100644
index 00000000000..3febc4fef54
--- /dev/null
+++ b/jstests/replsets/disable_cluster_time_gossiping_in_unreadable_state.js
@@ -0,0 +1,73 @@
+/**
+ * Verifies cluster time metadata is not gossiped or processed by nodes in an unreadable state.
+ */
+(function() {
+"use strict";
+
+function setUpUsers(rst) {
+ const primaryAdminDB = rst.getPrimary().getDB("admin");
+ assert.commandWorked(
+ primaryAdminDB.runCommand({createUser: "admin", pwd: "admin", roles: ["root"]}));
+ assert.eq(1, primaryAdminDB.auth("admin", "admin"));
+
+ assert.commandWorked(primaryAdminDB.getSiblingDB("test").runCommand(
+ {createUser: "NotTrusted", pwd: "pwd", roles: ["readWrite"]}));
+ primaryAdminDB.logout();
+
+ authutil.asCluster(rst.nodes, "jstests/libs/key1", () => {
+ rst.awaitLastOpCommitted();
+ });
+}
+
+// Start with auth enabled so cluster times are validated.
+const rst = new ReplSetTest({nodes: 2, keyFile: "jstests/libs/key1"});
+rst.startSet();
+rst.initiate();
+
+setUpUsers(rst);
+
+const secondaryAdminDB = new Mongo(rst.getSecondary().host).getDB("admin");
+secondaryAdminDB.auth("admin", "admin");
+
+const secondaryTestDB = rst.getSecondary().getDB("test");
+secondaryTestDB.auth("NotTrusted", "pwd");
+
+// Cluster time should be gossipped in the steady state.
+let res = assert.commandWorked(secondaryTestDB.runCommand({find: "foo", filter: {}}));
+assert.hasFields(res, ["$clusterTime", "operationTime"]);
+const validClusterTimeMetadata = res.$clusterTime;
+
+// After entering maintenance mode, cluster time should no longer be gossipped, in or out.
+assert.commandWorked(secondaryAdminDB.adminCommand({replSetMaintenance: 1}));
+
+// The find should fail because the node is unreadable.
+res = assert.commandFailedWithCode(secondaryTestDB.runCommand({find: "foo", filter: {}}),
+ ErrorCodes.NotPrimaryOrSecondary);
+assert(!res.hasOwnProperty("$clusterTime"), tojson(res));
+assert(!res.hasOwnProperty("operationTime"), tojson(res));
+
+// A request with $clusterTime should be ignored. This is verified by sending an invalid
+// $clusterTime to emulate situations where valid cluster times would be unable to be verified, e.g.
+// when the signing keys have not been cached but cannot be read from admin.system.keys because the
+// node is in an unreadable state.
+const invalidClusterTimeMetadata = Object.assign(
+ validClusterTimeMetadata,
+ {clusterTime: new Timestamp(validClusterTimeMetadata.clusterTime.getTime() + 100, 0)});
+res = assert.commandWorked(
+ secondaryTestDB.runCommand({hello: 1, $clusterTime: invalidClusterTimeMetadata}));
+
+assert.commandWorked(secondaryAdminDB.adminCommand({replSetMaintenance: 0}));
+
+res = assert.commandWorked(secondaryTestDB.runCommand({find: "foo", filter: {}}));
+assert.hasFields(res, ["$clusterTime", "operationTime"]);
+
+// A request with invalid cluster time metadata should now be rejected.
+assert.commandFailedWithCode(
+ secondaryTestDB.runCommand({hello: 1, $clusterTime: invalidClusterTimeMetadata}),
+ ErrorCodes.TimeProofMismatch);
+
+secondaryAdminDB.logout();
+secondaryTestDB.logout();
+
+rst.stopSet();
+})();
diff --git a/jstests/replsets/read_concern_uninitated_set.js b/jstests/replsets/read_concern_uninitated_set.js
index 71f9b2c6956..209c7c5b826 100644
--- a/jstests/replsets/read_concern_uninitated_set.js
+++ b/jstests/replsets/read_concern_uninitated_set.js
@@ -36,16 +36,18 @@ assert.commandFailedWithCode(
{find: "test", filter: {}, maxTimeMS: 60000, readConcern: {level: "majority"}}),
ErrorCodes.NotYetInitialized);
-jsTestLog("afterClusterTime readConcern should fail with NotYetInitialized.");
+// Nodes don't process $clusterTime metadata when in an unreadable state, so this read will fail
+// because the logical clock's latest value is less than the given afterClusterTime timestamp.
+jsTestLog("afterClusterTime readConcern should fail with InvalidOptions.");
assert.commandFailedWithCode(localDB.runCommand({
find: "test",
filter: {},
maxTimeMS: 60000,
readConcern: {afterClusterTime: Timestamp(1, 1)}
}),
- ErrorCodes.NotYetInitialized);
+ ErrorCodes.InvalidOptions);
-jsTestLog("oplog query should fail with NotYetInitialized.");
+jsTestLog("oplog query should fail with InvalidOptions.");
assert.commandFailedWithCode(localDB.runCommand({
find: "oplog.rs",
filter: {ts: {$gte: Timestamp(1520004466, 2)}},
@@ -57,6 +59,6 @@ assert.commandFailedWithCode(localDB.runCommand({
term: 1,
readConcern: {afterClusterTime: Timestamp(1, 1)}
}),
- ErrorCodes.NotYetInitialized);
+ ErrorCodes.InvalidOptions);
rst.stopSet();
}());