mirror of https://github.com/mongodb/mongo
166 lines
6.2 KiB
JavaScript
166 lines
6.2 KiB
JavaScript
/**
|
|
* Tests that a user's ability to view open cursors via $currentOp obeys authentication rules on
|
|
* both mongoD and mongoS.
|
|
* @tags: [assumes_read_concern_unchanged, requires_auth, requires_replication]
|
|
*/
|
|
import {FixtureHelpers} from "jstests/libs/fixture_helpers.js";
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
// Create a new sharded cluster for testing and enable auth.
|
|
const key = "jstests/libs/key1";
|
|
const st = new ShardingTest({name: jsTestName(), keyFile: key, shards: 1});
|
|
|
|
const shardConn = st.rs0.getPrimary();
|
|
const mongosConn = st.s;
|
|
|
|
shardConn.waitForClusterTime(60);
|
|
|
|
Random.setRandomSeed();
|
|
const pass = "a" + Random.rand();
|
|
|
|
// Create one root user and one regular user on the given connection.
|
|
function createUsers(conn, grantDirectShardOperationsRole) {
|
|
const adminDB = conn.getDB("admin");
|
|
|
|
adminDB.createUser({user: "ted", pwd: pass, roles: ["root"]});
|
|
assert(adminDB.auth("ted", pass), "Authentication 1 Failed");
|
|
|
|
let yutaRoles = ["readWriteAnyDatabase"];
|
|
if (grantDirectShardOperationsRole) yutaRoles.push("directShardOperations");
|
|
|
|
adminDB.createUser({user: "yuta", pwd: pass, roles: yutaRoles});
|
|
}
|
|
|
|
// Create the necessary users at the shard local level.
|
|
createUsers(shardConn, /* grantDirectShardOperationsRole */ true);
|
|
|
|
// Create the necessary users at the cluster level. If the shard is a configShard, then the users
|
|
// will have already been created on the config server from the previous createUsers() call.
|
|
if (!TestData.configShard) {
|
|
createUsers(mongosConn, /* grantDirectShardOperationsRole */ false);
|
|
} else {
|
|
// Even though we've skipped creating the users, we still need to log in on the mongos for the
|
|
// rest of the test.
|
|
assert(mongosConn.getDB("admin").auth("ted", pass), "Authentication 1 Failed");
|
|
}
|
|
|
|
// Run the various auth tests on the given shard or mongoS connection.
|
|
function runCursorTests(conn) {
|
|
const db = conn.getDB("test");
|
|
const adminDB = db.getSiblingDB("admin");
|
|
|
|
// Log in as the root user.
|
|
assert.commandWorked(adminDB.logout());
|
|
assert(adminDB.auth("ted", pass), "Authentication 2 Failed");
|
|
|
|
const coll = db.jstests_currentop_cursors_auth;
|
|
coll.drop();
|
|
for (let i = 0; i < 5; ++i) {
|
|
assert.commandWorked(coll.insert({val: i}));
|
|
}
|
|
|
|
// Verify that we can see our own cursor with {allUsers: false}.
|
|
const cursorId = assert.commandWorked(db.runCommand({find: "jstests_currentop_cursors_auth", batchSize: 2})).cursor
|
|
.id;
|
|
|
|
let result = adminDB
|
|
.aggregate([
|
|
{$currentOp: {localOps: true, allUsers: false, idleCursors: true}},
|
|
{$match: {$and: [{type: "idleCursor"}, {"cursor.cursorId": cursorId}]}},
|
|
])
|
|
.toArray();
|
|
assert.eq(result.length, 1, result);
|
|
|
|
// Log in as the non-root user.
|
|
assert.commandWorked(adminDB.logout());
|
|
assert(adminDB.auth("yuta", pass), "Authentication 3 Failed");
|
|
|
|
// Verify that we cannot see the root user's cursor.
|
|
result = adminDB
|
|
.aggregate([
|
|
{$currentOp: {localOps: true, allUsers: false, idleCursors: true}},
|
|
{$match: {$and: [{type: "idleCursor"}, {"cursor.cursorId": cursorId}]}},
|
|
])
|
|
.toArray();
|
|
assert.eq(result.length, 0, result);
|
|
|
|
// Make sure that the behavior is the same when 'allUsers' is not explicitly specified.
|
|
result = adminDB
|
|
.aggregate([
|
|
{$currentOp: {localOps: true, idleCursors: true}},
|
|
{$match: {$and: [{type: "idleCursor"}, {"cursor.cursorId": cursorId}]}},
|
|
])
|
|
.toArray();
|
|
assert.eq(result.length, 0, result);
|
|
|
|
// Verify that the user without the 'inprog' privilege cannot view shard cursors via mongoS.
|
|
if (FixtureHelpers.isMongos(db)) {
|
|
assert.commandFailedWithCode(
|
|
adminDB.runCommand({
|
|
aggregate: 1,
|
|
pipeline: [{$currentOp: {localOps: false, idleCursors: true}}],
|
|
cursor: {},
|
|
}),
|
|
ErrorCodes.Unauthorized,
|
|
);
|
|
}
|
|
|
|
// Create a cursor with the second (non-root) user and confirm that we can see it.
|
|
const secondCursorId = assert.commandWorked(db.runCommand({find: "jstests_currentop_cursors_auth", batchSize: 2}))
|
|
.cursor.id;
|
|
|
|
result = adminDB
|
|
.aggregate([
|
|
{$currentOp: {localOps: true, allUsers: false, idleCursors: true}},
|
|
{$match: {$and: [{type: "idleCursor"}, {"cursor.cursorId": secondCursorId}]}},
|
|
])
|
|
.toArray();
|
|
assert.eq(result.length, 1, result);
|
|
|
|
// Log back in with the root user and confirm that the first cursor is still present.
|
|
assert.commandWorked(adminDB.logout());
|
|
assert(adminDB.auth("ted", pass), "Authentication 4 Failed");
|
|
|
|
result = adminDB
|
|
.aggregate([
|
|
{$currentOp: {localOps: true, allUsers: false, idleCursors: true}},
|
|
{$match: {$and: [{type: "idleCursor"}, {"cursor.cursorId": cursorId}]}},
|
|
])
|
|
.toArray();
|
|
assert.eq(result.length, 1, result);
|
|
|
|
// Confirm that the root user can see both users' cursors with {allUsers: true}.
|
|
result = adminDB
|
|
.aggregate([
|
|
{$currentOp: {localOps: true, allUsers: true, idleCursors: true}},
|
|
{$match: {type: "idleCursor", "cursor.cursorId": {$in: [cursorId, secondCursorId]}}},
|
|
])
|
|
.toArray();
|
|
assert.eq(result.length, 2, result);
|
|
|
|
// The root user can also see both cursors on the shard via mongoS with {localOps: false}.
|
|
if (FixtureHelpers.isMongos(db)) {
|
|
result = adminDB
|
|
.aggregate([
|
|
{$currentOp: {localOps: false, allUsers: true, idleCursors: true}},
|
|
{$match: {type: "idleCursor", shard: st.shard0.shardName}},
|
|
])
|
|
.toArray();
|
|
assert.eq(result.length, 2, result);
|
|
}
|
|
|
|
// Clean up the cursors so that they don't affect subsequent tests.
|
|
assert.commandWorked(db.runCommand({killCursors: coll.getName(), cursors: [cursorId, secondCursorId]}));
|
|
|
|
// Make sure to logout to allow __system user to use the implicit session.
|
|
assert.commandWorked(adminDB.logout());
|
|
}
|
|
|
|
jsTestLog("Running cursor tests on mongoD");
|
|
runCursorTests(shardConn);
|
|
|
|
jsTestLog("Running cursor tests on mongoS");
|
|
runCursorTests(mongosConn);
|
|
|
|
st.stop();
|