diff options
Diffstat (limited to 'jstests/sharding/mongod_returns_no_cluster_time_without_keys.js')
-rw-r--r-- | jstests/sharding/mongod_returns_no_cluster_time_without_keys.js | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/jstests/sharding/mongod_returns_no_cluster_time_without_keys.js b/jstests/sharding/mongod_returns_no_cluster_time_without_keys.js new file mode 100644 index 00000000000..3c9cf3e6af7 --- /dev/null +++ b/jstests/sharding/mongod_returns_no_cluster_time_without_keys.js @@ -0,0 +1,82 @@ +/** + * Tests that mongod does not gossip cluster time metadata and operation time until at least one key + * is created on the + * config server. +* @tags: [requires_persistence] + */ + +(function() { + "use strict"; + + load("jstests/multiVersion/libs/multi_rs.js"); + + // TODO SERVER-32672: remove this flag. + TestData.skipGossipingClusterTime = true; + const keyFile = 'jstests/libs/key1'; + const adminUser = {db: "admin", username: "foo", password: "bar"}; + const rUser = {db: "test", username: "r", password: "bar"}; + + function assertContainsValidLogicalTime(res) { + assert.hasFields(res, ["$clusterTime"]); + assert.hasFields(res.$clusterTime, ["signature", "clusterTime"]); + // clusterTime must be greater than the uninitialzed value. + assert.hasFields(res.$clusterTime.signature, ["hash", "keyId"]); + // The signature must have been signed by a key with a valid generation. + assert(res.$clusterTime.signature.keyId > NumberLong(0)); + + assert.hasFields(res, ["operationTime"]); + assert(Object.prototype.toString.call(res.operationTime) === "[object Timestamp]", + "operationTime must be a timestamp"); + } + + let st = new ShardingTest({shards: {rs0: {nodes: 2}}, other: {keyFile: keyFile}}); + + jsTestLog("Started ShardingTest"); + + var adminDB = st.s.getDB("admin"); + adminDB.createUser({user: adminUser.username, pwd: adminUser.password, roles: ["__system"]}); + + adminDB.auth(adminUser.username, adminUser.password); + assert(st.s.getDB("admin").system.keys.count() >= 2); + + let priRSConn = st.rs0.getPrimary().getDB("admin"); + priRSConn.createUser({user: rUser.username, pwd: rUser.password, roles: ["root"]}); + + // TODO: SERVER-34964 + sleep(30000); + + priRSConn.auth(rUser.username, rUser.password); + const resWithKeys = priRSConn.runCommand({isMaster: 1}); + assertContainsValidLogicalTime(resWithKeys); + + // Enable the failpoint, remove all keys, and restart the config servers with the failpoint + // still enabled to guarantee there are no keys. + for (let i = 0; i < st.configRS.nodes.length; i++) { + assert.commandWorked(st.configRS.nodes[i].adminCommand( + {"configureFailPoint": "disableKeyGeneration", "mode": "alwaysOn"})); + } + + var priCSConn = st.configRS.getPrimary(); + authutil.asCluster(priCSConn, keyFile, function() { + priCSConn.getDB("admin").system.keys.remove({purpose: "HMAC"}); + }); + + assert(adminDB.system.keys.count() == 0, "expected there to be no keys on the config server"); + + st.configRS.stopSet(null /* signal */, true /* forRestart */); + st.configRS.startSet( + {restart: true, setParameter: {"failpoint.disableKeyGeneration": "{'mode':'alwaysOn'}"}}); + + // bounce rs0 to clean the key cache + st.rs0.stopSet(null /* signal */, true /* forRestart */); + st.rs0.startSet({restart: true}); + + priRSConn.auth(rUser.username, rUser.password); + const resNoKeys = priRSConn.runCommand({isMaster: 1}); + assert.commandWorked(resNoKeys); + + assert.eq(resNoKeys.hasOwnProperty("$clusterTime"), false); + assert.eq(resNoKeys.hasOwnProperty("operationTime"), false); + + st.stop(); +})(); |