mongo/jstests/auth/user_defined_roles.js

151 lines
6.3 KiB
JavaScript

/**
* This tests that user defined roles actually grant users the ability to perform the actions they
* should, and that changing the privileges assigned to roles changes the access granted to the user
* @tags: [requires_sharding]
*/
import {ShardingTest} from "jstests/libs/shardingtest.js";
function runTest(conn) {
let authzErrorCode = 13;
let hasAuthzError = function (result) {
assert(result instanceof WriteCommandError);
assert.eq(authzErrorCode, result.code);
};
conn.getDB("admin").createUser({user: "admin", pwd: "pwd", roles: ["root"]});
conn.getDB("admin").auth("admin", "pwd");
conn.getDB("admin").createUser({user: "userAdmin", pwd: "pwd", roles: ["userAdminAnyDatabase"]});
conn.getDB("admin").logout();
let userAdminConn = new Mongo(conn.host);
let adminUserAdmin = userAdminConn.getDB("admin");
adminUserAdmin.auth("userAdmin", "pwd");
adminUserAdmin.createRole({role: "adminRole", privileges: [], roles: []});
let testUserAdmin = userAdminConn.getDB("test");
testUserAdmin.createRole({role: "testRole1", privileges: [], roles: []});
testUserAdmin.createRole({role: "testRole2", privileges: [], roles: ["testRole1"]});
testUserAdmin.createUser({user: "testUser", pwd: "pwd", roles: ["testRole2", {role: "adminRole", db: "admin"}]});
let testDB = conn.getDB("test");
assert(testDB.auth("testUser", "pwd"));
// At this point there are 3 db handles in use. testUserAdmin and adminUserAdmin are handles to
// the "test" and "admin" dbs respectively. Both testUserAdmin and adminUserAdmin are on the
// same connection (userAdminConn) which has been auth'd as a user with the
// 'userAdminAnyDatabase' role. Those will be used for manipulating the user defined roles
// used in the test. "testDB" is a handle to the test database on a connection that has been
// auth'd as 'testUser@test' - this is the connection that will be used to test how privilege
// enforcement works.
// test CRUD
hasAuthzError(testDB.foo.insert({a: 1}));
assert.throws(function () {
testDB.foo.findOne();
});
testUserAdmin.grantPrivilegesToRole("testRole1", [{resource: {db: "test", collection: ""}, actions: ["find"]}]);
hasAuthzError(testDB.foo.insert({a: 1}));
assert.doesNotThrow(function () {
testDB.foo.findOne();
});
assert.eq(0, testDB.foo.count());
assert.eq(0, testDB.foo.find().itcount());
testUserAdmin.grantPrivilegesToRole("testRole1", [
{resource: {db: "test", collection: "foo"}, actions: ["insert"]},
]);
assert.commandWorked(testDB.foo.insert({a: 1}));
assert.eq(1, testDB.foo.findOne().a);
assert.eq(1, testDB.foo.count());
assert.eq(1, testDB.foo.find().itcount());
hasAuthzError(testDB.foo.update({a: 1}, {$inc: {a: 1}}));
assert.eq(1, testDB.foo.findOne().a);
hasAuthzError(testDB.bar.insert({a: 1}));
assert.eq(0, testDB.bar.count());
adminUserAdmin.grantPrivilegesToRole("adminRole", [{resource: {db: "", collection: "foo"}, actions: ["update"]}]);
assert.commandWorked(testDB.foo.update({a: 1}, {$inc: {a: 1}}));
assert.eq(2, testDB.foo.findOne().a);
assert.commandWorked(testDB.foo.update({b: 1}, {$inc: {b: 1}}, true)); // upsert
assert.eq(2, testDB.foo.count());
assert.eq(2, testDB.foo.findOne({b: {$exists: true}}).b);
hasAuthzError(testDB.foo.remove({b: 2}));
assert.eq(2, testDB.foo.count());
adminUserAdmin.grantPrivilegesToRole("adminRole", [{resource: {db: "", collection: ""}, actions: ["remove"]}]);
assert.commandWorked(testDB.foo.remove({b: 2}));
assert.eq(1, testDB.foo.count());
// Test revoking privileges
testUserAdmin.revokePrivilegesFromRole("testRole1", [
{resource: {db: "test", collection: "foo"}, actions: ["insert"]},
]);
hasAuthzError(testDB.foo.insert({a: 1}));
assert.eq(1, testDB.foo.count());
assert.commandWorked(testDB.foo.update({a: 2}, {$inc: {a: 1}}));
assert.eq(3, testDB.foo.findOne({a: {$exists: true}}).a);
hasAuthzError(testDB.foo.update({c: 1}, {$inc: {c: 1}}, true)); // upsert should fail
assert.eq(1, testDB.foo.count());
// Test changeOwnPassword/changeOwnCustomData
assert.throws(function () {
testDB.changeUserPassword("testUser", "password");
});
assert.throws(function () {
testDB.updateUser("testUser", {customData: {zipCode: 10036}});
});
assert.eq(null, testDB.getUser("testUser").customData);
testUserAdmin.grantPrivilegesToRole("testRole1", [
{
resource: {db: "test", collection: ""},
actions: ["changeOwnPassword", "changeOwnCustomData"],
},
]);
testDB.changeUserPassword("testUser", "password");
assert(!testDB.auth("testUser", "pwd"));
assert(testDB.auth("testUser", "password"));
testDB.updateUser("testUser", {customData: {zipCode: 10036}});
assert.eq(10036, testDB.getUser("testUser").customData.zipCode);
testUserAdmin.revokeRolesFromRole("testRole2", ["testRole1"]);
assert.throws(function () {
testDB.changeUserPassword("testUser", "pwd");
});
assert.throws(function () {
testDB.foo.findOne();
});
assert.throws(function () {
testDB.updateUser("testUser", {customData: {zipCode: 10028}});
});
assert.eq(10036, testDB.getUser("testUser").customData.zipCode);
// Test changeAnyPassword/changeAnyCustomData
testUserAdmin.grantPrivilegesToRole("testRole2", [
{resource: {db: "test", collection: ""}, actions: ["changePassword", "changeCustomData"]},
]);
testDB.changeUserPassword("testUser", "pwd");
assert(!testDB.auth("testUser", "password"));
assert(testDB.auth("testUser", "pwd"));
testDB.updateUser("testUser", {customData: {zipCode: 10028}});
assert.eq(10028, testDB.getUser("testUser").customData.zipCode);
// Test privileges on the cluster resource
assert.commandFailed(testDB.runCommand({serverStatus: 1}));
adminUserAdmin.grantPrivilegesToRole("adminRole", [{resource: {cluster: true}, actions: ["serverStatus"]}]);
assert.commandWorked(testDB.serverStatus());
}
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();