mongo/jstests/auth/impersonation-deny.js

94 lines
3.3 KiB
JavaScript

// Test that manually inserted impersonation can't escalate privileges.
// @tags: [requires_replication]
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {ShardingTest} from "jstests/libs/shardingtest.js";
function runTest(conn, keyFile = undefined) {
const admin = conn.getDB("admin");
admin.createUser({user: "admin", pwd: "admin", roles: ["root"]});
function assertError(cmd, msg, code) {
const errmsg = assert.commandFailedWithCode(admin.runCommand(cmd), code).errmsg;
assert(errmsg.includes(msg), "Error message is missing '" + msg + "': " + errmsg);
}
jsTest.log("Start - Sanity check without impersonation metadata");
// Localhost authbypass is disabled, and we haven't logged in,
// so normal auth-required commands should fail.
assertError({usersInfo: 1}, "Command usersInfo requires authentication", ErrorCodes.Unauthorized);
// Hello command requires no auth, so it works fine.
assert.commandWorked(admin.runCommand({hello: 1}));
jsTest.log("Negative tests - Add impersonation metadata to hello command");
// Adding impersonation metadata is forbidden if we're not permitted to use it.
const kImpersonatedUserHello = {
hello: 1,
"$audit": {
"$impersonatedUser": {user: "admin", db: "admin"},
"$impersonatedRoles": [{role: "root", db: "admin"}],
},
};
const kImpersonatedClientHello = {
hello: 1,
"$audit": {
"$impersonatedClient": {hosts: ["172.23.55.11:23890", "192.43.22.3:14089"]},
"$impersonatedRoles": [],
},
};
assertError(kImpersonatedUserHello, "Unauthorized use of impersonation metadata", ErrorCodes.Unauthorized);
assertError(kImpersonatedClientHello, "Unauthorized use of impersonation metadata", ErrorCodes.Unauthorized);
// Try as admin (root role), should still fail.
admin.auth("admin", "admin");
assertError(kImpersonatedUserHello, "Unauthorized use of impersonation metadata", ErrorCodes.Unauthorized);
assertError(kImpersonatedClientHello, "Unauthorized use of impersonation metadata", ErrorCodes.Unauthorized);
admin.logout();
if (keyFile !== undefined) {
// On a ReplSet or mongos, our impersonation payload should be fine with cluster user.
jsTest.log("Positive test, impersonation is okay when we're local.__system");
authutil.asCluster(conn, keyFile, () => {
assert.commandWorked(admin.runCommand(kImpersonatedUserHello));
assert.commandWorked(admin.runCommand(kImpersonatedClientHello));
});
}
jsTest.log("End");
}
{
const standalone = MongoRunner.runMongod({auth: ""});
runTest(standalone);
MongoRunner.stopMongod(standalone);
}
{
const kKeyfile = "jstests/libs/key1";
const rst = new ReplSetTest({nodes: 2});
rst.startSet({keyFile: kKeyfile});
rst.initiate();
rst.awaitSecondaryNodes();
runTest(rst.getPrimary(), kKeyfile);
rst.stopSet();
}
{
const kKeyfile = "jstests/libs/key1";
const st = new ShardingTest({
mongos: 1,
config: 1,
shard: 2,
keyFile: kKeyfile,
other: {mongosOptions: {auth: null}, configOptions: {auth: null}, rsOptions: {auth: null}},
});
runTest(st.s0, kKeyfile);
st.stop();
}