mirror of https://github.com/mongodb/mongo
200 lines
6.4 KiB
JavaScript
200 lines
6.4 KiB
JavaScript
/**
|
|
* This tests the access control for the pseudo-commands inprog, curop, and killop. Once
|
|
* SERVER-5466 is resolved this test should be removed and its functionality merged into
|
|
* commands_builtin_roles.js and commands_user_defined_roles.js.
|
|
* @tags: [requires_sharding]
|
|
*/
|
|
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
function runTest(conn) {
|
|
conn.getDB("admin").createUser({user: "admin", pwd: "pwd", roles: ["root"]});
|
|
|
|
const adminConn = new Mongo(conn.host);
|
|
const admin = adminConn.getDB("admin");
|
|
|
|
assert(admin.auth("admin", "pwd"));
|
|
admin.createRole({role: "myRole", roles: [], privileges: []});
|
|
admin.createUser({user: "spencer", pwd: "pwd", roles: ["myRole"]});
|
|
const arbitraryShard = admin.getSiblingDB("config").shards.findOne();
|
|
|
|
const db = conn.getDB("admin");
|
|
assert(db.auth("spencer", "pwd"));
|
|
|
|
/**
|
|
* Tests that a single operation has the proper authorization. The operation is run by invoking
|
|
* "testFunc". "testFunc" must take a single argument indicating whether we expect the test to
|
|
* pass or fail due to being unauthorized. Roles in an object that described which roles are
|
|
* expected to be able to run the operation, and privilege is the privilege that must be granted
|
|
* a user-defined-role in order to run the operation.
|
|
*/
|
|
function testProperAuthorization(testFunc, roles, privilege) {
|
|
// Test built-in roles first
|
|
for (let role in roles) {
|
|
admin.updateRole("myRole", {roles: [role]});
|
|
testFunc(roles[role]);
|
|
}
|
|
|
|
// Now test user-defined role
|
|
admin.updateRole("myRole", {roles: [], privileges: [privilege]});
|
|
testFunc(true);
|
|
|
|
admin.updateRole("myRole", {roles: [], privileges: []});
|
|
testFunc(false);
|
|
}
|
|
|
|
/**
|
|
* Returns true if conn is a connection to mongos,
|
|
* and false otherwise.
|
|
*/
|
|
function isMongos(db) {
|
|
let res = db.adminCommand({isdbgrid: 1});
|
|
return res.ok == 1 && res.isdbgrid == 1;
|
|
}
|
|
|
|
(function testInprog() {
|
|
jsTestLog("Testing inprog");
|
|
|
|
let roles = {
|
|
read: false,
|
|
readAnyDatabase: false,
|
|
readWrite: false,
|
|
readWriteAnyDatabase: false,
|
|
dbAdmin: false,
|
|
dbAdminAnyDatabase: false,
|
|
dbOwner: false,
|
|
clusterMonitor: true,
|
|
clusterManager: false,
|
|
hostManager: false,
|
|
clusterAdmin: true,
|
|
root: true,
|
|
__system: true,
|
|
};
|
|
|
|
let privilege = {resource: {cluster: true}, actions: ["inprog"]};
|
|
|
|
let testFunc = function (shouldPass) {
|
|
let passed = true;
|
|
try {
|
|
var res = db.currentOp();
|
|
passed = res.ok && !res.hasOwnProperty("errmsg");
|
|
} catch (e) {
|
|
passed = false;
|
|
}
|
|
|
|
assert.eq(shouldPass, passed);
|
|
if (shouldPass) {
|
|
assert.gte(res.inprog.length, 0);
|
|
}
|
|
};
|
|
|
|
testProperAuthorization(testFunc, roles, privilege);
|
|
})();
|
|
|
|
(function testKillop() {
|
|
jsTestLog("Testing killOp");
|
|
|
|
let roles = {
|
|
read: false,
|
|
readAnyDatabase: false,
|
|
readWrite: false,
|
|
readWriteAnyDatabase: false,
|
|
dbAdmin: false,
|
|
dbAdminAnyDatabase: false,
|
|
dbOwner: false,
|
|
clusterMonitor: false,
|
|
clusterManager: false,
|
|
hostManager: true,
|
|
clusterAdmin: true,
|
|
root: true,
|
|
__system: true,
|
|
};
|
|
|
|
let privilege = {resource: {cluster: true}, actions: ["killop"]};
|
|
|
|
let testFunc = function (shouldPass) {
|
|
let passed = true;
|
|
try {
|
|
let opid;
|
|
const maxOpId = Math.pow(2, 31) - 1; // Operation id cannot exceed INT_MAX.
|
|
if (isMongos(db)) {
|
|
// opid format different between mongos and mongod
|
|
opid = arbitraryShard._id + ":" + maxOpId.toString();
|
|
} else {
|
|
opid = maxOpId;
|
|
}
|
|
let res = db.killOp(opid);
|
|
printjson(res);
|
|
passed = res.ok && !res.errmsg && !res.err && !res["$err"];
|
|
} catch (e) {
|
|
passed = false;
|
|
}
|
|
assert.eq(shouldPass, passed);
|
|
};
|
|
|
|
testProperAuthorization(testFunc, roles, privilege);
|
|
})();
|
|
|
|
(function testUnlock() {
|
|
if (isMongos(db)) {
|
|
return; // unlock doesn't work on mongos
|
|
}
|
|
|
|
jsTestLog("Testing unlock");
|
|
|
|
let roles = {
|
|
read: false,
|
|
readAnyDatabase: false,
|
|
readWrite: false,
|
|
readWriteAnyDatabase: false,
|
|
dbAdmin: false,
|
|
dbAdminAnyDatabase: false,
|
|
dbOwner: false,
|
|
clusterMonitor: false,
|
|
clusterManager: false,
|
|
hostManager: true,
|
|
clusterAdmin: true,
|
|
root: true,
|
|
__system: true,
|
|
};
|
|
|
|
let privilege = {resource: {cluster: true}, actions: ["unlock"]};
|
|
|
|
let testFunc = function (shouldPass) {
|
|
let passed = true;
|
|
try {
|
|
let ret = admin.fsyncLock(); // must be locked first
|
|
// If the storage engine doesnt support fsync lock, we can't proceed
|
|
if (!ret.ok) {
|
|
assert.commandFailedWithCode(ret, ErrorCodes.CommandNotSupported);
|
|
assert(shouldPass); // If we get to the storage engine, we better be authorized.
|
|
return;
|
|
}
|
|
let res = db.fsyncUnlock();
|
|
printjson(res);
|
|
passed = res.ok && !res.errmsg && !res.err && !res["$err"];
|
|
passed = passed || false; // convert undefined to false
|
|
} catch (e) {
|
|
passed = false;
|
|
}
|
|
if (!passed) {
|
|
admin.fsyncUnlock();
|
|
}
|
|
|
|
assert.eq(shouldPass, passed);
|
|
};
|
|
|
|
testProperAuthorization(testFunc, roles, privilege);
|
|
})();
|
|
}
|
|
|
|
jsTest.log("Test standalone");
|
|
let conn = MongoRunner.runMongod({auth: ""});
|
|
runTest(conn);
|
|
MongoRunner.stopMongod(conn);
|
|
|
|
jsTest.log("Test sharding");
|
|
let st = new ShardingTest({shards: 2, config: 3, keyFile: "jstests/libs/key1"});
|
|
runTest(st.s);
|
|
st.stop();
|