0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-25 09:19:32 +01:00
mongodb/jstests/auth/user_management_commands_mechanisms.js
2022-02-24 02:51:46 +00:00

241 lines
8.3 KiB
JavaScript

// Ensure that created/updated users have the correct credentials.
// @tags: [requires_persistence]
(function() {
'use strict';
let mongod = MongoRunner.runMongod(
{auth: "", setParameter: "authenticationMechanisms=SCRAM-SHA-1,SCRAM-SHA-256,PLAIN"});
const admin = mongod.getDB('admin');
const test = mongod.getDB('test');
function checkUser(userid, passwd, haveSCRAMSHA1, haveSCRAMSHA256) {
function checkCredentialRecord(creds, hashLen, saltLen, itCount) {
assert.eq(creds.iterationCount, itCount);
assert.eq(creds.salt.length, saltLen);
assert.eq(creds.storedKey.length, hashLen);
assert.eq(creds.serverKey.length, hashLen);
}
function checkLogin(mech, digestOK, nodigestOK) {
assert(test.auth({user: userid, pwd: passwd, mechanism: mech}));
test.logout();
assert.eq(digestOK,
test.auth({user: userid, pwd: passwd, mechanism: mech, digestPassword: true}));
if (digestOK) {
test.logout();
}
assert.eq(nodigestOK,
test.auth({user: userid, pwd: passwd, mechanism: mech, digestPassword: false}));
if (nodigestOK) {
test.logout();
}
}
assert(admin.auth('admin', 'pass'));
const user = admin.system.users.findOne({_id: ('test.' + userid)});
assert.eq(user.credentials.hasOwnProperty('SCRAM-SHA-1'), haveSCRAMSHA1);
assert.eq(user.credentials.hasOwnProperty('SCRAM-SHA-256'), haveSCRAMSHA256);
// usersInfo contains correct mechanisms for the user
const userInfo = assert.commandWorked(test.runCommand({usersInfo: userid}));
assert(Array.isArray(userInfo.users[0].mechanisms));
assert.eq(userInfo.users[0].mechanisms.includes('SCRAM-SHA-1'), haveSCRAMSHA1);
assert.eq(userInfo.users[0].mechanisms.includes('SCRAM-SHA-256'), haveSCRAMSHA256);
// usersInfo with showCredentials shows correct mechanisms and credentials
const userInfoWithCredentials =
assert.commandWorked(test.runCommand({usersInfo: userid, showCredentials: true}));
print(tojson(userInfoWithCredentials));
assert.eq(userInfoWithCredentials.users[0].credentials.hasOwnProperty('SCRAM-SHA-1'),
haveSCRAMSHA1);
assert.eq(userInfoWithCredentials.users[0].credentials.hasOwnProperty('SCRAM-SHA-256'),
haveSCRAMSHA256);
assert(Array.isArray(userInfoWithCredentials.users[0].mechanisms));
assert.eq(userInfoWithCredentials.users[0].mechanisms.includes('SCRAM-SHA-1'), haveSCRAMSHA1);
assert.eq(userInfoWithCredentials.users[0].mechanisms.includes('SCRAM-SHA-256'),
haveSCRAMSHA256);
admin.logout();
if (haveSCRAMSHA1) {
checkCredentialRecord(user.credentials['SCRAM-SHA-1'], 28, 24, 10000);
checkLogin('SCRAM-SHA-1', true, false);
checkLogin('PLAIN', false, true);
}
if (haveSCRAMSHA256) {
checkCredentialRecord(user.credentials['SCRAM-SHA-256'], 44, 40, 15000);
checkLogin('SCRAM-SHA-256', false, true);
checkLogin('PLAIN', false, true);
}
}
admin.createUser({user: 'admin', pwd: 'pass', roles: jsTest.adminUserRoles});
assert(admin.auth('admin', 'pass'));
function createUser(db, user) {
assert(admin.auth('admin', 'pass'));
db.createUser(user);
admin.logout();
}
function createUserThrows(db, user) {
assert(admin.auth('admin', 'pass'));
assert.throws(() => db.createUser(user));
admin.logout();
}
// Unknown mechanism.
createUserThrows(test, {
user: 'shalala',
pwd: 'pass',
roles: jsTest.basicUserRoles,
mechanisms: ['SCRAM-SHA-1', 'SCRAM-SHA-LA-LA'],
});
// By default, users are created with both SCRAM variants.
createUser(test, {user: 'user', pwd: 'pass', roles: jsTest.basicUserRoles});
checkUser('user', 'pass', true, true);
// Request SHA1 only.
createUser(
test,
{user: 'sha1user', pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: ['SCRAM-SHA-1']});
checkUser('sha1user', 'pass', true, false);
// Request SHA256 only.
createUser(
test,
{user: 'sha256user', pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: ['SCRAM-SHA-256']});
checkUser('sha256user', 'pass', false, true);
// Fail passing an empty mechanisms field.
createUserThrows(test,
{user: 'userNoMech', pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: []});
// Repeat above, but request client-side digesting.
// Only the SCRAM-SHA-1 exclusive version should succeed.
createUserThrows(
test, {user: 'user2', pwd: 'pass', roles: jsTest.basicUserRoles, passwordDisgestor: 'client'});
createUser(test, {
user: 'sha1user2',
pwd: 'pass',
roles: jsTest.basicUserRoles,
mechanisms: ['SCRAM-SHA-1'],
passwordDigestor: 'client'
});
checkUser('sha1user2', 'pass', true, false);
createUserThrows(test, {
user: 'sha256user2',
pwd: 'pass',
roles: jsTest.basicUserRoles,
mechanisms: ['SCRAM-SHA-256'],
passwordDigestor: 'client'
});
function updateUser(db, user, props) {
assert(admin.auth('admin', 'pass'));
db.updateUser(user, props);
admin.logout();
}
function updateUserThrows(db, user, props) {
assert(admin.auth('admin', 'pass'));
assert.throws(() => db.updateUser(user, props));
admin.logout();
}
// Update original 1/256 user to just sha-1.
updateUser(test, 'user', {pwd: 'pass1', mechanisms: ['SCRAM-SHA-1']});
checkUser('user', 'pass1', true, false);
// Then flip to 256-only
updateUser(test, 'user', {pwd: 'pass256', mechanisms: ['SCRAM-SHA-256']});
checkUser('user', 'pass256', false, true);
// And back to (default) all.
updateUser(test, 'user', {pwd: 'passAll'});
checkUser('user', 'passAll', true, true);
// Trim out mechanisms without changing password.
updateUser(test, 'user', {mechanisms: ['SCRAM-SHA-256']});
checkUser('user', 'passAll', false, true);
// Fail when mechanisms is not a subset of the current user.
updateUserThrows(test, 'user', {mechanisms: ['SCRAM-SHA-1']});
// Fail when passing an empty mechanisms field.
updateUserThrows(test, 'user', {pwd: 'passEmpty', mechanisms: []});
// Succeed if we're using SHA-1 only.
createUser(
test, {user: "\u2168", pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: ['SCRAM-SHA-1']});
checkUser("\u2168", 'pass', true, false);
assert(admin.auth('admin', 'pass'));
// Demonstrate that usersInfo returns all users with mechanisms lists
const allUsersInfo = assert.commandWorked(test.runCommand({usersInfo: 1}));
allUsersInfo.users.forEach(function(userObj) {
assert(Array.isArray(userObj.mechanisms));
});
// Demonstrate that usersInfo can return all users with credentials
const allUsersInfoWithCredentials =
assert.commandWorked(test.runCommand({usersInfo: 1, showCredentials: true}));
allUsersInfoWithCredentials.users.forEach(function(userObj) {
assert(userObj.credentials !== undefined);
assert(!Array.isArray(userObj.credentials));
assert(userObj.mechanisms !== undefined);
assert(Array.isArray(userObj.mechanisms));
});
// Demonstrate that usersInfo can find SCRAM-SHA-1 users
const allSCRAMSHA1UsersInfo =
assert.commandWorked(test.runCommand({usersInfo: 1, filter: {mechanisms: "SCRAM-SHA-1"}}));
let foundUsers = [];
allSCRAMSHA1UsersInfo.users.forEach(function(userObj) {
foundUsers.push(userObj.user);
});
assert.eq(["sha1user", "sha1user2", "\u2168"], foundUsers);
// Demonstrate that usersInfo can find SCRAM-SHA-256 users
const allSCRAMSHA256UsersInfo =
assert.commandWorked(test.runCommand({usersInfo: 1, filter: {mechanisms: "SCRAM-SHA-256"}}));
foundUsers = [];
allSCRAMSHA256UsersInfo.users.forEach(function(userObj) {
foundUsers.push(userObj.user);
});
assert.eq(["sha256user", "user"], foundUsers);
MongoRunner.stopMongod(mongod);
// Ensure mechanisms can be enabled and disabled.
function restartWithOneMech(mech) {
const sha1ok = (mech === 'SCRAM-SHA-1');
const sha256ok = (mech === 'SCRAM-SHA-256');
mongod = MongoRunner.runMongod({
auth: "",
setParameter: "authenticationMechanisms=" + mech,
restart: mongod,
noCleanData: true
});
const test = mongod.getDB('test');
assert.eq(test.auth("sha1user", "pass"), sha1ok);
if (sha1ok) {
test.logout();
}
assert.eq(test.auth("sha256user", "pass"), sha256ok);
if (sha256ok) {
test.logout();
}
assert(mongod.getDB('admin').auth('admin', 'pass'));
MongoRunner.stopMongod(mongod);
}
restartWithOneMech('SCRAM-SHA-1');
restartWithOneMech('SCRAM-SHA-256');
})();