diff options
Diffstat (limited to 'jstests/auth/kill_cursors.js')
-rw-r--r-- | jstests/auth/kill_cursors.js | 328 |
1 files changed, 156 insertions, 172 deletions
diff --git a/jstests/auth/kill_cursors.js b/jstests/auth/kill_cursors.js index dc49c7dba59..3d9a535311b 100644 --- a/jstests/auth/kill_cursors.js +++ b/jstests/auth/kill_cursors.js @@ -1,190 +1,174 @@ // Test the killCursors command. // @tags: [requires_sharding] (function() { - 'use strict'; - - // TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. - TestData.disableImplicitSessions = true; - - function runTest(mongod) { - /** - * Open a cursor on `db` while authenticated as `authUsers`. - * Then logout, and log back in as `killUsers` and try to kill that cursor. - * - * @param db - The db to create a cursor on and ultimately kill agains. - * @param authUsers - Array of ['username', db] pairs to create the cursor under. - * @param killUsers - Array of ['username', dn] pairs to use when killing. - * @param shouldWork - Whether we expect success - */ - function tryKill(db, authUsers, killUsers, shouldWork) { - function loginAll(users) { - users.forEach(function(u) { - assert(u[1].auth(u[0], 'pass')); - }); - } +'use strict'; + +// TODO SERVER-35447: Multiple users cannot be authenticated on one connection within a session. +TestData.disableImplicitSessions = true; + +function runTest(mongod) { + /** + * Open a cursor on `db` while authenticated as `authUsers`. + * Then logout, and log back in as `killUsers` and try to kill that cursor. + * + * @param db - The db to create a cursor on and ultimately kill agains. + * @param authUsers - Array of ['username', db] pairs to create the cursor under. + * @param killUsers - Array of ['username', dn] pairs to use when killing. + * @param shouldWork - Whether we expect success + */ + function tryKill(db, authUsers, killUsers, shouldWork) { + function loginAll(users) { + users.forEach(function(u) { + assert(u[1].auth(u[0], 'pass')); + }); + } - function logoutAll() { - [testA, testB].forEach(function(d) { - const users = assert.commandWorked(d.runCommand({connectionStatus: 1})) - .authInfo.authenticatedUsers; - users.forEach(function(u) { - mongod.getDB(u.db).logout(); - }); + function logoutAll() { + [testA, testB].forEach(function(d) { + const users = assert.commandWorked(d.runCommand({connectionStatus: 1})) + .authInfo.authenticatedUsers; + users.forEach(function(u) { + mongod.getDB(u.db).logout(); }); - } + }); + } - function doKill(extra) { - // Create a cursor to be killed later. - loginAll(authUsers); - let cmd = {find: db.coll.getName(), batchSize: 2}; - Object.assign(cmd, extra); - const id = assert.commandWorked(db.runCommand(cmd)).cursor.id; - assert.neq(id, 0, "Invalid cursor ID"); - logoutAll(); - - loginAll(killUsers); - const killCmd = db.runCommand({killCursors: db.coll.getName(), cursors: [id]}); - logoutAll(); - if (shouldWork) { - assert.commandWorked(killCmd, "Unable to kill cursor"); - } else { - assert.commandFailed(killCmd, "Should not have been able to kill cursor"); - } + function doKill(extra) { + // Create a cursor to be killed later. + loginAll(authUsers); + let cmd = {find: db.coll.getName(), batchSize: 2}; + Object.assign(cmd, extra); + const id = assert.commandWorked(db.runCommand(cmd)).cursor.id; + assert.neq(id, 0, "Invalid cursor ID"); + logoutAll(); + + loginAll(killUsers); + const killCmd = db.runCommand({killCursors: db.coll.getName(), cursors: [id]}); + logoutAll(); + if (shouldWork) { + assert.commandWorked(killCmd, "Unable to kill cursor"); + } else { + assert.commandFailed(killCmd, "Should not have been able to kill cursor"); } + } - doKill({}); + doKill({}); - if ((authUsers.length === 1) && (killUsers.length === 1)) { - // Session variant only makes sense with single auth'd users. - doKill({lsid: {id: BinData(4, "QlLfPHTySm6tqfuV+EOsVA==")}}); - } + if ((authUsers.length === 1) && (killUsers.length === 1)) { + // Session variant only makes sense with single auth'd users. + doKill({lsid: {id: BinData(4, "QlLfPHTySm6tqfuV+EOsVA==")}}); } + } - function trySelfKill(user) { - const db = user[1]; - assert(db.auth(user[0], 'pass')); - - assert.commandWorked(db.runCommand({startSession: 1})); + function trySelfKill(user) { + const db = user[1]; + assert(db.auth(user[0], 'pass')); - const cmd = { - aggregate: 1, - pipeline: [{$listLocalSessions: {}}], - cursor: {batchSize: 0} - }; - const res = assert.commandWorked(db.runCommand(cmd)); - print(tojson(res)); - const id = res.cursor.id; - assert.neq(id, 0, "Invalid cursor ID"); + assert.commandWorked(db.runCommand({startSession: 1})); - const killCmdRes = db.runCommand({killCursors: db.getName() + ".$cmd", cursors: [id]}); - db.logout(); + const cmd = {aggregate: 1, pipeline: [{$listLocalSessions: {}}], cursor: {batchSize: 0}}; + const res = assert.commandWorked(db.runCommand(cmd)); + print(tojson(res)); + const id = res.cursor.id; + assert.neq(id, 0, "Invalid cursor ID"); - assert.commandWorked(killCmdRes, "Unable to kill cursor"); - } + const killCmdRes = db.runCommand({killCursors: db.getName() + ".$cmd", cursors: [id]}); + db.logout(); - /** - * Create user1/user2 in testA, and user3/user4 in testB. - * Create two 101 element collections in testA and testB. - * Use various combinations of those users to open cursors, - * then (potentially) different combinations of users to kill them. - * - * A cursor should only be killable if at least one of the users - * who created it is trying to kill it. - */ - - const testA = mongod.getDB('testA'); - const testB = mongod.getDB('testB'); - const admin = mongod.getDB('admin'); - - // Setup users - admin.createUser({user: 'admin', pwd: 'pass', roles: jsTest.adminUserRoles}); - assert(admin.auth('admin', 'pass')); - - testA.createUser({user: 'user1', pwd: 'pass', roles: jsTest.basicUserRoles}); - testA.createUser({user: 'user2', pwd: 'pass', roles: jsTest.basicUserRoles}); - testB.createUser({user: 'user3', pwd: 'pass', roles: jsTest.basicUserRoles}); - testB.createUser({user: 'user4', pwd: 'pass', roles: jsTest.basicUserRoles}); - testB.createUser({user: 'user5', pwd: 'pass', roles: []}); - admin.logout(); - - // Create a collection with batchable data - assert(testA.auth('user1', 'pass')); - assert(testB.auth('user3', 'pass')); - for (var i = 0; i < 101; ++i) { - assert.writeOK(testA.coll.insert({_id: i})); - assert.writeOK(testB.coll.insert({_id: i})); - } - testA.logout(); - testB.logout(); - - // A user can kill their own cursor. - tryKill(testA, [['user1', testA]], [['user1', testA]], true); - tryKill(testA, [['user2', testA]], [['user2', testA]], true); - tryKill(testB, [['user3', testB]], [['user3', testB]], true); - tryKill(testB, [['user4', testB]], [['user4', testB]], true); - trySelfKill(['user1', testA]); - trySelfKill(['user5', testB]); - trySelfKill(['admin', admin]); - - // A user cannot kill someone else's cursor. - tryKill(testA, [['user1', testA]], [['user2', testA]], false); - tryKill(testA, [['user1', testA]], [['user2', testA], ['user3', testB]], false); - tryKill(testA, [['user2', testA]], [['user1', testA]], false); - tryKill(testA, [['user2', testA]], [['user1', testA], ['user3', testB]], false); - tryKill(testB, [['user3', testB]], [['user1', testA], ['user4', testB]], false); - tryKill(testB, [['user3', testB]], [['user2', testA], ['user4', testB]], false); - - // A multi-owned cursor can be killed by any/all owner. - tryKill(testA, [['user1', testA], ['user3', testB]], [['user1', testA]], true); - tryKill(testB, [['user1', testA], ['user3', testB]], [['user3', testB]], true); - tryKill(testA, - [['user1', testA], ['user3', testB]], - [['user1', testA], ['user3', testB]], - true); - tryKill(testA, - [['user1', testA], ['user3', testB]], - [['user2', testA], ['user3', testB]], - true); - tryKill(testB, - [['user1', testA], ['user3', testB]], - [['user1', testA], ['user3', testB]], - true); - tryKill(testB, - [['user1', testA], ['user3', testB]], - [['user1', testA], ['user4', testB]], - true); - - // An owned cursor can not be killed by other user(s). - tryKill(testA, - [['user1', testA], ['user3', testB]], - [['user2', testA], ['user4', testB]], - false); - tryKill(testA, [['user1', testA]], [['user2', testA], ['user3', testB]], false); - tryKill(testA, - [['user1', testA], ['user3', testB]], - [['user2', testA], ['user4', testB]], - false); - - // Admin can kill anything. - tryKill(testA, [['user1', testA]], [['admin', admin]], true); - tryKill(testA, [['user2', testA]], [['admin', admin]], true); - tryKill(testB, [['user3', testB]], [['admin', admin]], true); - tryKill(testB, [['user4', testB]], [['admin', admin]], true); - tryKill(testA, [['user1', testA], ['user3', testB]], [['admin', admin]], true); - tryKill(testB, [['user2', testA], ['user4', testB]], [['admin', admin]], true); + assert.commandWorked(killCmdRes, "Unable to kill cursor"); } - const mongod = MongoRunner.runMongod({auth: ""}); - runTest(mongod); - MongoRunner.stopMongod(mongod); - - // TODO: Remove 'shardAsReplicaSet: false' when SERVER-32672 is fixed. - const st = new ShardingTest({ - shards: 1, - mongos: 1, - config: 1, - other: {keyFile: 'jstests/libs/key1', shardAsReplicaSet: false} - }); - runTest(st.s0); - st.stop(); + /** + * Create user1/user2 in testA, and user3/user4 in testB. + * Create two 101 element collections in testA and testB. + * Use various combinations of those users to open cursors, + * then (potentially) different combinations of users to kill them. + * + * A cursor should only be killable if at least one of the users + * who created it is trying to kill it. + */ + + const testA = mongod.getDB('testA'); + const testB = mongod.getDB('testB'); + const admin = mongod.getDB('admin'); + + // Setup users + admin.createUser({user: 'admin', pwd: 'pass', roles: jsTest.adminUserRoles}); + assert(admin.auth('admin', 'pass')); + + testA.createUser({user: 'user1', pwd: 'pass', roles: jsTest.basicUserRoles}); + testA.createUser({user: 'user2', pwd: 'pass', roles: jsTest.basicUserRoles}); + testB.createUser({user: 'user3', pwd: 'pass', roles: jsTest.basicUserRoles}); + testB.createUser({user: 'user4', pwd: 'pass', roles: jsTest.basicUserRoles}); + testB.createUser({user: 'user5', pwd: 'pass', roles: []}); + admin.logout(); + + // Create a collection with batchable data + assert(testA.auth('user1', 'pass')); + assert(testB.auth('user3', 'pass')); + for (var i = 0; i < 101; ++i) { + assert.writeOK(testA.coll.insert({_id: i})); + assert.writeOK(testB.coll.insert({_id: i})); + } + testA.logout(); + testB.logout(); + + // A user can kill their own cursor. + tryKill(testA, [['user1', testA]], [['user1', testA]], true); + tryKill(testA, [['user2', testA]], [['user2', testA]], true); + tryKill(testB, [['user3', testB]], [['user3', testB]], true); + tryKill(testB, [['user4', testB]], [['user4', testB]], true); + trySelfKill(['user1', testA]); + trySelfKill(['user5', testB]); + trySelfKill(['admin', admin]); + + // A user cannot kill someone else's cursor. + tryKill(testA, [['user1', testA]], [['user2', testA]], false); + tryKill(testA, [['user1', testA]], [['user2', testA], ['user3', testB]], false); + tryKill(testA, [['user2', testA]], [['user1', testA]], false); + tryKill(testA, [['user2', testA]], [['user1', testA], ['user3', testB]], false); + tryKill(testB, [['user3', testB]], [['user1', testA], ['user4', testB]], false); + tryKill(testB, [['user3', testB]], [['user2', testA], ['user4', testB]], false); + + // A multi-owned cursor can be killed by any/all owner. + tryKill(testA, [['user1', testA], ['user3', testB]], [['user1', testA]], true); + tryKill(testB, [['user1', testA], ['user3', testB]], [['user3', testB]], true); + tryKill( + testA, [['user1', testA], ['user3', testB]], [['user1', testA], ['user3', testB]], true); + tryKill( + testA, [['user1', testA], ['user3', testB]], [['user2', testA], ['user3', testB]], true); + tryKill( + testB, [['user1', testA], ['user3', testB]], [['user1', testA], ['user3', testB]], true); + tryKill( + testB, [['user1', testA], ['user3', testB]], [['user1', testA], ['user4', testB]], true); + + // An owned cursor can not be killed by other user(s). + tryKill( + testA, [['user1', testA], ['user3', testB]], [['user2', testA], ['user4', testB]], false); + tryKill(testA, [['user1', testA]], [['user2', testA], ['user3', testB]], false); + tryKill( + testA, [['user1', testA], ['user3', testB]], [['user2', testA], ['user4', testB]], false); + + // Admin can kill anything. + tryKill(testA, [['user1', testA]], [['admin', admin]], true); + tryKill(testA, [['user2', testA]], [['admin', admin]], true); + tryKill(testB, [['user3', testB]], [['admin', admin]], true); + tryKill(testB, [['user4', testB]], [['admin', admin]], true); + tryKill(testA, [['user1', testA], ['user3', testB]], [['admin', admin]], true); + tryKill(testB, [['user2', testA], ['user4', testB]], [['admin', admin]], true); +} + +const mongod = MongoRunner.runMongod({auth: ""}); +runTest(mongod); +MongoRunner.stopMongod(mongod); + +// TODO: Remove 'shardAsReplicaSet: false' when SERVER-32672 is fixed. +const st = new ShardingTest({ + shards: 1, + mongos: 1, + config: 1, + other: {keyFile: 'jstests/libs/key1', shardAsReplicaSet: false} +}); +runTest(st.s0); +st.stop(); })(); |