// Test role restrictions when using security tokens. // @tags: [requires_replication, featureFlagSecurityToken] import {runCommandWithSecurityToken} from "jstests/libs/multitenancy_utils.js"; import {ReplSetTest} from "jstests/libs/replsettest.js"; const tenantID = ObjectId(); const kVTSKey = "secret"; function runTest(conn, rst = undefined) { const admin = conn.getDB("admin"); const external = conn.getDB("$external"); // Must be authenticated as a user with ActionType::useTenant in order to use unsigned security // token. assert.commandWorked(admin.runCommand({createUser: "admin", pwd: "pwd", roles: ["root"]})); assert(admin.auth("admin", "pwd")); // Create tenant-specific users. const users = { readOnlyUser: {roles: [{role: "readAnyDatabase", db: "admin"}]}, readWriteUser: {roles: [{role: "readWriteAnyDatabase", db: "admin"}]}, clusterAdminUser: {roles: [{role: "clusterAdmin", db: "admin"}], prohibited: true}, }; const unsignedToken = _createTenantToken({tenant: tenantID}); Object.keys(users).forEach((user) => assert.commandWorked( runCommandWithSecurityToken(unsignedToken, external, {createUser: user, roles: users[user].roles}), ), ); if (rst) { rst.awaitReplication(); } Object.keys(users).forEach(function (user) { const tokenConn = new Mongo(conn.host); tokenConn._setSecurityToken(_createSecurityToken({user: user, db: "$external", tenant: tenantID}, kVTSKey)); const tokenDB = tokenConn.getDB("test"); if (users[user].prohibited) { assert.commandFailed(tokenDB.adminCommand({connectionStatus: 1})); } else { const authInfo = assert.commandWorked(tokenDB.adminCommand({connectionStatus: 1})).authInfo; jsTest.log(authInfo); assert.eq(authInfo.authenticatedUsers.length, 1); assert.eq(authInfo.authenticatedUsers[0].user, user); assert.eq(authInfo.authenticatedUsers[0].db, "$external"); const authedRoles = authInfo.authenticatedUserRoles.map((role) => role.db + "." + role.role); const expectRoles = users[user].roles.map((role) => role.db + "." + role.role); const unexpectedRoles = authedRoles.filter((role) => !expectRoles.includes(role)); assert.eq(unexpectedRoles.length, 0, "Unexpected roles: " + tojson(unexpectedRoles)); const missingRoles = expectRoles.filter((role) => !authedRoles.includes(role)); assert.eq(missingRoles.length, 0, "Missing roles: " + tojson(missingRoles)); } }); } const opts = { auth: "", setParameter: { multitenancySupport: true, testOnlyValidatedTenancyScopeKey: kVTSKey, }, }; { const standalone = MongoRunner.runMongod(opts); assert(standalone !== null, "MongoD failed to start"); runTest(standalone); MongoRunner.stopMongod(standalone); } { const rst = new ReplSetTest({nodes: 2, nodeOptions: opts}); rst.startSet({keyFile: "jstests/libs/key1"}); rst.initiate(); runTest(rst.getPrimary(), rst); rst.stopSet(); }