diff options
Diffstat (limited to 'jstests/replsets')
-rw-r--r-- | jstests/replsets/disable_cluster_time_gossiping_in_unreadable_state.js | 73 | ||||
-rw-r--r-- | jstests/replsets/read_concern_uninitated_set.js | 10 |
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(); }()); |