mirror of https://github.com/mongodb/mongo
267 lines
8.3 KiB
JavaScript
267 lines
8.3 KiB
JavaScript
/*
|
|
* Tests that resource pattern matching rules work as expected.
|
|
* @tags: [requires_replication, requires_sharding]
|
|
*/
|
|
|
|
// This test logs in users on the admin database, but doesn't log them out, which can fail with
|
|
// implicit sessions and ReplSetTest when the fixture attempts to verify data hashes at shutdown by
|
|
// authenticating as the __system user.
|
|
TestData.disableImplicitSessions = true;
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
function setup_users(granter) {
|
|
const admin = granter.getSiblingDB("admin");
|
|
assert.commandWorked(admin.runCommand({
|
|
createUser: "admin",
|
|
pwd: "admin",
|
|
roles:
|
|
["userAdminAnyDatabase",
|
|
"dbAdminAnyDatabase",
|
|
"clusterAdmin",
|
|
"readWriteAnyDatabase"]
|
|
}));
|
|
|
|
assert(admin.auth("admin", "admin"));
|
|
printjson(admin.runCommand({createRole: "test_role", privileges: [], roles: []}));
|
|
printjson(admin.runCommand({createUser: "test_user", pwd: "password", roles: ["test_role"]}));
|
|
admin.logout();
|
|
}
|
|
|
|
function setup_dbs_and_cols(db) {
|
|
const admin = db.getSiblingDB('admin');
|
|
const test_db_a = db.getSiblingDB('a');
|
|
const test_db_b = db.getSiblingDB('b');
|
|
|
|
assert(admin.auth('admin', 'admin'));
|
|
assert.commandWorked(test_db_a.dropDatabase({w: 'majority'}));
|
|
assert.commandWorked(test_db_b.dropDatabase({w: 'majority'}));
|
|
|
|
assert.commandWorked(test_db_a.createCollection("a", {writeConcern: {w: 'majority'}}));
|
|
assert.commandWorked(test_db_a.createCollection("b", {writeConcern: {w: 'majority'}}));
|
|
|
|
assert.commandWorked(test_db_b.createCollection("a", {writeConcern: {w: 'majority'}}));
|
|
assert.commandWorked(test_db_b.createCollection("b", {writeConcern: {w: 'majority'}}));
|
|
admin.logout();
|
|
}
|
|
|
|
function grant_privileges(granter, privileges) {
|
|
const admin = granter.getSiblingDB("admin");
|
|
|
|
assert(admin.auth("admin", "admin"));
|
|
const result = admin.runCommand({
|
|
grantPrivilegesToRole: "test_role",
|
|
privileges: privileges,
|
|
writeConcern: {w: 'majority'}
|
|
});
|
|
admin.logout();
|
|
return result;
|
|
}
|
|
|
|
function revoke_privileges(granter, privileges) {
|
|
const admin = granter.getSiblingDB("admin");
|
|
|
|
assert(admin.auth("admin", "admin"));
|
|
const result = admin.runCommand({
|
|
revokePrivilegesFromRole: "test_role",
|
|
privileges: privileges,
|
|
writeConcern: {w: 'majority'}
|
|
});
|
|
admin.logout();
|
|
return result;
|
|
}
|
|
|
|
function invalidateUserCache(verifier) {
|
|
const admin = verifier.getSiblingDB("admin");
|
|
assert(admin.auth('admin', 'admin'));
|
|
assert.commandWorked(admin.runCommand("invalidateUserCache"));
|
|
admin.logout();
|
|
}
|
|
|
|
function run_test(name, granter, verifier, privileges, collections) {
|
|
print("\n=== testing " + name + "() ===\n");
|
|
|
|
grant_privileges(granter, privileges);
|
|
invalidateUserCache(verifier);
|
|
|
|
const verifierDB = verifier.getSiblingDB('admin');
|
|
assert(verifierDB.auth("test_user", "password"));
|
|
|
|
for (var key in collections) {
|
|
const parts = key.split(".");
|
|
const testdb = verifier.getSiblingDB(parts[0]);
|
|
const col = testdb.getCollection(parts[1]);
|
|
|
|
const cb = collections[key];
|
|
|
|
cb(testdb, col);
|
|
}
|
|
verifierDB.logout();
|
|
|
|
revoke_privileges(granter, privileges);
|
|
}
|
|
|
|
function run_test_bad_resource(name, granter, resource) {
|
|
print("\n=== testing resource fail " + name + "() ===\n");
|
|
assert.commandFailed(grant_privileges(granter, [{resource: resource, actions: ["find"]}]));
|
|
}
|
|
|
|
function should_insert(testdb, testcol) {
|
|
assert.doesNotThrow(function() {
|
|
testcol.insert({a: "b"});
|
|
});
|
|
}
|
|
|
|
function should_fail_insert(testdb, testcol) {
|
|
assert.throws(function() {
|
|
testcol.insert({a: "b"});
|
|
});
|
|
}
|
|
|
|
function should_find(testdb, testcol) {
|
|
assert.doesNotThrow(function() {
|
|
testcol.findOne();
|
|
});
|
|
}
|
|
|
|
function should_fail_find(testdb, testcol) {
|
|
assert.throws(function() {
|
|
testcol.findOne();
|
|
});
|
|
}
|
|
|
|
function run_tests(granter, verifier) {
|
|
setup_users(granter);
|
|
setup_dbs_and_cols(granter);
|
|
|
|
run_test("specific",
|
|
granter,
|
|
verifier,
|
|
[{resource: {db: "a", collection: "a"}, actions: ["find"]}],
|
|
{
|
|
"a.a": should_find,
|
|
"a.b": should_fail_find,
|
|
"b.a": should_fail_find,
|
|
"b.b": should_fail_find
|
|
});
|
|
|
|
run_test(
|
|
"glob_collection",
|
|
granter,
|
|
verifier,
|
|
[{resource: {db: "a", collection: ""}, actions: ["find"]}],
|
|
{"a.a": should_find, "a.b": should_find, "b.a": should_fail_find, "b.b": should_fail_find});
|
|
|
|
run_test(
|
|
"glob_database",
|
|
granter,
|
|
verifier,
|
|
[{resource: {db: "", collection: "a"}, actions: ["find"]}],
|
|
{"a.a": should_find, "a.b": should_fail_find, "b.a": should_find, "b.b": should_fail_find});
|
|
|
|
run_test("glob_all",
|
|
granter,
|
|
verifier,
|
|
[{resource: {db: "", collection: ""}, actions: ["find"]}],
|
|
{"a.a": should_find, "a.b": should_find, "b.a": should_find, "b.b": should_find});
|
|
|
|
run_test(
|
|
"any_resource", granter, verifier, [{resource: {anyResource: true}, actions: ["find"]}], {
|
|
"a.a": should_find,
|
|
"a.b": should_find,
|
|
"b.a": should_find,
|
|
"b.b": should_find,
|
|
"c.a": should_find
|
|
});
|
|
|
|
run_test("no_global_access",
|
|
granter,
|
|
verifier,
|
|
[{resource: {db: "$", collection: "cmd"}, actions: ["find"]}],
|
|
{
|
|
"a.a": function(testdb, testcol) {
|
|
var r = testdb.stats();
|
|
|
|
if (r["ok"])
|
|
throw ("db.$.cmd shouldn't give a.stats()");
|
|
}
|
|
});
|
|
|
|
run_test_bad_resource("empty_resource", granter, {});
|
|
run_test_bad_resource("users_collection_any_db", granter, {collection: "users"});
|
|
run_test_bad_resource("bad_key", granter, {myResource: "users"});
|
|
run_test_bad_resource("extra_key", granter, {db: "test", collection: "users", cluster: true});
|
|
run_test_bad_resource("bad_value_type", granter, {cluster: "false"});
|
|
run_test_bad_resource("bad_collection", granter, {db: "test", collection: "$$$$"});
|
|
|
|
run_test("mixed_find_write",
|
|
granter,
|
|
verifier,
|
|
[
|
|
{resource: {db: "a", collection: "a"}, actions: ["find"]},
|
|
{resource: {db: "", collection: ""}, actions: ["insert"]}
|
|
],
|
|
{
|
|
"a.a": function(testdb, testcol) {
|
|
should_insert(testdb, testcol);
|
|
should_find(testdb, testcol);
|
|
},
|
|
"a.b": function(testdb, testcol) {
|
|
should_insert(testdb, testcol);
|
|
should_fail_find(testdb, testcol);
|
|
},
|
|
"b.a": function(testdb, testcol) {
|
|
should_insert(testdb, testcol);
|
|
should_fail_find(testdb, testcol);
|
|
},
|
|
"b.b": function(testdb, testcol) {
|
|
should_insert(testdb, testcol);
|
|
should_fail_find(testdb, testcol);
|
|
},
|
|
});
|
|
}
|
|
|
|
const keyfile = "jstests/libs/key1";
|
|
|
|
{
|
|
print('--- standalone node test ---');
|
|
const conn = MongoRunner.runMongod({auth: null, keyFile: keyfile});
|
|
run_tests(conn.getDB('test'), conn.getDB('test'));
|
|
MongoRunner.stopMongod(conn);
|
|
print('--- done standalone node test ---');
|
|
}
|
|
|
|
{
|
|
print('--- replica set test ---');
|
|
const rst =
|
|
new ReplSetTest({name: 'testset', nodes: 2, nodeOptions: {'auth': null}, keyFile: keyfile});
|
|
|
|
rst.startSet();
|
|
rst.initiate();
|
|
const primary = rst.getPrimary().getDB('admin');
|
|
rst.awaitSecondaryNodes();
|
|
const secondary = rst.getSecondaries()[0].getDB('admin');
|
|
run_tests(primary, secondary);
|
|
rst.stopSet();
|
|
print('--- done with the rs tests ---');
|
|
}
|
|
|
|
{
|
|
print('--- sharding test ---');
|
|
const st = new ShardingTest({
|
|
mongos: 2,
|
|
shard: 1,
|
|
keyFile: keyfile,
|
|
other: {
|
|
mongosOptions: {'auth': null},
|
|
configOptions: {'auth': null},
|
|
shardOptions: {'auth': null}
|
|
}
|
|
});
|
|
run_tests(st.s0.getDB('admin'), st.s1.getDB('admin'));
|
|
st.stop();
|
|
print('--- sharding test done ---');
|
|
}
|
|
})();
|