mirror of https://github.com/mongodb/mongo
154 lines
6.2 KiB
JavaScript
154 lines
6.2 KiB
JavaScript
// Auth test the listDatabases command.
|
|
export function runTest(mongod) {
|
|
const admin = mongod.getDB("admin");
|
|
admin.createUser({user: "admin", pwd: "pass", roles: jsTest.adminUserRoles});
|
|
assert(admin.auth("admin", "pass"));
|
|
|
|
// Establish db0..db7
|
|
for (let i = 0; i < 8; ++i) {
|
|
mongod.getDB("db" + i).foo.insert({bar: "baz"});
|
|
}
|
|
mongod.getDB("db0").baz.insert({x: "y"});
|
|
mongod.getDB("db2").baz.insert({x: "y"});
|
|
|
|
admin.createRole({
|
|
role: "dbLister",
|
|
privileges: [{resource: {cluster: true}, actions: ["listDatabases"]}],
|
|
roles: [],
|
|
});
|
|
|
|
admin.createRole({
|
|
role: "specificCollection",
|
|
privileges: [{resource: {db: "db0", collection: "baz"}, actions: ["find"]}],
|
|
roles: [],
|
|
});
|
|
|
|
admin.createRole({
|
|
role: "sharedNameCollections",
|
|
privileges: [{resource: {db: "", collection: "baz"}, actions: ["find"]}],
|
|
roles: [],
|
|
});
|
|
|
|
// Make db0, db2, db4, db6 readable to user1 abd user3.
|
|
// Make db0, db1, db2, db3 read/writable to user 2 and user3.
|
|
function makeRole(perm, dbNum) {
|
|
return {role: perm, db: "db" + dbNum};
|
|
}
|
|
const readEven = [0, 2, 4, 6].map(function (i) {
|
|
return makeRole("read", i);
|
|
});
|
|
const readWriteLow = [0, 1, 2, 3].map(function (i) {
|
|
return makeRole("readWrite", i);
|
|
});
|
|
admin.createUser({user: "user1", pwd: "pass", roles: readEven});
|
|
admin.createUser({user: "user2", pwd: "pass", roles: readWriteLow});
|
|
admin.createUser({user: "user3", pwd: "pass", roles: readEven.concat(readWriteLow)});
|
|
|
|
// Make db4 readable by user 4, and let them list all dbs.
|
|
// Make db5 readable by user 5, and let them list all dbs.
|
|
// Make collection baz in db0 findable by user6, and let them list db0.
|
|
// Make all baz collections findable by user7, and let them list all dbs.
|
|
admin.createUser({user: "user4", pwd: "pass", roles: [makeRole("read", 4), "dbLister"]});
|
|
admin.createUser({user: "user5", pwd: "pass", roles: [makeRole("read", 5), "dbLister"]});
|
|
admin.createUser({user: "user6", pwd: "pass", roles: ["specificCollection"]});
|
|
admin.createUser({user: "user7", pwd: "pass", roles: ["sharedNameCollections"]});
|
|
admin.logout();
|
|
|
|
const admin_dbs = ["admin", "db0", "db1", "db2", "db3", "db4", "db5", "db6", "db7"];
|
|
|
|
[
|
|
{user: "user1", dbs: ["db0", "db2", "db4", "db6"]},
|
|
{user: "user2", dbs: ["db0", "db1", "db2", "db3"]},
|
|
{user: "user3", dbs: ["db0", "db1", "db2", "db3", "db4", "db6"]},
|
|
{user: "user4", dbs: admin_dbs, authDbs: ["db4"]},
|
|
{user: "user5", dbs: admin_dbs, authDbs: ["db5"]},
|
|
{user: "user6", dbs: ["db0"]},
|
|
{user: "user7", dbs: admin_dbs},
|
|
{user: "admin", dbs: admin_dbs, authDbs: admin_dbs},
|
|
].forEach(function (test) {
|
|
function filterSpecial(db) {
|
|
// Returning of local/config varies with sharding, etc..
|
|
// Ignore these for simplicity.
|
|
return db !== "local" && db !== "config";
|
|
}
|
|
|
|
// Invoking {listDatabases: 1} directly.
|
|
function tryList(cmd, expect_dbs) {
|
|
const dbs = assert.commandWorked(admin.runCommand(cmd));
|
|
assert.eq(
|
|
dbs.databases
|
|
.map(function (db) {
|
|
return db.name;
|
|
})
|
|
.filter(filterSpecial)
|
|
.sort(),
|
|
expect_dbs,
|
|
test.user + " permissions",
|
|
);
|
|
}
|
|
|
|
admin.auth(test.user, "pass");
|
|
tryList({listDatabases: 1}, test.dbs);
|
|
tryList({listDatabases: 1, authorizedDatabases: true}, test.authDbs || test.dbs);
|
|
|
|
if (test.authDbs) {
|
|
tryList({listDatabases: 1, authorizedDatabases: false}, test.dbs);
|
|
} else {
|
|
// Users without listDatabases cluster perm may not
|
|
// request authorizedDatabases: false.
|
|
assert.throws(tryList, [{listDatabases: 1, authorizedDatabases: false}, test.dbs]);
|
|
}
|
|
|
|
// Test using shell helper Mongo.getDBs().
|
|
assert.eq(
|
|
mongod.getDBs(undefined, {}, true).filter(filterSpecial),
|
|
test.dbs,
|
|
"Shell helper speaking to same version",
|
|
);
|
|
if (test.user !== "admin" && test.user !== "user7") {
|
|
// Admin and user7 don't have an explicit list of DBs to parse.
|
|
assert.eq(mongod._getDatabaseNamesFromPrivileges(), test.authDbs || test.dbs);
|
|
|
|
// Test (non-admin) call to Mongo.getDBs() on a < 4.0 MongoD
|
|
// by injecting a command failure into Mongo.adminCommand().
|
|
// This will allow us to resemble a < 4.0 server.
|
|
const adminCommandFunction = mongod.adminCommand;
|
|
const adminCommandMethod = adminCommandFunction.bind(mongod);
|
|
|
|
try {
|
|
mongod.adminCommand = function (cmd) {
|
|
if (cmd.hasOwnProperty("listDatabases")) {
|
|
return {
|
|
ok: 0,
|
|
errmsg: "Stubbed command failure: " + tojson(cmd),
|
|
code: ErrorCodes.Unauthorized,
|
|
codeName: "Unauthorized",
|
|
};
|
|
}
|
|
return adminCommandMethod(cmd);
|
|
};
|
|
// Command fails, but we dispatch via _getDatabaseNamesFromPrivileges().
|
|
assert.eq(
|
|
mongod.getDBs().databases.map(function (x) {
|
|
return x.name;
|
|
}),
|
|
test.authDbs || test.dbs,
|
|
);
|
|
|
|
// Still dispatches with explicit nameOnly===true, returns only names.
|
|
assert.eq(mongod.getDBs(undefined, undefined, true), test.authDbs || test.dbs);
|
|
|
|
// Command fails and unable to dispatch because nameOnly !== true.
|
|
assert.throws(() => mongod.getDBs(undefined, undefined, false));
|
|
|
|
// Command fails and unable to dispatch because filter is not empty.
|
|
assert.throws(() => mongod.getDBs(undefined, {name: "foo"}));
|
|
} finally {
|
|
mongod.adminCommand = adminCommandFunction;
|
|
}
|
|
}
|
|
|
|
admin.logout();
|
|
});
|
|
}
|