1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
// Test that manually inserted impersonation can't escalate privileges.
// @tags: [requires_replication]
(function() {
'use strict';
function testMongod(mongod, systemuserpwd = undefined) {
const admin = mongod.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 kImpersonatedHello = {
hello: 1,
"$audit": {
"$impersonatedUser": {user: 'admin', db: 'admin'},
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
}
};
assertError(
kImpersonatedHello, 'Unauthorized use of impersonation metadata', ErrorCodes.Unauthorized);
// TODO SERVER-72448: Remove
const kImpersonatedHelloLegacy = {
hello: 1,
"$audit": {
"$impersonatedUsers": [{user: 'admin', db: 'admin'}],
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
}
};
assertError(kImpersonatedHelloLegacy,
'Unauthorized use of impersonation metadata',
ErrorCodes.Unauthorized);
// TODO SERVER-72448: Remove, checks that both legacy and new impersonation metadata fields
// cannot be set simultaneously.
const kImpersonatedHelloBoth = {
hello: 1,
"$audit": {
"$impersonatedUser": {user: 'admin', db: 'admin'},
"$impersonatedUsers": [{user: 'admin', db: 'admin'}],
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
}
};
assertError(kImpersonatedHelloBoth,
'Cannot specify both $impersonatedUser and $impersonatedUsers',
ErrorCodes.BadValue);
// TODO SERVER-72448: Remove, checks that the legacy impersonation metadata field can only
// contain at most 1 field if specified.
const kImpersonatedHelloLegacyMultiple = {
hello: 1,
"$audit": {
"$impersonatedUsers": [{user: 'admin', db: 'admin'}, {user: 'test', db: 'pwd'}],
"$impersonatedRoles": [{role: 'root', db: 'admin'}],
}
};
assertError(kImpersonatedHelloLegacyMultiple,
'Can only impersonate up to one user per connection',
ErrorCodes.BadValue);
// Try as admin (root role), should still fail.
admin.auth('admin', 'admin');
assertError(
kImpersonatedHello, 'Unauthorized use of impersonation metadata', ErrorCodes.Unauthorized);
admin.logout();
if (systemuserpwd !== undefined) {
// On a ReplSet, our impersonation payload should be fine with cluster user.
jsTest.log('Positive test, impersonation is okay when we\'re local.__system');
const local = mongod.getDB('local');
local.auth('__system', systemuserpwd);
assert.commandWorked(admin.runCommand(kImpersonatedHello));
local.logout();
}
jsTest.log('End');
}
{
const standalone = MongoRunner.runMongod({auth: ''});
testMongod(standalone);
MongoRunner.stopMongod(standalone);
}
{
const kKeyfile = 'jstests/libs/key1';
const kKey = cat(kKeyfile).replace(/[\011-\015\040]/g, '');
const rst = new ReplSetTest({nodes: 2});
rst.startSet({keyFile: kKeyfile});
rst.initiate();
rst.awaitSecondaryNodes();
testMongod(rst.getPrimary(), kKey);
rst.stopSet();
}
})();
|