summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2022-02-04 19:05:54 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-02-24 02:51:46 +0000
commite4032fe5c39f1974c76de4cefdc07d98ab25aeef (patch)
tree3bba629166e40d1455cfc1cd65d299311670c535
parente9f462ba1ec6c1c105fab71239b9a958ae106484 (diff)
downloadmongo-e4032fe5c39f1974c76de4cefdc07d98ab25aeef.tar.gz
SERVER-57369 Disable concurrent authentication
-rw-r--r--jstests/auth/auth-counters.js12
-rw-r--r--jstests/auth/auth_mechanism_discovery.js5
-rw-r--r--jstests/auth/authentication_restrictions.js95
-rw-r--r--jstests/auth/authentication_restrictions_role.js117
-rw-r--r--jstests/auth/authz_cache_on_system_modification.js9
-rw-r--r--jstests/auth/basic_role_auth.js1
-rw-r--r--jstests/auth/clac_system_colls.js2
-rw-r--r--jstests/auth/cluster_ip_allowlist.js22
-rw-r--r--jstests/auth/commands_user_defined_roles.js142
-rw-r--r--jstests/auth/db_multiple_login.js48
-rw-r--r--jstests/auth/getMore.js63
-rw-r--r--jstests/auth/kill_cursors.js113
-rw-r--r--jstests/auth/list_all_sessions.js1
-rw-r--r--jstests/auth/list_local_sessions_base.js1
-rw-r--r--jstests/auth/list_sessions.js1
-rw-r--r--jstests/auth/profile.js72
-rw-r--r--jstests/auth/pseudo_commands.js22
-rw-r--r--jstests/auth/rename.js23
-rw-r--r--jstests/auth/renameRestrictedCollections.js19
-rw-r--r--jstests/auth/resource_pattern_matching.js149
-rw-r--r--jstests/auth/user_management_commands_lib.js44
-rw-r--r--jstests/auth/user_management_commands_mechanisms.js140
-rw-r--r--jstests/auth/user_special_chars.js11
-rw-r--r--jstests/auth/views_authz.js17
-rw-r--r--jstests/core/user_management_helpers.js44
-rw-r--r--jstests/multiVersion/libs/multi_rs.js32
-rw-r--r--jstests/noPassthrough/change_streams_required_privileges.js5
-rw-r--r--jstests/noPassthrough/multi_user_forbidden.js26
-rw-r--r--jstests/noPassthrough/start_session_command.js29
-rw-r--r--jstests/replsets/advance_cluster_time.js7
-rw-r--r--jstests/replsets/auth1.js12
-rw-r--r--jstests/replsets/rollback_auth.js165
-rw-r--r--jstests/sharding/advance_cluster_time_action_type.js2
-rw-r--r--jstests/sharding/authCommands.js1
-rw-r--r--jstests/sharding/commands_that_write_accept_wc_configRS.js110
-rw-r--r--jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js16
-rw-r--r--jstests/sharding/query/aggregation_currentop.js2
-rw-r--r--jstests/sharding/query/mrShardedOutputAuth.js39
-rw-r--r--jstests/ssl/auth-counters.js20
-rw-r--r--jstests/sslSpecial/upgrade_to_x509_ssl_nossl.js143
-rw-r--r--jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js11
-rw-r--r--src/mongo/db/auth/authorization_session_impl.cpp59
-rw-r--r--src/mongo/db/auth/authorization_session_test.cpp319
-rw-r--r--src/mongo/db/logical_session_id_test.cpp31
-rw-r--r--src/mongo/shell/replsettest.js13
45 files changed, 1051 insertions, 1164 deletions
diff --git a/jstests/auth/auth-counters.js b/jstests/auth/auth-counters.js
index b74fa531725..b1c6b54d4af 100644
--- a/jstests/auth/auth-counters.js
+++ b/jstests/auth/auth-counters.js
@@ -25,8 +25,14 @@ test.createUser(
// Count the number of authentications performed during setup
const expected =
assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication.mechanisms;
+admin.logout();
function assertStats() {
+ // Need to be authenticated to run serverStatus.
+ assert(admin.auth('admin', 'pwd'));
+ ++expected['SCRAM-SHA-256'].authenticate.successful;
+ ++expected['SCRAM-SHA-256'].authenticate.received;
+
const mechStats = assert.commandWorked(admin.runCommand({serverStatus: 1}))
.security.authentication.mechanisms;
Object.keys(expected).forEach(function(mech) {
@@ -45,13 +51,13 @@ function assertStats() {
throw e;
}
});
+
+ admin.logout();
}
function assertSuccess(creds, mech, db = test) {
assert.eq(db.auth(creds), true);
- if (db !== admin) {
- db.logout();
- }
+ db.logout();
++expected[mech].authenticate.received;
++expected[mech].authenticate.successful;
assertStats();
diff --git a/jstests/auth/auth_mechanism_discovery.js b/jstests/auth/auth_mechanism_discovery.js
index d17d1ddb03b..28d0a531d18 100644
--- a/jstests/auth/auth_mechanism_discovery.js
+++ b/jstests/auth/auth_mechanism_discovery.js
@@ -8,18 +8,19 @@ function runTest(conn) {
const test = conn.getDB("test");
admin.createUser({user: 'admin', pwd: 'pass', roles: jsTest.adminUserRoles});
- assert(admin.auth('admin', 'pass'));
// Verify user mechanism discovery.
function checkUser(username, mechanism) {
- var createUser = {createUser: username, pwd: 'pwd', roles: []};
+ const createUser = {createUser: username, pwd: 'pwd', roles: []};
if (mechanism !== undefined) {
createUser.mechanisms = [mechanism];
} else {
// Create both variants, expect to prefer 256.
mechanism = 'SCRAM-SHA-256';
}
+ assert(admin.auth('admin', 'pass'));
assert.commandWorked(test.runCommand(createUser));
+ admin.logout();
assert.eq(test._getDefaultAuthenticationMechanism(username, test.getName()), mechanism);
assert(test.auth(username, 'pwd'));
test.logout();
diff --git a/jstests/auth/authentication_restrictions.js b/jstests/auth/authentication_restrictions.js
index 9de899ef592..81d04565299 100644
--- a/jstests/auth/authentication_restrictions.js
+++ b/jstests/auth/authentication_restrictions.js
@@ -14,96 +14,105 @@ function testConnection(
load("jstests/libs/host_ipaddr.js");
// Create a session which observes an eventually consistent view of user data
- var eventualDb = eventuallyConsistentConn.getDB("admin");
+ const eventualDb = eventuallyConsistentConn.getDB("admin");
// Create a session for modifying user data during the life of the test
- var adminSession = new Mongo("localhost:" + conn.port);
- var admin = adminSession.getDB("admin");
+ const adminSession = new Mongo("localhost:" + conn.port);
+ const admin = adminSession.getDB("admin");
assert.commandWorked(admin.runCommand(
{createUser: "admin", pwd: "admin", roles: [{role: "root", db: "admin"}]}));
assert(admin.auth("admin", "admin"));
+ admin.logout();
// Create a strongly consistent session for consuming user data
- var db = conn.getDB("admin");
+ const db = conn.getDB("admin");
// Create a strongly consistent session for consuming user data, with a non-localhost
// source IP.
- var externalMongo = new Mongo(get_ipaddr() + ":" + conn.port);
- var externalDb = externalMongo.getDB("admin");
+ const externalMongo = new Mongo(get_ipaddr() + ":" + conn.port);
+ const externalDb = externalMongo.getDB("admin");
- assert.commandWorked(admin.runCommand({
+ // Create a connection which remains authenticated as 'admin'
+ // so that we can create/mutate users/roles while we do
+ // multiple authentications.
+ const adminMongo = new Mongo(conn.host);
+ const adminDB = adminMongo.getDB('admin');
+ assert(adminDB.auth('admin', 'admin'));
+
+ assert.commandWorked(adminDB.runCommand({
createUser: "user2",
pwd: "user",
roles: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"]}]
}));
- assert.commandWorked(admin.runCommand({createUser: "user3", pwd: "user", roles: []}));
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand({createUser: "user3", pwd: "user", roles: []}));
+ assert.commandWorked(adminDB.runCommand(
{updateUser: "user3", authenticationRestrictions: [{serverAddress: ["127.0.0.1"]}]}));
print("=== User creation tests");
print(
"When a client creates users with empty authenticationRestrictions, the operation succeeds, though it has no effect");
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{createUser: "user4", pwd: "user", roles: [], authenticationRestrictions: []}));
- assert(!Object.keys(admin.system.users.findOne({user: "user4"}))
+ assert(!Object.keys(adminDB.system.users.findOne({user: "user4"}))
.includes("authenticationRestrictions"));
print(
"When a client updates a user's authenticationRestrictions to be empty, the operation succeeds, and removes the authenticationRestrictions field");
- assert.commandWorked(admin.runCommand({createUser: "user5", pwd: "user", roles: []}));
- assert.commandWorked(admin.runCommand({updateUser: "user5", authenticationRestrictions: []}));
- assert(!Object.keys(admin.system.users.findOne({user: "user5"}))
+ assert.commandWorked(adminDB.runCommand({createUser: "user5", pwd: "user", roles: []}));
+ assert.commandWorked(adminDB.runCommand({updateUser: "user5", authenticationRestrictions: []}));
+ assert(!Object.keys(adminDB.system.users.findOne({user: "user5"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{updateUser: "user5", authenticationRestrictions: [{clientSource: ["127.0.0.1"]}]}));
- assert(Object.keys(admin.system.users.findOne({user: "user5"}))
+ assert(Object.keys(adminDB.system.users.findOne({user: "user5"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand({updateUser: "user5", authenticationRestrictions: []}));
- assert(!Object.keys(admin.system.users.findOne({user: "user5"}))
+ assert.commandWorked(adminDB.runCommand({updateUser: "user5", authenticationRestrictions: []}));
+ assert(!Object.keys(adminDB.system.users.findOne({user: "user5"}))
.includes("authenticationRestrictions"));
print(
"When a client updates a user's authenticationRestrictions to be null or undefined, the operation fails");
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{updateUser: "user5", authenticationRestrictions: [{clientSource: ["127.0.0.1"]}]}));
- assert(Object.keys(admin.system.users.findOne({user: "user5"}))
+ assert(Object.keys(adminDB.system.users.findOne({user: "user5"}))
.includes("authenticationRestrictions"));
- assert.commandFailed(admin.runCommand({updateUser: "user5", authenticationRestrictions: null}));
- assert(Object.keys(admin.system.users.findOne({user: "user5"}))
+ assert.commandFailed(
+ adminDB.runCommand({updateUser: "user5", authenticationRestrictions: null}));
+ assert(Object.keys(adminDB.system.users.findOne({user: "user5"}))
.includes("authenticationRestrictions"));
assert.commandFailed(
- admin.runCommand({updateUser: "user5", authenticationRestrictions: undefined}));
- assert(Object.keys(admin.system.users.findOne({user: "user5"}))
+ adminDB.runCommand({updateUser: "user5", authenticationRestrictions: undefined}));
+ assert(Object.keys(adminDB.system.users.findOne({user: "user5"}))
.includes("authenticationRestrictions"));
print(
"When a client creates users, it may use clientSource and serverAddress authenticationRestrictions");
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createUser: "user6",
pwd: "user",
roles: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"]}]
}));
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createUser: "user7",
pwd: "user",
roles: [],
authenticationRestrictions: [{serverAddress: ["127.0.0.1"]}]
}));
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createUser: "user8",
pwd: "user",
roles: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"], serverAddress: ["127.0.0.1"]}]
}));
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createUser: "user9",
pwd: "user",
roles: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"]}, {serverAddress: ["127.0.0.1"]}]
}));
- assert.commandFailed(admin.runCommand({
+ assert.commandFailed(adminDB.runCommand({
createUser: "user10",
pwd: "user",
roles: [],
@@ -115,14 +124,17 @@ function testConnection(
print(
"When a client on the loopback authenticates to a user with {clientSource: \"127.0.0.1\"}, it will succeed");
assert(db.auth("user6", "user"));
+ db.logout();
print(
"When a client on the loopback authenticates to a user with {serverAddress: \"127.0.0.1\"}, it will succeed");
assert(db.auth("user7", "user"));
+ db.logout();
print(
"When a client on the loopback authenticates to a user with {clientSource: \"127.0.0.1\", serverAddress: \"127.0.0.1\"}, it will succeed");
assert(db.auth("user8", "user"));
+ db.logout();
print("=== Remote access tests");
print(
@@ -140,51 +152,54 @@ function testConnection(
print("=== Invalidation tests");
print(
"When a client removes all authenticationRestrictions from a user, authentication will succeed");
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createUser: "user11",
pwd: "user",
roles: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"], serverAddress: ["127.0.0.1"]}]
}));
assert(!externalDb.auth("user11", "user"));
- assert.commandWorked(admin.runCommand({updateUser: "user11", authenticationRestrictions: []}));
+ assert.commandWorked(
+ adminDB.runCommand({updateUser: "user11", authenticationRestrictions: []}));
assert(externalDb.auth("user11", "user"));
+ externalDb.logout();
print(
"When a client sets authenticationRestrictions on a user, authorization privileges are revoked");
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{createUser: "user12", pwd: "user", roles: [{role: "readWrite", db: "test"}]}));
assert(db.auth("user12", "user"));
assert.commandWorked(db.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
+ db.logout();
sleepUntilUserDataPropagated();
assert(eventualDb.auth("user12", "user"));
assert.commandWorked(eventualDb.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{updateUser: "user12", authenticationRestrictions: [{clientSource: ["192.0.2.0"]}]}));
- assert.commandFailed(db.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
+ assert(!db.auth('user12', 'user'));
sleepUntilUserDataRefreshed();
assert.commandFailed(eventualDb.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
}
print("Testing standalone");
-var conn = MongoRunner.runMongod({bind_ip_all: "", auth: ""});
+const conn = MongoRunner.runMongod({bind_ip_all: "", auth: ""});
testConnection(conn, conn, function() {}, function() {});
MongoRunner.stopMongod(conn);
-var keyfile = "jstests/libs/key1";
+const keyfile = "jstests/libs/key1";
print("Testing replicaset");
-var rst = new ReplSetTest(
+const rst = new ReplSetTest(
{name: 'testset', nodes: 2, nodeOptions: {bind_ip_all: "", auth: ""}, keyFile: keyfile});
-var nodes = rst.startSet();
+const nodes = rst.startSet();
rst.initiate();
rst.awaitSecondaryNodes();
-var awaitReplication = function() {
+const awaitReplication = function() {
authutil.asCluster(nodes, "jstests/libs/key1", function() {
rst.awaitReplication();
});
@@ -194,7 +209,7 @@ testConnection(rst.getPrimary(), rst.getSecondary(), awaitReplication, awaitRepl
rst.stopSet();
print("Testing sharded cluster");
-var st = new ShardingTest({
+const st = new ShardingTest({
mongos: 2,
config: 3,
shard: 1,
diff --git a/jstests/auth/authentication_restrictions_role.js b/jstests/auth/authentication_restrictions_role.js
index e663e7e3b33..627edb6e618 100644
--- a/jstests/auth/authentication_restrictions_role.js
+++ b/jstests/auth/authentication_restrictions_role.js
@@ -14,98 +14,105 @@ function testRestrictionCreationAndEnforcement(
load("jstests/libs/host_ipaddr.js");
// Create a session which observes an eventually consistent view of user data
- var eventualDb = eventuallyConsistentConn.getDB("admin");
+ const eventualDb = eventuallyConsistentConn.getDB("admin");
// Create a session for modifying user data during the life of the test
- var adminSession = new Mongo("127.0.0.1:" + conn.port);
- var admin = adminSession.getDB("admin");
+ const adminSession = new Mongo("127.0.0.1:" + conn.port);
+ const admin = adminSession.getDB("admin");
assert.commandWorked(admin.runCommand(
{createUser: "admin", pwd: "admin", roles: [{role: "root", db: "admin"}]}));
assert(admin.auth("admin", "admin"));
// Create a strongly consistent session for consuming user data
- var db = conn.getDB("admin");
+ const db = conn.getDB("admin");
// Create a strongly consistent session for consuming user data, with a non-localhost
// source IP.
- var externalMongo = new Mongo(get_ipaddr() + ":" + conn.port);
- var externalDb = externalMongo.getDB("admin");
+ const externalMongo = new Mongo(get_ipaddr() + ":" + conn.port);
+ const externalDb = externalMongo.getDB("admin");
- assert.commandWorked(admin.runCommand({
+ // Create a connection which remains authenticated as 'admin'
+ // so that we can create/mutate users/roles while we do
+ // multiple authentications.
+ const adminMongo = new Mongo(conn.host);
+ const adminDB = adminMongo.getDB('admin');
+ assert(adminDB.auth('admin', 'admin'));
+
+ assert.commandWorked(adminDB.runCommand({
createRole: "role2",
roles: [],
privileges: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1/32"]}]
}));
- assert(Object.keys(admin.system.roles.findOne({role: "role2"}))
+ assert(Object.keys(adminDB.system.roles.findOne({role: "role2"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand({createRole: "role3", roles: [], privileges: []}));
+ assert.commandWorked(adminDB.runCommand({createRole: "role3", roles: [], privileges: []}));
print("=== Role creation tests");
print("When a role is updated, it retains authenticationRestrictions");
- assert.commandWorked(admin.runCommand({updateRole: "role2", roles: ["root"]}));
+ assert.commandWorked(adminDB.runCommand({updateRole: "role2", roles: ["root"]}));
const role2Info = assert.commandWorked(
- admin.runCommand({rolesInfo: "role2", showAuthenticationRestrictions: true}));
+ adminDB.runCommand({rolesInfo: "role2", showAuthenticationRestrictions: true}));
printjson(role2Info);
assert.eq(JSON.stringify([[{clientSource: ["127.0.0.1/32"]}]]),
JSON.stringify(role2Info.roles[0].authenticationRestrictions));
print(
"When a client creates roles with empty authenticationRestrictions, the operation succeeds, though it has no effect");
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{createRole: "role4", roles: [], privileges: [], authenticationRestrictions: []}));
- assert(!Object.keys(admin.system.roles.findOne({role: "role4"}))
+ assert(!Object.keys(adminDB.system.roles.findOne({role: "role4"}))
.includes("authenticationRestrictions"));
print(
"When a client updates a role's authenticationRestrictions to be empty, the operation succeeds, and removes the authenticationRestrictions field");
- assert.commandWorked(admin.runCommand({createRole: "role5", roles: [], privileges: []}));
- assert.commandWorked(admin.runCommand({updateRole: "role5", authenticationRestrictions: []}));
- assert(!Object.keys(admin.system.roles.findOne({role: "role5"}))
+ assert.commandWorked(adminDB.runCommand({createRole: "role5", roles: [], privileges: []}));
+ assert.commandWorked(adminDB.runCommand({updateRole: "role5", authenticationRestrictions: []}));
+ assert(!Object.keys(adminDB.system.roles.findOne({role: "role5"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{updateRole: "role5", authenticationRestrictions: [{clientSource: ["127.0.0.1"]}]}));
- assert(Object.keys(admin.system.roles.findOne({role: "role5"}))
+ assert(Object.keys(adminDB.system.roles.findOne({role: "role5"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand({updateRole: "role5", authenticationRestrictions: []}));
- assert(!Object.keys(admin.system.roles.findOne({role: "role5"}))
+ assert.commandWorked(adminDB.runCommand({updateRole: "role5", authenticationRestrictions: []}));
+ assert(!Object.keys(adminDB.system.roles.findOne({role: "role5"}))
.includes("authenticationRestrictions"));
print(
"When a client creates roles, it may use clientSource and serverAddress authenticationRestrictions");
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createRole: "role6",
roles: [],
privileges: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"]}]
}));
- assert(Object.keys(admin.system.roles.findOne({role: "role6"}))
+ assert(Object.keys(adminDB.system.roles.findOne({role: "role6"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createRole: "role7",
roles: [],
privileges: [],
authenticationRestrictions: [{serverAddress: ["127.0.0.1"]}]
}));
- assert(Object.keys(admin.system.roles.findOne({role: "role7"}))
+ assert(Object.keys(adminDB.system.roles.findOne({role: "role7"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createRole: "role8",
roles: [],
privileges: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"], serverAddress: ["127.0.0.1"]}]
}));
- assert(Object.keys(admin.system.roles.findOne({role: "role8"}))
+ assert(Object.keys(adminDB.system.roles.findOne({role: "role8"}))
.includes("authenticationRestrictions"));
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createRole: "role9",
roles: [],
privileges: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"]}, {serverAddress: ["127.0.0.1"]}]
}));
- assert(Object.keys(admin.system.roles.findOne({role: "role9"}))
+ assert(Object.keys(adminDB.system.roles.findOne({role: "role9"}))
.includes("authenticationRestrictions"));
- assert.commandFailed(admin.runCommand({
+ assert.commandFailed(adminDB.runCommand({
createRole: "role10",
roles: [],
privileges: [],
@@ -115,18 +122,21 @@ function testRestrictionCreationAndEnforcement(
print("=== Localhost access tests");
print(
"When a client on the loopback authenticates to a user with {clientSource: \"127.0.0.1\"}, it will succeed");
- assert.commandWorked(admin.runCommand({createUser: "user6", pwd: "user", roles: ["role6"]}));
+ assert.commandWorked(adminDB.runCommand({createUser: "user6", pwd: "user", roles: ["role6"]}));
assert(db.auth("user6", "user"));
+ db.logout();
print(
"When a client on the loopback authenticates to a user with {serverAddress: \"127.0.0.1\"}, it will succeed");
- assert.commandWorked(admin.runCommand({createUser: "user7", pwd: "user", roles: ["role7"]}));
+ assert.commandWorked(adminDB.runCommand({createUser: "user7", pwd: "user", roles: ["role7"]}));
assert(db.auth("user7", "user"));
+ db.logout();
print(
"When a client on the loopback authenticates to a user with {clientSource: \"127.0.0.1\", serverAddress: \"127.0.0.1\"}, it will succeed");
- assert.commandWorked(admin.runCommand({createUser: "user8", pwd: "user", roles: ["role8"]}));
+ assert.commandWorked(adminDB.runCommand({createUser: "user8", pwd: "user", roles: ["role8"]}));
assert(db.auth("user8", "user"));
+ db.logout();
print("=== Remote access tests");
print(
@@ -144,36 +154,45 @@ function testRestrictionCreationAndEnforcement(
print("=== Invalidation tests");
print(
"When a client removes all authenticationRestrictions from a role, authentication will succeed");
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createRole: "role11",
roles: [],
privileges: [],
authenticationRestrictions: [{clientSource: ["127.0.0.1"], serverAddress: ["127.0.0.1"]}]
}));
- assert.commandWorked(admin.runCommand({createUser: "user11", pwd: "user", roles: ["role11"]}));
+ assert.commandWorked(
+ adminDB.runCommand({createUser: "user11", pwd: "user", roles: ["role11"]}));
assert(!externalDb.auth("user11", "user"));
- assert.commandWorked(admin.runCommand({updateRole: "role11", authenticationRestrictions: []}));
+ assert.commandWorked(
+ adminDB.runCommand({updateRole: "role11", authenticationRestrictions: []}));
assert(externalDb.auth("user11", "user"));
+ externalDb.logout();
print(
"When a client sets authenticationRestrictions on a role, authorization privileges are revoked");
- assert.commandWorked(admin.runCommand({
+ assert.commandWorked(adminDB.runCommand({
createRole: "role12",
roles: [],
privileges: [{resource: {db: "test", collection: "foo"}, actions: ["find"]}],
authenticationRestrictions: [{clientSource: ["127.0.0.1"]}]
}));
- assert.commandWorked(admin.runCommand({createUser: "user12", pwd: "user", roles: ["role12"]}));
+ assert.commandWorked(
+ adminDB.runCommand({createUser: "user12", pwd: "user", roles: ["role12"]}));
assert(db.auth("user12", "user"));
assert.commandWorked(db.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
+ db.logout();
+
sleepUntilUserDataPropagated();
+
assert(eventualDb.auth("user12", "user"));
assert.commandWorked(eventualDb.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
- assert.commandWorked(admin.runCommand(
+ assert.commandWorked(adminDB.runCommand(
{updateRole: "role12", authenticationRestrictions: [{clientSource: ["192.168.2.0"]}]}));
assert.commandFailed(db.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
+ eventualDb.logout();
+
sleepUntilUserDataRefreshed();
- assert.commandFailed(eventualDb.getSiblingDB("test").runCommand({find: "foo", batchSize: 0}));
+ assert(!eventualDb.auth("user12", "user"));
}
function testUsersInfoCommand(conn) {
@@ -184,7 +203,7 @@ function testUsersInfoCommand(conn) {
res.users.forEach(assertFun);
}
- var admin = conn.getDB("admin");
+ const admin = conn.getDB("admin");
assert(admin.auth("admin", "admin"));
assert.commandWorked(admin.runCommand({createUser: "user", pwd: "pwd", roles: []}));
@@ -289,6 +308,8 @@ function testUsersInfoCommand(conn) {
assert(userDoc.hasOwnProperty("inheritedAuthenticationRestrictions"));
assert.eq(1, userDoc["inheritedAuthenticationRestrictions"].length);
});
+
+ admin.logout();
}
function testRolesInfoCommand(conn) {
@@ -299,7 +320,7 @@ function testRolesInfoCommand(conn) {
res.roles.forEach(assertFun);
}
- var admin = conn.getDB("admin");
+ const admin = conn.getDB("admin");
assert(admin.auth("admin", "admin"));
assert.commandWorked(admin.runCommand({createRole: "role", roles: [], privileges: []}));
@@ -358,24 +379,26 @@ function testRolesInfoCommand(conn) {
assert(roleDoc.hasOwnProperty("inheritedAuthenticationRestrictions"));
assert.eq(2, roleDoc.inheritedAuthenticationRestrictions.length);
});
+
+ admin.logout();
}
-var keyfile = "jstests/libs/key1";
+const keyfile = "jstests/libs/key1";
print("Testing standalone");
-var conn = MongoRunner.runMongod({bind_ip_all: "", auth: ""});
+const conn = MongoRunner.runMongod({bind_ip_all: "", auth: ""});
testRestrictionCreationAndEnforcement(conn, conn, function() {}, function() {});
testUsersInfoCommand(conn);
testRolesInfoCommand(conn);
MongoRunner.stopMongod(conn);
print("Testing replicaset");
-var rst = new ReplSetTest(
+const rst = new ReplSetTest(
{name: 'testset', nodes: 2, nodeOptions: {bind_ip_all: "", auth: ""}, keyFile: keyfile});
-var nodes = rst.startSet();
+const nodes = rst.startSet();
rst.initiate();
rst.awaitSecondaryNodes();
-var awaitReplication = function() {
+const awaitReplication = function() {
authutil.asCluster(nodes, "jstests/libs/key1", function() {
rst.awaitReplication();
});
@@ -388,7 +411,7 @@ testRolesInfoCommand(rst.getPrimary());
rst.stopSet();
print("Testing sharded cluster");
-var st = new ShardingTest({
+const st = new ShardingTest({
mongos: 2,
config: 3,
shard: 1,
diff --git a/jstests/auth/authz_cache_on_system_modification.js b/jstests/auth/authz_cache_on_system_modification.js
index 02239019a85..23473cd0d01 100644
--- a/jstests/auth/authz_cache_on_system_modification.js
+++ b/jstests/auth/authz_cache_on_system_modification.js
@@ -28,6 +28,7 @@ assert.commandWorked(db.runCommand({
"Could not create custom role");
assert.commandWorked(db.runCommand({createUser: 'custom', pwd: 'pwd', roles: ['writeCustom']}),
"Could not create new user with custom role");
+db.logout();
// tests that a user does not retain their privileges after the system.roles collection is modified
(function testModifySystemRolesCollection() {
@@ -35,14 +36,19 @@ assert.commandWorked(db.runCommand({createUser: 'custom', pwd: 'pwd', roles: ['w
assert(db.auth('custom', 'pwd'));
assert.commandWorked(db.runCommand({insert: "admin.test", documents: [{foo: "bar"}]}),
"Could not insert to test collection with 'custom' user");
+ db.logout();
+
assert(db.auth('root', 'pwd'));
assert.commandWorked(db.runCommand({renameCollection: "admin.system.roles", to: "admin.wolez"}),
"Could not rename system.roles collection with root user");
+ db.logout();
+
assert(db.auth('custom', 'pwd'));
assert.commandFailedWithCode(
db.runCommand({insert: "admin.test", documents: [{woo: "mar"}]}),
authzErrorCode,
"Privileges retained after modification to system.roles collections");
+ db.logout();
})();
// tests that a user does not retain their privileges after the system.users colleciton is modified
@@ -57,7 +63,8 @@ assert.commandWorked(db.runCommand({createUser: 'custom', pwd: 'pwd', roles: ['w
db.runCommand({renameCollection: 'admin.scratch', to: 'admin.system.users'}),
authzErrorCode,
"User cache not invalidated after modification to system collection");
+ db.logout();
})();
MongoRunner.stopMongod(conn);
-})(); \ No newline at end of file
+})();
diff --git a/jstests/auth/basic_role_auth.js b/jstests/auth/basic_role_auth.js
index b86f61dba9d..ac906d3fd98 100644
--- a/jstests/auth/basic_role_auth.js
+++ b/jstests/auth/basic_role_auth.js
@@ -434,6 +434,7 @@ var TESTS = [
test: function(conn) {
var testDB = conn.getDB('test');
assert.eq(1, testDB.auth('rw', AUTH_INFO.test.rw.pwd));
+ testDB.logout();
assert.eq(1, testDB.auth('ro', AUTH_INFO.test.ro.pwd));
testOps(testDB, READ_PERM);
diff --git a/jstests/auth/clac_system_colls.js b/jstests/auth/clac_system_colls.js
index 066b6e6c727..496a93c5344 100644
--- a/jstests/auth/clac_system_colls.js
+++ b/jstests/auth/clac_system_colls.js
@@ -26,6 +26,7 @@ function runTest(admindb) {
admindb.createUser({user: "user", pwd: "pwd", roles: ["FindInDB"]});
// Verify the find on all collections exludes system collections
+ admindb.logout();
assert.eq(1, admindb.auth("user", "pwd"));
assert.doesNotThrow(function() {
@@ -36,6 +37,7 @@ function runTest(admindb) {
}
// Verify that find on system collections gives find permissions
+ admindb.logout();
assert.eq(1, admindb.auth("sysUser", "pwd"));
assert.throws(function() {
diff --git a/jstests/auth/cluster_ip_allowlist.js b/jstests/auth/cluster_ip_allowlist.js
index 76ac47593d9..fbee89bbbb5 100644
--- a/jstests/auth/cluster_ip_allowlist.js
+++ b/jstests/auth/cluster_ip_allowlist.js
@@ -43,15 +43,16 @@ function testIpAllowlistRuntime(description, allowlistString, authResult) {
print("Runtime: " + description);
const conn = MongoRunner.runMongod({keyFile: "jstests/libs/key1"});
+ const admin = conn.getDB('admin');
+ const local = conn.getDB('local');
// Must create a user to verify that we don't fallback to localhost exception for auth.
- assert.commandWorked(
- conn.getDB('admin').runCommand({createUser: 'admin', pwd: 'admin', roles: ['root']}));
+ assert.commandWorked(admin.runCommand({createUser: 'admin', pwd: 'admin', roles: ['root']}));
- assert.eq(true, conn.getDB("local").auth("__system", "foopdedoop"));
+ assert(local.auth("__system", "foopdedoop"));
print("Testing whether __system can login after set to: " + allowlistString);
- assert.commandWorked(conn.adminCommand(
+ assert.commandWorked(admin.runCommand(
{setParameter: 1, "clusterIpSourceAllowlist": allowlistString.split(",")}));
if (!authResult) {
// At this time we have no valid authentication, and existing session should reset.
@@ -60,18 +61,21 @@ function testIpAllowlistRuntime(description, allowlistString, authResult) {
assert.commandFailed(conn.adminCommand({fsync: 1}));
}
- assert.eq(authResult, conn.getDB("local").auth("__system", "foopdedoop"));
+ let authDB = local;
+ assert.eq(authResult, local.auth("__system", "foopdedoop"));
emitWarningAuthErrorIsExpected(authResult);
if (!authResult) {
print("Authenticating with admin user since __system is barred");
- conn.getDB('admin').auth('admin', 'admin');
+ assert(admin.auth('admin', 'admin'));
+ authDB = admin;
}
print("Testing that __system can login after reset to null");
- assert.commandWorked(conn.adminCommand({setParameter: 1, "clusterIpSourceAllowlist": null}));
- conn.getDB("local").logout();
- assert.eq(true, conn.getDB("local").auth("__system", "foopdedoop"));
+ assert.commandWorked(admin.runCommand({setParameter: 1, "clusterIpSourceAllowlist": null}));
+ authDB.logout();
+
+ assert.eq(true, local.auth("__system", "foopdedoop"));
MongoRunner.stopMongod(conn);
}
diff --git a/jstests/auth/commands_user_defined_roles.js b/jstests/auth/commands_user_defined_roles.js
index f214bddc9df..3c9b33cd54a 100644
--- a/jstests/auth/commands_user_defined_roles.js
+++ b/jstests/auth/commands_user_defined_roles.js
@@ -20,33 +20,39 @@ var testRole = "userDefinedRolesTestRole";
load("jstests/auth/lib/commands_lib.js");
load("jstests/libs/fail_point_util.js");
-/**
- * Run the command specified in 't' with the privileges specified in 'privileges'.
- */
-function testProperAuthorization(conn, t, testcase, privileges) {
- var out = "";
+function doTestSetup(conn, t, testcase, privileges) {
+ const admin = conn.getDB('admin');
+ const runOnDb = conn.getDB(testcase.runOnDb);
+ const state = authCommandsLib.setup(conn, t, runOnDb);
- var runOnDb = conn.getDB(testcase.runOnDb);
- var firstDb = conn.getDB(firstDbName);
- var adminDb = conn.getDB(adminDbName);
+ assert(admin.auth('admin', 'password'));
+ assert.commandWorked(admin.runCommand({updateRole: testRole, privileges: privileges}));
+ admin.logout();
- var state = authCommandsLib.setup(conn, t, runOnDb);
-
- adminDb.auth("admin", "password");
- assert.commandWorked(adminDb.runCommand({updateRole: testRole, privileges: privileges}));
- adminDb.logout();
+ return state;
+}
- assert(adminDb.auth(testUser, "password"));
+function doTestTeardown(conn, t, testcase, res) {
+ const runOnDb = conn.getDB(testcase.runOnDb);
+ authCommandsLib.teardown(conn, t, runOnDb, res);
+}
+/**
+ * Run the command specified in 't' with the privileges specified in 'privileges'.
+ */
+function testProperAuthorization(conn, t, testcase, privileges) {
+ const runOnDb = conn.getDB(testcase.runOnDb);
+ const state = doTestSetup(conn.sidechannel, t, testcase, privileges);
authCommandsLib.authenticatedSetup(t, runOnDb);
- var command = t.command;
+ let command = t.command;
if (typeof (command) === "function") {
command = t.command(state, testcase.commandArgs);
}
- var res = runOnDb.runCommand(command);
+ const res = runOnDb.runCommand(command);
- if (!testcase.expectFail && res.ok != 1 && res.code != commandNotSupportedCode) {
+ let out = "";
+ if (!testcase.expectFail && (res.ok != 1) && (res.code != commandNotSupportedCode)) {
// don't error if the test failed with code commandNotSupported since
// some storage engines don't support some commands.
out = "command failed with " + tojson(res) + " on db " + testcase.runOnDb +
@@ -57,47 +63,34 @@ function testProperAuthorization(conn, t, testcase, privileges) {
tojson(privileges);
}
- firstDb.logout();
- authCommandsLib.teardown(conn, t, runOnDb, res);
+ doTestTeardown(conn.sidechannel, t, testcase, res);
return out;
}
function testInsufficientPrivileges(conn, t, testcase, privileges) {
- var out = "";
-
- var runOnDb = conn.getDB(testcase.runOnDb);
- var firstDb = conn.getDB(firstDbName);
- var adminDb = conn.getDB(adminDbName);
-
- var state = authCommandsLib.setup(conn, t, runOnDb);
-
- adminDb.auth("admin", "password");
- assert.commandWorked(adminDb.runCommand({updateRole: testRole, privileges: privileges}));
- adminDb.logout();
-
- assert(adminDb.auth(testUser, "password"));
-
+ const runOnDb = conn.getDB(testcase.runOnDb);
+ const state = doTestSetup(conn.sidechannel, t, testcase, privileges);
authCommandsLib.authenticatedSetup(t, runOnDb);
- var command = t.command;
+ let command = t.command;
if (typeof (command) === "function") {
command = t.command(state, testcase.commandArgs);
}
- var res = runOnDb.runCommand(command);
+ const res = runOnDb.runCommand(command);
- if (res.ok == 1 || res.code != authErrCode) {
+ let out = "";
+ if ((res.ok == 1) || (res.code != authErrCode)) {
out = "expected authorization failure " +
" but received " + tojson(res) + " with privileges " + tojson(privileges);
}
- firstDb.logout();
- authCommandsLib.teardown(conn, t, runOnDb);
+ doTestTeardown(conn.sidechannel, t, testcase, res);
return out;
}
function runOneTest(conn, t) {
- var failures = [];
- var msg;
+ const failures = [];
+ let msg;
// Some tests requires mongot, however, setting this failpoint will make search queries to
// return EOF, that way all the hassle of setting it up can be avoided.
@@ -106,8 +99,8 @@ function runOneTest(conn, t) {
disableSearchFailpoint = configureFailPoint(conn.rs0 ? conn.rs0.getPrimary() : conn,
'searchReturnEofImmediately');
}
- for (var i = 0; i < t.testcases.length; i++) {
- var testcase = t.testcases[i];
+ for (let i = 0; i < t.testcases.length; i++) {
+ const testcase = t.testcases[i];
if (!("privileges" in testcase)) {
continue;
}
@@ -123,9 +116,9 @@ function runOneTest(conn, t) {
if ((testcase.privileges.length == 1 && testcase.privileges[0].actions.length > 1) ||
testcase.privileges.length > 1) {
for (var j = 0; j < testcase.privileges.length; j++) {
- var p = testcase.privileges[j];
- var resource = p.resource;
- var actions = p.actions;
+ const p = testcase.privileges[j];
+ const resource = p.resource;
+ const actions = p.actions;
// A particular privilege can explicitly specify that it should not be removed when
// testing for authorization failure. This accommodates special-case behavior for
@@ -134,8 +127,8 @@ function runOneTest(conn, t) {
continue;
}
- for (var k = 0; k < actions.length; k++) {
- var privDoc = {resource: resource, actions: [actions[k]]};
+ for (let k = 0; k < actions.length; k++) {
+ const privDoc = {resource: resource, actions: [actions[k]]};
msg = testInsufficientPrivileges(conn, t, testcase, [privDoc]);
if (msg) {
failures.push(t.testname + ": " + msg);
@@ -150,9 +143,10 @@ function runOneTest(conn, t) {
failures.push(t.testname + ": " + msg);
}
- var specialResource = function(resource) {
- if (!resource)
+ function specialResource(resource) {
+ if (!resource) {
return true;
+ }
// Tests which use {db: "local", collection: "oplog.rs"} will not work with
// {db: "", collection: "oplog.rs"}. oplog.rs is special, and does not match with
@@ -162,13 +156,13 @@ function runOneTest(conn, t) {
// the same property as oplog.rs.
return !resource.db || !resource.collection ||
resource.collection.startsWith("system.") || resource.db == "local";
- };
+ }
// Test for proper authorization with the test case's privileges where non-system
// collections are modified to be the empty string.
msg = testProperAuthorization(conn, t, testcase, testcase.privileges.map(function(priv) {
// Make a copy of the privilege so as not to modify the original array.
- var modifiedPrivilege = Object.extend({}, priv, true);
+ const modifiedPrivilege = Object.extend({}, priv, true);
if (modifiedPrivilege.resource.collection && !specialResource(priv.resource)) {
modifiedPrivilege.resource.collection = "";
}
@@ -182,7 +176,7 @@ function runOneTest(conn, t) {
// empty string.
msg = testProperAuthorization(conn, t, testcase, testcase.privileges.map(function(priv) {
// Make a copy of the privilege so as not to modify the original array.
- var modifiedPrivilege = Object.extend({}, priv, true);
+ const modifiedPrivilege = Object.extend({}, priv, true);
if (!specialResource(priv.resource)) {
modifiedPrivilege.resource.db = "";
}
@@ -201,8 +195,7 @@ function runOneTest(conn, t) {
}
function createUsers(conn) {
- var adminDb = conn.getDB(adminDbName);
- var firstDb = conn.getDB(firstDbName);
+ const adminDb = conn.getDB(adminDbName);
adminDb.createUser({user: "admin", pwd: "password", roles: ["__system"]});
assert(adminDb.auth("admin", "password"));
@@ -212,18 +205,41 @@ function createUsers(conn) {
{createUser: testUser, pwd: "password", roles: [{role: testRole, db: adminDbName}]}));
adminDb.logout();
+
+ // Primary connection will now act as test user only.
+ assert(adminDb.auth(testUser, "password"));
}
-var opts = {auth: "", enableExperimentalStorageDetailsCmd: ""};
-var impls = {createUsers: createUsers, runOneTest: runOneTest};
+const opts = {
+ auth: "",
+ enableExperimentalStorageDetailsCmd: ""
+};
+const impls = {
+ createUsers: createUsers,
+ runOneTest: runOneTest
+};
// run all tests standalone
-var conn = MongoRunner.runMongod(opts);
-authCommandsLib.runTests(conn, impls);
-MongoRunner.stopMongod(conn);
+{
+ const conn = MongoRunner.runMongod(opts);
+
+ // Create secondary connection to be intermittently authed
+ // with admin privileges for setup/teardown.
+ conn.sidechannel = new Mongo(conn.host);
+ authCommandsLib.runTests(conn, impls);
+ MongoRunner.stopMongod(conn);
+}
// run all tests sharded
-conn = new ShardingTest(
- {shards: 1, mongos: 1, config: 1, keyFile: "jstests/libs/key1", other: {shardOptions: opts}});
-authCommandsLib.runTests(conn, impls);
-conn.stop();
+{
+ const conn = new ShardingTest({
+ shards: 1,
+ mongos: 1,
+ config: 1,
+ keyFile: "jstests/libs/key1",
+ other: {shardOptions: opts}
+ });
+ conn.sidechannel = new Mongo(conn.s0.host);
+ authCommandsLib.runTests(conn, impls);
+ conn.stop();
+}
diff --git a/jstests/auth/db_multiple_login.js b/jstests/auth/db_multiple_login.js
index b4d46aeb9e9..7f399419bcb 100644
--- a/jstests/auth/db_multiple_login.js
+++ b/jstests/auth/db_multiple_login.js
@@ -1,31 +1,25 @@
-// Test the behavior when two users from the same database are authenticated serially on a single
-// connection. Expected behavior is that the first user is implicitly logged out by the second
-// authentication.
-//
-// Regression test for SERVER-8144.
-var conn = MongoRunner.runMongod({auth: ""});
-var admin = conn.getDB("admin");
-var test = conn.getDB("test");
+// Test that only one user may be authenticated against the database at a time.
-admin.createUser({user: 'admin', pwd: 'a', roles: jsTest.adminUserRoles});
-assert(admin.auth('admin', 'a'));
-test.createUser({user: 'reader', pwd: 'a', roles: ["read"]});
-test.createUser({user: 'writer', pwd: 'a', roles: ["readWrite"]});
-admin.logout();
+(function() {
+'use strict';
+
+const conn = MongoRunner.runMongod({auth: ''});
+const admin = conn.getDB('admin');
+const test = conn.getDB('test');
-// Nothing logged in, can neither read nor write.
-assert.writeError(test.docs.insert({value: 0}));
-assert.throws(function() {
- test.foo.findOne();
-});
+admin.createUser({user: 'admin', pwd: 'pwd', roles: jsTest.adminUserRoles});
+assert(admin.auth('admin', 'pwd'));
+test.createUser({user: 'user', pwd: 'pwd', roles: ['readWrite']});
-// Writer logged in, can read and write.
-test.auth('writer', 'a');
-assert.commandWorked(test.docs.insert({value: 1}));
-test.foo.findOne();
+jsTest.log('Testing multi-auth');
+assert(!test.auth('user', 'pwd'));
+
+jsTest.log('Testing re-auth after logout');
+admin.logout();
+assert(test.auth('user', 'pwd'));
+test.logout();
-// Reader logged in, replacing writer, can only read.
-test.auth('reader', 'a');
-assert.writeError(test.docs.insert({value: 2}));
-test.foo.findOne();
-MongoRunner.stopMongod(conn, null, {user: 'admin', pwd: 'a'});
+jsTest.log('Shutting down');
+assert(admin.auth('admin', 'pwd'));
+MongoRunner.stopMongod(conn);
+})();
diff --git a/jstests/auth/getMore.js b/jstests/auth/getMore.js
index 83e427accd6..d7588d73dc6 100644
--- a/jstests/auth/getMore.js
+++ b/jstests/auth/getMore.js
@@ -7,8 +7,8 @@
TestData.disableImplicitSessions = true;
function runTest(conn) {
- let adminDB = conn.getDB("admin");
- let hello = adminDB.runCommand("hello");
+ const adminDB = conn.getDB("admin");
+ const hello = adminDB.runCommand("hello");
assert.commandWorked(hello);
const isMongos = (hello.msg === "isdbgrid");
@@ -252,70 +252,15 @@ function runTest(conn) {
adminDB.runCommand({createUser: "fooBarUser", pwd: "pwd", roles: ["readFooBar"]}));
adminDB.logout();
-
- // Test that a cursor created by "fooUser" and "fooBarUser" can be used by "fooUser".
- assert.eq(1, testDB.auth("fooUser", "pwd"));
- assert.eq(1, adminDB.auth("fooBarUser", "pwd"));
- res = assert.commandWorked(testDB.runCommand({find: "foo", batchSize: 0}));
- cursorId = res.cursor.id;
- assert.neq(0, cursorId);
- adminDB.logout();
- assert.commandWorked(testDB.runCommand({getMore: cursorId, collection: "foo"}));
- testDB.logout();
-
- // Test that a cursor created by "fooUser" and "fooBarUser" cannot be used by "fooUser" if
- // "fooUser" does not have the privilege to read the collection.
- assert.eq(1, testDB.auth("fooUser", "pwd"));
- assert.eq(1, adminDB.auth("fooBarUser", "pwd"));
- res = assert.commandWorked(testDB.runCommand({find: "bar", batchSize: 0}));
- cursorId = res.cursor.id;
- assert.neq(0, cursorId);
- adminDB.logout();
- assert.commandFailedWithCode(testDB.runCommand({getMore: cursorId, collection: "bar"}),
- ErrorCodes.Unauthorized,
- "read from a cursor without required privileges");
- testDB.logout();
-
- // Test that an aggregate cursor created by "fooUser" and "fooBarUser" cannot be used by
- // "fooUser" if "fooUser" does not have all privileges required by the pipeline.
- assert.eq(1, testDB.auth("fooUser", "pwd"));
- assert.eq(1, adminDB.auth("fooBarUser", "pwd"));
- res = assert.commandWorked(testDB.runCommand({
- aggregate: "foo",
- pipeline: [
- {$match: {_id: 0}},
- {$lookup: {from: "bar", localField: "_id", foreignField: "_id", as: "bar"}}
- ],
- cursor: {batchSize: 0}
- }));
- cursorId = res.cursor.id;
- assert.neq(0, cursorId);
- assert.commandWorked(testDB.runCommand({getMore: cursorId, collection: "foo"}));
-
- res = assert.commandWorked(testDB.runCommand({
- aggregate: "foo",
- pipeline: [
- {$match: {_id: 0}},
- {$lookup: {from: "bar", localField: "_id", foreignField: "_id", as: "bar"}}
- ],
- cursor: {batchSize: 0}
- }));
- cursorId = res.cursor.id;
- assert.neq(0, cursorId);
- adminDB.logout();
- assert.commandFailedWithCode(testDB.runCommand({getMore: cursorId, collection: "foo"}),
- ErrorCodes.Unauthorized,
- "read from a cursor without required privileges");
- testDB.logout();
}
// Run the test on a standalone.
-let conn = MongoRunner.runMongod({auth: "", bind_ip: "127.0.0.1"});
+const conn = MongoRunner.runMongod({auth: "", bind_ip: "127.0.0.1"});
runTest(conn);
MongoRunner.stopMongod(conn);
// Run the test on a sharded cluster.
-let cluster = new ShardingTest(
+const cluster = new ShardingTest(
{shards: 1, mongos: 1, keyFile: "jstests/libs/key1", other: {shardOptions: {auth: ""}}});
runTest(cluster);
cluster.stop();
diff --git a/jstests/auth/kill_cursors.js b/jstests/auth/kill_cursors.js
index ee791320520..e4fdc181b69 100644
--- a/jstests/auth/kill_cursors.js
+++ b/jstests/auth/kill_cursors.js
@@ -13,51 +13,34 @@ function runTest(mongod) {
*
* @param db - The db to create a cursor on and ultimately kill agains.
* @param authUsers - Array of ['username', db] pairs to create the cursor under.
- * @param killUsers - Array of ['username', dn] pairs to use when killing.
+ * @param killUsers - Array of ['username', db] pairs to use when killing.
* @param shouldWork - Whether we expect success
*/
- function tryKill(db, authUsers, killUsers, shouldWork) {
- function loginAll(users) {
- users.forEach(function(u) {
- assert(u[1].auth(u[0], 'pass'));
- });
- }
-
- function logoutAll() {
- [testA, testB].forEach(function(d) {
- const users = assert.commandWorked(d.runCommand({connectionStatus: 1}))
- .authInfo.authenticatedUsers;
- users.forEach(function(u) {
- mongod.getDB(u.db).logout();
- });
- });
- }
-
+ function tryKill(db, authUser, killUsers, shouldWork) {
function doKill(extra) {
// Create a cursor to be killed later.
- loginAll(authUsers);
- let cmd = {find: db.coll.getName(), batchSize: 2};
- Object.assign(cmd, extra);
+ assert(authUser[1].auth(authUser[0], 'pass'));
+ const cmd = Object.assign({find: db.coll.getName(), batchSize: 2}, extra);
const id = assert.commandWorked(db.runCommand(cmd)).cursor.id;
assert.neq(id, 0, "Invalid cursor ID");
- logoutAll();
-
- loginAll(killUsers);
- const killCmd = db.runCommand({killCursors: db.coll.getName(), cursors: [id]});
- logoutAll();
- if (shouldWork) {
- assert.commandWorked(killCmd, "Unable to kill cursor");
- } else {
- assert.commandFailed(killCmd, "Should not have been able to kill cursor");
- }
+ authUser[1].logout();
+
+ killUsers.forEach(function(killUser) {
+ assert(killUser[1].auth(killUser[0], 'pass'));
+ const cmd = db.runCommand({killCursors: db.coll.getName(), cursors: [id]});
+ killUser[1].logout();
+
+ if (shouldWork) {
+ assert.commandWorked(cmd, "Unable to kill cursor");
+ } else {
+ assert.commandFailed(cmd, "Should not have been able to kill cursor");
+ }
+ });
}
+ // Run though create/kill with and without a session ID.
doKill({});
-
- if ((authUsers.length === 1) && (killUsers.length === 1)) {
- // Session variant only makes sense with single auth'd users.
- doKill({lsid: {id: BinData(4, "QlLfPHTySm6tqfuV+EOsVA==")}});
- }
+ doKill({lsid: {id: BinData(4, "QlLfPHTySm6tqfuV+EOsVA==")}});
}
function trySelfKill(user) {
@@ -105,57 +88,39 @@ function runTest(mongod) {
// Create a collection with batchable data
assert(testA.auth('user1', 'pass'));
- assert(testB.auth('user3', 'pass'));
- for (var i = 0; i < 101; ++i) {
+ for (let i = 0; i < 101; ++i) {
assert.commandWorked(testA.coll.insert({_id: i}));
- assert.commandWorked(testB.coll.insert({_id: i}));
}
testA.logout();
+
+ assert(testB.auth('user3', 'pass'));
+ for (let i = 0; i < 101; ++i) {
+ assert.commandWorked(testB.coll.insert({_id: i}));
+ }
testB.logout();
// A user can kill their own cursor.
- tryKill(testA, [['user1', testA]], [['user1', testA]], true);
- tryKill(testA, [['user2', testA]], [['user2', testA]], true);
- tryKill(testB, [['user3', testB]], [['user3', testB]], true);
- tryKill(testB, [['user4', testB]], [['user4', testB]], true);
+ tryKill(testA, ['user1', testA], [['user1', testA]], true);
+ tryKill(testA, ['user2', testA], [['user2', testA]], true);
+ tryKill(testB, ['user3', testB], [['user3', testB]], true);
+ tryKill(testB, ['user4', testB], [['user4', testB]], true);
trySelfKill(['user1', testA]);
trySelfKill(['user5', testB]);
trySelfKill(['admin', admin]);
// A user cannot kill someone else's cursor.
- tryKill(testA, [['user1', testA]], [['user2', testA]], false);
- tryKill(testA, [['user1', testA]], [['user2', testA], ['user3', testB]], false);
- tryKill(testA, [['user2', testA]], [['user1', testA]], false);
- tryKill(testA, [['user2', testA]], [['user1', testA], ['user3', testB]], false);
- tryKill(testB, [['user3', testB]], [['user1', testA], ['user4', testB]], false);
- tryKill(testB, [['user3', testB]], [['user2', testA], ['user4', testB]], false);
-
- // A multi-owned cursor can be killed by any/all owner.
- tryKill(testA, [['user1', testA], ['user3', testB]], [['user1', testA]], true);
- tryKill(testB, [['user1', testA], ['user3', testB]], [['user3', testB]], true);
- tryKill(
- testA, [['user1', testA], ['user3', testB]], [['user1', testA], ['user3', testB]], true);
- tryKill(
- testA, [['user1', testA], ['user3', testB]], [['user2', testA], ['user3', testB]], true);
- tryKill(
- testB, [['user1', testA], ['user3', testB]], [['user1', testA], ['user3', testB]], true);
- tryKill(
- testB, [['user1', testA], ['user3', testB]], [['user1', testA], ['user4', testB]], true);
-
- // An owned cursor can not be killed by other user(s).
- tryKill(
- testA, [['user1', testA], ['user3', testB]], [['user2', testA], ['user4', testB]], false);
- tryKill(testA, [['user1', testA]], [['user2', testA], ['user3', testB]], false);
- tryKill(
- testA, [['user1', testA], ['user3', testB]], [['user2', testA], ['user4', testB]], false);
+ tryKill(testA, ['user1', testA], [['user2', testA]], false);
+ tryKill(testA, ['user1', testA], [['user2', testA], ['user3', testB]], false);
+ tryKill(testA, ['user2', testA], [['user1', testA]], false);
+ tryKill(testA, ['user2', testA], [['user1', testA], ['user3', testB]], false);
+ tryKill(testB, ['user3', testB], [['user1', testA], ['user4', testB]], false);
+ tryKill(testB, ['user3', testB], [['user2', testA], ['user4', testB]], false);
// Admin can kill anything.
- tryKill(testA, [['user1', testA]], [['admin', admin]], true);
- tryKill(testA, [['user2', testA]], [['admin', admin]], true);
- tryKill(testB, [['user3', testB]], [['admin', admin]], true);
- tryKill(testB, [['user4', testB]], [['admin', admin]], true);
- tryKill(testA, [['user1', testA], ['user3', testB]], [['admin', admin]], true);
- tryKill(testB, [['user2', testA], ['user4', testB]], [['admin', admin]], true);
+ tryKill(testA, ['user1', testA], [['admin', admin]], true);
+ tryKill(testA, ['user2', testA], [['admin', admin]], true);
+ tryKill(testB, ['user3', testB], [['admin', admin]], true);
+ tryKill(testB, ['user4', testB], [['admin', admin]], true);
}
const mongod = MongoRunner.runMongod({auth: ""});
diff --git a/jstests/auth/list_all_sessions.js b/jstests/auth/list_all_sessions.js
index 52b48825577..02d90c3d04e 100644
--- a/jstests/auth/list_all_sessions.js
+++ b/jstests/auth/list_all_sessions.js
@@ -38,6 +38,7 @@ function runListAllSessionsTest(mongod) {
assertErrorCode(config.system.sessions, viewAdminPipeline, ErrorCodes.Unauthorized);
// Ensure that the cache now contains the session and is visible by admin
+ admin.logout();
assert(admin.auth('admin', 'pass'));
const resultArray =
config.system.sessions
diff --git a/jstests/auth/list_local_sessions_base.js b/jstests/auth/list_local_sessions_base.js
index 1901bd50914..64d4a1b9b94 100644
--- a/jstests/auth/list_local_sessions_base.js
+++ b/jstests/auth/list_local_sessions_base.js
@@ -47,6 +47,7 @@ function runListLocalSessionsTest(mongod) {
assert.eq(bsonWoCompare(resultArray, resultArrayMine), 0);
// Ensure that changing users hides the session.
+ db.logout();
assert(db.auth('user2', 'pass'));
const otherArray = assert.doesNotThrow(listLocalSessions).toArray();
assert.eq(otherArray.length, 0);
diff --git a/jstests/auth/list_sessions.js b/jstests/auth/list_sessions.js
index 291c1e1d050..13a546d7329 100644
--- a/jstests/auth/list_sessions.js
+++ b/jstests/auth/list_sessions.js
@@ -56,6 +56,7 @@ function runListSessionsTest(mongod) {
assertErrorCode(admin.system.collections, pipeline, ErrorCodes.InvalidNamespace);
// Ensure that changing users hides the session everwhere.
+ admin.logout();
assert(admin.auth('user2', 'pass'));
assert.eq(listSessions().toArray().length, 0);
diff --git a/jstests/auth/profile.js b/jstests/auth/profile.js
index 3c88b37ad29..d6e388dff4a 100644
--- a/jstests/auth/profile.js
+++ b/jstests/auth/profile.js
@@ -1,11 +1,13 @@
// Check that username information gets recorded properly in profiler.
// @tags: [requires_profiling]
-var conn = MongoRunner.runMongod();
-var db1 = conn.getDB("profile-a");
-var db2 = db1.getSiblingDB("profile-b");
-var username = "user";
-db1.createUser({user: username, pwd: "password", roles: jsTest.basicUserRoles});
-db2.createUser({user: username, pwd: "password", roles: jsTest.basicUserRoles});
+
+(function() {
+'use strict';
+
+const conn = MongoRunner.runMongod();
+const db = conn.getDB("profile");
+const username = "user";
+db.createUser({user: username, pwd: "password", roles: jsTest.basicUserRoles});
function lastOp(db) {
return db.system.profile.find().sort({$natural: -1}).next();
@@ -15,39 +17,27 @@ function principalName(user, db) {
return user + "@" + db.getName();
}
-db1.setProfilingLevel(0);
-db1.system.profile.drop();
-assert.eq(0, db1.system.profile.count());
-
-db1.setProfilingLevel(2);
-
-db1.foo.findOne();
-var last = lastOp(db1);
-assert.eq("", last.user);
-assert.eq(0, last.allUsers.length);
-
-db1.auth(username, "password");
-
-db1.foo.findOne();
-var last = lastOp(db1);
-assert.eq(principalName(username, db1), last.user);
-assert.eq(1, last.allUsers.length);
-assert.eq(username, last.allUsers[0].user);
-assert.eq(db1, last.allUsers[0].db);
-
-db2.auth(username, "password");
-
-db1.foo.findOne();
-var last = lastOp(db1);
-// Which user gets put in "user" and the ordering of users in "allUsers" is undefined.
-assert((principalName(username, db1) == last.user) || (principalName(username, db2) == last.user));
-assert.eq(2, last.allUsers.length);
-assert.eq(username, last.allUsers[0].user);
-assert.eq(username, last.allUsers[1].user);
-assert((db1 == last.allUsers[0].db && db2 == last.allUsers[1].db) ||
- (db2 == last.allUsers[0].db && db1 == last.allUsers[1].db));
-
-db1.setProfilingLevel(0);
-db1.dropDatabase();
-db2.dropDatabase();
+db.setProfilingLevel(0);
+db.system.profile.drop();
+assert.eq(0, db.system.profile.count());
+
+db.setProfilingLevel(2);
+
+db.foo.findOne();
+const last1 = lastOp(db);
+assert.eq("", last1.user);
+assert.eq(0, last1.allUsers.length);
+
+assert(db.auth(username, "password"));
+db.foo.findOne();
+const last2 = lastOp(db);
+assert.eq(principalName(username, db), last2.user);
+assert.eq(1, last2.allUsers.length);
+assert.eq(username, last2.allUsers[0].user);
+assert.eq(db, last2.allUsers[0].db);
+db.logout();
+
+db.setProfilingLevel(0);
+db.dropDatabase();
MongoRunner.stopMongod(conn);
+})();
diff --git a/jstests/auth/pseudo_commands.js b/jstests/auth/pseudo_commands.js
index 1802336c2e3..4615f6dba08 100644
--- a/jstests/auth/pseudo_commands.js
+++ b/jstests/auth/pseudo_commands.js
@@ -5,21 +5,24 @@
* @tags: [requires_sharding]
*/
+(function() {
+'use strict';
+
function runTest(conn) {
- var authzErrorCode = 13;
+ const authzErrorCode = 13;
conn.getDB('admin').createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
- var adminConn = new Mongo(conn.host);
- adminConn.getDB('admin').auth('admin', 'pwd');
- var admin = adminConn.getDB('admin');
+ const adminConn = new Mongo(conn.host);
+ const admin = adminConn.getDB('admin');
+
+ assert(admin.auth('admin', 'pwd'));
admin.createRole({role: 'myRole', roles: [], privileges: []});
admin.createUser({user: 'spencer', pwd: 'pwd', roles: ['myRole']});
+ const arbitraryShard = admin.getSiblingDB("config").shards.findOne();
- var db = conn.getDB('admin');
- db.auth('admin', 'pwd');
- var arbitraryShard = db.getSiblingDB("config").shards.findOne();
- db.auth('spencer', 'pwd');
+ const db = conn.getDB('admin');
+ assert(db.auth('spencer', 'pwd'));
/**
* Tests that a single operation has the proper authorization. The operation is run by invoking
@@ -30,7 +33,7 @@ function runTest(conn) {
*/
function testProperAuthorization(testFunc, roles, privilege) {
// Test built-in roles first
- for (role in roles) {
+ for (let role in roles) {
admin.updateRole("myRole", {roles: [role]});
testFunc(roles[role]);
}
@@ -197,3 +200,4 @@ jsTest.log('Test sharding');
var st = new ShardingTest({shards: 2, config: 3, keyFile: 'jstests/libs/key1'});
runTest(st.s);
st.stop();
+})();
diff --git a/jstests/auth/rename.js b/jstests/auth/rename.js
index 4bc25d1053d..0db405d32db 100644
--- a/jstests/auth/rename.js
+++ b/jstests/auth/rename.js
@@ -3,18 +3,21 @@
// Multiple users cannot be authenticated on one connection within a session.
TestData.disableImplicitSessions = true;
-var m = MongoRunner.runMongod({auth: ""});
+(function() {
+'use strict';
-var db1 = m.getDB("foo");
-var db2 = m.getDB("bar");
-var admin = m.getDB('admin');
+const m = MongoRunner.runMongod({auth: ""});
+
+const db1 = m.getDB("foo");
+const db2 = m.getDB("bar");
+const admin = m.getDB('admin');
// Setup initial data
admin.createUser({user: 'admin', pwd: 'password', roles: jsTest.adminUserRoles});
admin.auth('admin', 'password');
db1.createUser({user: "foo", pwd: "bar", roles: jsTest.basicUserRoles});
-db2.createUser({user: "bar", pwd: "foo", roles: jsTest.basicUserRoles});
+db2.createUser({user: "bar", pwd: "foo", roles: [{role: 'readWriteAnyDatabase', db: 'admin'}]});
printjson(db1.a.count());
db1.a.save({});
@@ -27,16 +30,17 @@ assert.commandFailed(
admin.runCommand({renameCollection: db1.a.getFullName(), to: db1.b.getFullName()}));
// can run same db with auth
-db1.auth('foo', 'bar');
+assert(db1.auth('foo', 'bar'));
assert.commandWorked(
admin.runCommand({renameCollection: db1.a.getFullName(), to: db1.b.getFullName()}));
// can't run diff db w/o auth
assert.commandFailed(
admin.runCommand({renameCollection: db1.b.getFullName(), to: db2.a.getFullName()}));
+db1.logout();
// can run diff db with auth
-db2.auth('bar', 'foo');
+assert(db2.auth('bar', 'foo'));
assert.commandWorked(
admin.runCommand({renameCollection: db1.b.getFullName(), to: db2.a.getFullName()}));
@@ -44,5 +48,8 @@ assert.commandWorked(
assert.eq(db1.a.count(), 0);
assert.eq(db1.b.count(), 0);
assert.eq(db2.a.count(), 1);
+db2.logout();
-MongoRunner.stopMongod(m, null, {user: 'admin', pwd: 'password'});
+assert(admin.auth('admin', 'password'));
+MongoRunner.stopMongod(m);
+})();
diff --git a/jstests/auth/renameRestrictedCollections.js b/jstests/auth/renameRestrictedCollections.js
index 6120d5c964a..4d487d38d08 100644
--- a/jstests/auth/renameRestrictedCollections.js
+++ b/jstests/auth/renameRestrictedCollections.js
@@ -19,7 +19,7 @@ const backdoorUserDoc = {
adminDB.createUser({user: 'userAdmin', pwd: 'password', roles: ['userAdminAnyDatabase']});
-adminDB.auth('userAdmin', 'password');
+assert(adminDB.auth('userAdmin', 'password'));
adminDB.createUser({user: 'readWriteAdmin', pwd: 'password', roles: ['readWriteAnyDatabase']});
adminDB.createUser({
user: 'readWriteAndUserAdmin',
@@ -31,8 +31,8 @@ adminDB.createUser({user: 'rootier', pwd: 'password', roles: ['__system']});
adminDB.logout();
jsTestLog("Test that a readWrite user can't rename system.profile to something they can read");
-adminDB.auth('readWriteAdmin', 'password');
-var res = adminDB.system.profile.renameCollection("profile");
+assert(adminDB.auth('readWriteAdmin', 'password'));
+let res = adminDB.system.profile.renameCollection("profile");
assert.eq(0, res.ok);
assert.eq(CodeUnauthorized, res.code);
@@ -51,13 +51,15 @@ adminDB.users.drop();
jsTestLog("Test that a userAdmin can't rename system.users without readWrite");
adminDB.logout();
-adminDB.auth('userAdmin', 'password');
+
+assert(adminDB.auth('userAdmin', 'password'));
res = adminDB.system.users.renameCollection("users");
assert.eq(0, res.ok);
assert.eq(CodeUnauthorized, res.code);
assert.eq(5, adminDB.system.users.count());
+adminDB.logout();
-adminDB.auth('readWriteAndUserAdmin', 'password');
+assert(adminDB.auth('readWriteAndUserAdmin', 'password'));
assert.eq(0, adminDB.users.count());
jsTestLog("Test that even with userAdmin AND dbAdmin you CANNOT rename to/from system.users");
@@ -74,8 +76,9 @@ assert.eq(CodeUnauthorized, res.code);
assert.eq(null, adminDB.system.users.findOne({user: backdoorUserDoc.user}));
assert.neq(null, adminDB.system.users.findOne({user: 'userAdmin'}));
+adminDB.logout();
-adminDB.auth('rootier', 'password');
+assert(adminDB.auth('rootier', 'password'));
// Test permissions against the configDB and localDB
@@ -102,13 +105,15 @@ assert.writeError(res, 13, "not authorized on config to execute command");
res = localDB.test2.renameCollection('test');
assert.eq(0, res.ok);
assert.eq(CodeUnauthorized, res.code);
+adminDB.logout();
// Test renaming system.users collection with __system
assert(adminDB.auth('rootier', 'password'));
jsTestLog("Test that with __system you CAN rename to/from system.users");
res = adminDB.system.users.renameCollection("users", true);
assert.eq(1, res.ok, tojson(res));
+
// At this point, all the user documents are gone, so further activity may be unauthorized,
// depending on cluster configuration. So, this is the end of the test.
MongoRunner.stopMongod(conn, {user: 'userAdmin', pwd: 'password'});
-})(); \ No newline at end of file
+})();
diff --git a/jstests/auth/resource_pattern_matching.js b/jstests/auth/resource_pattern_matching.js
index b02fe7951e6..61aed0e8271 100644
--- a/jstests/auth/resource_pattern_matching.js
+++ b/jstests/auth/resource_pattern_matching.js
@@ -8,26 +8,33 @@
// authenticating as the __system user.
TestData.disableImplicitSessions = true;
+(function() {
+'use strict';
+
function setup_users(granter) {
- var admindb = granter.getSiblingDB("admin");
- admindb.runCommand({
+ const admin = granter.getSiblingDB("admin");
+ assert.commandWorked(admin.runCommand({
createUser: "admin",
pwd: "admin",
roles:
- ["userAdminAnyDatabase", "dbAdminAnyDatabase", "clusterAdmin", "readWriteAnyDatabase"]
- });
-
- admindb.auth("admin", "admin");
-
- printjson(admindb.runCommand({createRole: "test_role", privileges: [], roles: []}));
-
- printjson(admindb.runCommand({createUser: "test_user", pwd: "password", roles: ["test_role"]}));
+ ["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) {
- var test_db_a = db.getSiblingDB("a");
- var test_db_b = db.getSiblingDB("b");
+ 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'}));
@@ -36,45 +43,40 @@ function setup_dbs_and_cols(db) {
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) {
- var admindb = granter.getSiblingDB("admin");
+ const admin = granter.getSiblingDB("admin");
- admindb.auth("admin", "admin");
-
- var result = admindb.runCommand({
+ assert(admin.auth("admin", "admin"));
+ const result = admin.runCommand({
grantPrivilegesToRole: "test_role",
privileges: privileges,
writeConcern: {w: 'majority'}
});
-
- admindb.logout();
-
+ admin.logout();
return result;
}
function revoke_privileges(granter, privileges) {
- var admindb = granter.getSiblingDB("admin");
+ const admin = granter.getSiblingDB("admin");
- admindb.auth("admin", "admin");
-
- var result = admindb.runCommand({
+ assert(admin.auth("admin", "admin"));
+ const result = admin.runCommand({
revokePrivilegesFromRole: "test_role",
privileges: privileges,
writeConcern: {w: 'majority'}
});
-
- admindb.logout();
-
+ admin.logout();
return result;
}
function invalidateUserCache(verifier) {
- var admindb = verifier.getSiblingDB("admin");
- admindb.auth('admin', 'admin');
- admindb.runCommand("invalidateUserCache");
- admindb.logout();
+ 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) {
@@ -84,25 +86,24 @@ function run_test(name, granter, verifier, privileges, collections) {
invalidateUserCache(verifier);
const verifierDB = verifier.getSiblingDB('admin');
- verifierDB.auth("test_user", "password");
+ assert(verifierDB.auth("test_user", "password"));
for (var key in collections) {
- var parts = key.split(".");
- var testdb = verifier.getSiblingDB(parts[0]);
- var col = testdb.getCollection(parts[1]);
+ const parts = key.split(".");
+ const testdb = verifier.getSiblingDB(parts[0]);
+ const col = testdb.getCollection(parts[1]);
- var cb = collections[key];
+ const cb = collections[key];
cb(testdb, col);
}
+ verifierDB.logout();
revoke_privileges(granter, privileges);
- verifierDB.logout();
}
function run_test_bad_resource(name, granter, resource) {
print("\n=== testing resource fail " + name + "() ===\n");
- var admindb = granter.getSiblingDB("admin");
assert.commandFailed(grant_privileges(granter, [{resource: resource, actions: ["find"]}]));
}
@@ -221,35 +222,45 @@ function run_tests(granter, verifier) {
});
}
-var keyfile = "jstests/libs/key1";
-
-print('--- standalone node test ---');
-var 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 ---');
-var rst =
- new ReplSetTest({name: 'testset', nodes: 2, nodeOptions: {'auth': null}, keyFile: keyfile});
-
-rst.startSet();
-rst.initiate();
-var primary = rst.getPrimary().getDB('admin');
-rst.awaitSecondaryNodes();
-var secondary = rst.getSecondaries()[0].getDB('admin');
-run_tests(primary, secondary);
-rst.stopSet();
-print('--- done with the rs tests ---');
-
-print('--- sharding test ---');
-var 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 ---');
+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 ---');
+}
+})();
diff --git a/jstests/auth/user_management_commands_lib.js b/jstests/auth/user_management_commands_lib.js
index 128cdb300f8..859be7496d0 100644
--- a/jstests/auth/user_management_commands_lib.js
+++ b/jstests/auth/user_management_commands_lib.js
@@ -5,39 +5,42 @@
function runAllUserManagementCommandsTests(conn, writeConcern) {
'use strict';
- var hasAuthzError = function(result) {
+ function hasAuthzError(result) {
assert(result instanceof WriteCommandError);
assert.eq(ErrorCodes.Unauthorized, result.code);
- };
+ }
- conn.getDB('admin').createUser({user: 'admin', pwd: 'pwd', roles: ['root']}, writeConcern);
- conn.getDB('admin').auth('admin', 'pwd');
- conn.getDB('admin').createUser({
+ const admin = conn.getDB('admin');
+
+ admin.createUser({user: 'admin', pwd: 'pwd', roles: ['root']}, writeConcern);
+ assert(admin.auth('admin', 'pwd'));
+ admin.createUser({
user: 'userAdmin',
pwd: 'pwd',
roles: ['userAdminAnyDatabase'],
customData: {userAdmin: true}
},
- writeConcern);
- conn.getDB('admin').logout();
+ writeConcern);
+ admin.logout();
- var userAdminConn = new Mongo(conn.host);
- userAdminConn.getDB('admin').auth('userAdmin', 'pwd');
- var testUserAdmin = userAdminConn.getDB('test');
+ const userAdminConn = new Mongo(conn.host);
+ const userAdmin = userAdminConn.getDB('admin');
+ assert(userAdmin.auth('userAdmin', 'pwd'));
+ const testUserAdmin = userAdminConn.getDB('test');
testUserAdmin.createRole({
role: 'testRole',
roles: [],
privileges: [{resource: {db: 'test', collection: ''}, actions: ['viewRole']}],
},
writeConcern);
- userAdminConn.getDB('admin').createRole({
+ userAdmin.createRole({
role: 'adminRole',
roles: [],
privileges: [{resource: {cluster: true}, actions: ['connPoolSync']}]
},
- writeConcern);
+ writeConcern);
- var db = conn.getDB('test');
+ const db = conn.getDB('test');
// At this point there are 2 handles to the "test" database in use - "testUserAdmin" and "db".
// "testUserAdmin" is on a connection which has been auth'd as a user with the
@@ -58,7 +61,7 @@ function runAllUserManagementCommandsTests(conn, writeConcern) {
writeConcern);
testUserAdmin.createUser({user: "andy", pwd: "pwd", roles: []}, writeConcern);
- var user = testUserAdmin.getUser('spencer');
+ const user = testUserAdmin.getUser('spencer');
assert.eq(10028, user.customData.zipCode);
assert(db.auth('spencer', 'pwd'));
assert.commandWorked(db.foo.insert({a: 1}));
@@ -69,6 +72,7 @@ function runAllUserManagementCommandsTests(conn, writeConcern) {
assert.commandWorked(db.adminCommand('connPoolSync'));
db.logout();
+
assert(db.auth('andy', 'pwd'));
hasAuthzError(db.foo.insert({a: 1}));
assert.throws(function() {
@@ -77,20 +81,21 @@ function runAllUserManagementCommandsTests(conn, writeConcern) {
assert.throws(function() {
db.getRole('testRole');
});
+ db.logout();
})();
(function testUpdateUser() {
jsTestLog("Testing updateUser");
testUserAdmin.updateUser('spencer', {pwd: 'password', customData: {}}, writeConcern);
- var user = testUserAdmin.getUser('spencer');
- assert.eq(null, user.customData.zipCode);
+ const user1 = testUserAdmin.getUser('spencer');
+ assert.eq(null, user1.customData.zipCode);
assert(!db.auth('spencer', 'pwd'));
assert(db.auth('spencer', 'password'));
testUserAdmin.updateUser(
'spencer', {customData: {zipCode: 10036}, roles: ["read", "testRole"]}, writeConcern);
- var user = testUserAdmin.getUser('spencer');
+ const user = testUserAdmin.getUser('spencer');
assert.eq(10036, user.customData.zipCode);
hasAuthzError(db.foo.insert({a: 1}));
assert.eq(1, db.foo.findOne().a);
@@ -217,7 +222,7 @@ function runAllUserManagementCommandsTests(conn, writeConcern) {
jsTestLog("Testing usersInfo");
jsTestLog("Running exact usersInfo with default options on username only");
- var res = testUserAdmin.runCommand({usersInfo: 'spencer'});
+ let res = testUserAdmin.runCommand({usersInfo: 'spencer'});
printjson(res);
assert.eq(1, res.users.length);
assert.eq(10036, res.users[0].customData.zipCode);
@@ -424,12 +429,14 @@ function runAllUserManagementCommandsTests(conn, writeConcern) {
jsTestLog("Testing dropUser");
assert(db.auth('spencer', 'password'));
+ db.logout();
assert(db.auth('andy', 'pwd'));
testUserAdmin.dropUser('spencer', writeConcern);
assert(!db.auth('spencer', 'password'));
assert(db.auth('andy', 'pwd'));
+ db.logout();
assert.eq(1, testUserAdmin.getUsers().length);
})();
@@ -439,6 +446,7 @@ function runAllUserManagementCommandsTests(conn, writeConcern) {
assert.eq(1, testUserAdmin.getUsers().length);
assert(db.auth('andy', 'pwd'));
+ db.logout();
testUserAdmin.dropAllUsers(writeConcern);
diff --git a/jstests/auth/user_management_commands_mechanisms.js b/jstests/auth/user_management_commands_mechanisms.js
index 98c806f194b..a1784b2d375 100644
--- a/jstests/auth/user_management_commands_mechanisms.js
+++ b/jstests/auth/user_management_commands_mechanisms.js
@@ -6,7 +6,6 @@
let mongod = MongoRunner.runMongod(
{auth: "", setParameter: "authenticationMechanisms=SCRAM-SHA-1,SCRAM-SHA-256,PLAIN"});
-assert(mongod);
const admin = mongod.getDB('admin');
const test = mongod.getDB('test');
@@ -32,6 +31,7 @@ function checkUser(userid, passwd, haveSCRAMSHA1, haveSCRAMSHA256) {
}
}
+ 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);
@@ -54,6 +54,7 @@ function checkUser(userid, passwd, haveSCRAMSHA1, haveSCRAMSHA256) {
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);
@@ -70,45 +71,53 @@ function checkUser(userid, passwd, haveSCRAMSHA1, haveSCRAMSHA256) {
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.
-assert.throws(function() {
- test.createUser({
- user: 'shalala',
- pwd: 'pass',
- roles: jsTest.basicUserRoles,
- mechanisms: ['SCRAM-SHA-1', 'SCRAM-SHA-LA-LA'],
- });
+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.
-test.createUser({user: 'user', pwd: 'pass', roles: jsTest.basicUserRoles});
+createUser(test, {user: 'user', pwd: 'pass', roles: jsTest.basicUserRoles});
checkUser('user', 'pass', true, true);
// Request SHA1 only.
-test.createUser(
+createUser(
+ test,
{user: 'sha1user', pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: ['SCRAM-SHA-1']});
checkUser('sha1user', 'pass', true, false);
// Request SHA256 only.
-test.createUser(
+createUser(
+ test,
{user: 'sha256user', pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: ['SCRAM-SHA-256']});
checkUser('sha256user', 'pass', false, true);
// Fail passing an empty mechanisms field.
-assert.throws(function() {
- test.createUser(
- {user: 'userNoMech', pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: []});
-});
+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.
-assert.throws(function() {
- test.createUser(
- {user: 'user2', pwd: 'pass', roles: jsTest.basicUserRoles, passwordDisgestor: 'client'});
-});
+createUserThrows(
+ test, {user: 'user2', pwd: 'pass', roles: jsTest.basicUserRoles, passwordDisgestor: 'client'});
-test.createUser({
+createUser(test, {
user: 'sha1user2',
pwd: 'pass',
roles: jsTest.basicUserRoles,
@@ -117,47 +126,55 @@ test.createUser({
});
checkUser('sha1user2', 'pass', true, false);
-assert.throws(function() {
- test.createUser({
- user: 'sha256user2',
- pwd: 'pass',
- roles: jsTest.basicUserRoles,
- mechanisms: ['SCRAM-SHA-256'],
- passwordDigestor: 'client'
- });
+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.
-test.updateUser('user', {pwd: 'pass1', mechanisms: ['SCRAM-SHA-1']});
+updateUser(test, 'user', {pwd: 'pass1', mechanisms: ['SCRAM-SHA-1']});
checkUser('user', 'pass1', true, false);
// Then flip to 256-only
-test.updateUser('user', {pwd: 'pass256', mechanisms: ['SCRAM-SHA-256']});
+updateUser(test, 'user', {pwd: 'pass256', mechanisms: ['SCRAM-SHA-256']});
checkUser('user', 'pass256', false, true);
// And back to (default) all.
-test.updateUser('user', {pwd: 'passAll'});
+updateUser(test, 'user', {pwd: 'passAll'});
checkUser('user', 'passAll', true, true);
// Trim out mechanisms without changing password.
-test.updateUser('user', {mechanisms: ['SCRAM-SHA-256']});
+updateUser(test, 'user', {mechanisms: ['SCRAM-SHA-256']});
checkUser('user', 'passAll', false, true);
// Fail when mechanisms is not a subset of the current user.
-assert.throws(function() {
- test.updateUser('user', {mechanisms: ['SCRAM-SHA-1']});
-});
+updateUserThrows(test, 'user', {mechanisms: ['SCRAM-SHA-1']});
// Fail when passing an empty mechanisms field.
-assert.throws(function() {
- test.updateUser('user', {pwd: 'passEmpty', mechanisms: []});
-});
+updateUserThrows(test, 'user', {pwd: 'passEmpty', mechanisms: []});
// Succeed if we're using SHA-1 only.
-test.createUser(
- {user: "\u2168", pwd: 'pass', roles: jsTest.basicUserRoles, mechanisms: ['SCRAM-SHA-1']});
+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) {
@@ -195,22 +212,29 @@ assert.eq(["sha256user", "user"], foundUsers);
MongoRunner.stopMongod(mongod);
// Ensure mechanisms can be enabled and disabled.
-mongod = MongoRunner.runMongod({
- auth: "",
- setParameter: "authenticationMechanisms=SCRAM-SHA-1",
- restart: mongod,
- noCleanData: true
-});
-assert(mongod.getDB("test").auth("sha1user", "pass"));
-assert(!mongod.getDB("test").auth("sha256user", "pass"));
-MongoRunner.stopMongod(mongod);
-mongod = MongoRunner.runMongod({
- auth: "",
- setParameter: "authenticationMechanisms=SCRAM-SHA-256",
- restart: mongod,
- noCleanData: true
-});
-assert(!mongod.getDB("test").auth("sha1user", "pass"));
-assert(mongod.getDB("test").auth("sha256user", "pass"));
-MongoRunner.stopMongod(mongod);
+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');
})();
diff --git a/jstests/auth/user_special_chars.js b/jstests/auth/user_special_chars.js
index 6ee9371860c..23afa7f617a 100644
--- a/jstests/auth/user_special_chars.js
+++ b/jstests/auth/user_special_chars.js
@@ -48,17 +48,6 @@ var testUserAndDatabaseAtSymbolConflation = function() {
assert.commandWorked(bcDB.col.insert({data: 3}));
assert.writeError(cDB.col.insert({data: 4}));
assert(bcDB.logout());
-
- // Ensure that the user cache permits both users to log in at the same time
- assert(cDB.auth('a@b', 'pass1'));
- assert(bcDB.auth('a', 'pass2'));
- assert(cDB.logout());
- assert(bcDB.logout());
-
- assert(bcDB.auth('a', 'pass2'));
- assert(cDB.auth('a@b', 'pass1'));
- assert(cDB.logout());
- assert(bcDB.logout());
};
testUserAndDatabaseAtSymbolConflation();
diff --git a/jstests/auth/views_authz.js b/jstests/auth/views_authz.js
index 25093191628..b74176ea52a 100644
--- a/jstests/auth/views_authz.js
+++ b/jstests/auth/views_authz.js
@@ -11,12 +11,12 @@ TestData.disableImplicitSessions = true;
function runTest(conn) {
// Create the admin user.
- let adminDB = conn.getDB("admin");
+ const adminDB = conn.getDB("admin");
assert.commandWorked(adminDB.runCommand({createUser: "admin", pwd: "admin", roles: ["root"]}));
- assert.eq(1, adminDB.auth("admin", "admin"));
+ assert(adminDB.auth("admin", "admin"));
const viewsDBName = "views_authz";
- let viewsDB = adminDB.getSiblingDB(viewsDBName);
+ const viewsDB = adminDB.getSiblingDB(viewsDBName);
viewsDB.dropAllUsers();
viewsDB.logout();
@@ -38,7 +38,7 @@ function runTest(conn) {
viewsDB.runCommand({createUser: "viewUser", pwd: "pwd", roles: ["readWriteView"]}));
adminDB.logout();
- assert.eq(1, viewsDB.auth("viewUser", "pwd"));
+ assert(viewsDB.auth("viewUser", "pwd"));
const lookupStage = {$lookup: {from: "forbidden", localField: "x", foreignField: "x", as: "y"}};
const graphLookupStage = {
@@ -104,6 +104,7 @@ function runTest(conn) {
assert.commandFailedWithCode(viewsDB.runCommand({collMod: "view", viewOn: "other"}),
ErrorCodes.InvalidOptions,
"modified a view without having to specify 'pipeline'");
+ viewsDB.logout();
// Create a view on a forbidden collection and populate it.
assert.eq(1, adminDB.auth("admin", "admin"));
@@ -115,25 +116,27 @@ function runTest(conn) {
// Performing a find on a readable view returns a cursor that allows us to perform a getMore
// even if the underlying collection is unreadable.
+ assert(viewsDB.auth("viewUser", "pwd"));
assert.commandFailedWithCode(viewsDB.runCommand({find: "forbidden"}),
ErrorCodes.Unauthorized,
"successfully performed a find on an unreadable namespace");
- let res = viewsDB.runCommand({find: "view2", batchSize: 1});
+ const res = viewsDB.runCommand({find: "view2", batchSize: 1});
assert.commandWorked(res, "could not perform a find on a readable view");
assert.eq(res.cursor.ns,
"views_authz.view2",
"performing find on a view does not return a cursor on the view namespace");
assert.commandWorked(viewsDB.runCommand({getMore: res.cursor.id, collection: "view2"}),
"could not perform getMore on a readable view");
+ viewsDB.logout();
}
// Run the test on a standalone.
-let mongod = MongoRunner.runMongod({auth: "", bind_ip: "127.0.0.1"});
+const mongod = MongoRunner.runMongod({auth: "", bind_ip: "127.0.0.1"});
runTest(mongod);
MongoRunner.stopMongod(mongod);
// Run the test on a sharded cluster.
-let cluster = new ShardingTest(
+const cluster = new ShardingTest(
{shards: 1, mongos: 1, keyFile: "jstests/libs/key1", other: {shardOptions: {auth: ""}}});
runTest(cluster);
cluster.stop();
diff --git a/jstests/core/user_management_helpers.js b/jstests/core/user_management_helpers.js
index 4bd64d51864..b71752a2ac8 100644
--- a/jstests/core/user_management_helpers.js
+++ b/jstests/core/user_management_helpers.js
@@ -6,11 +6,14 @@
// requires_non_retryable_commands,
// ]
+(function() {
+'use strict';
+
// This test is a basic sanity check of the shell helpers for manipulating user objects
// It is not a comprehensive test of the functionality of the user manipulation commands
function assertHasRole(rolesArray, roleName, roleDB) {
- for (i in rolesArray) {
- var curRole = rolesArray[i];
+ for (let i in rolesArray) {
+ const curRole = rolesArray[i];
if (curRole.role == roleName && curRole.db == roleDB) {
return;
}
@@ -19,7 +22,6 @@ function assertHasRole(rolesArray, roleName, roleDB) {
}
function runTest(db) {
- var db = db.getSiblingDB("user_management_helpers");
db.dropDatabase();
db.dropAllUsers();
@@ -27,12 +29,12 @@ function runTest(db) {
db.createUser({user: "andy", pwd: "password", roles: ['readWrite']});
// Test getUser
- var userObj = db.getUser('spencer');
+ let userObj = db.getUser('spencer');
assert.eq(1, userObj.roles.length);
assertHasRole(userObj.roles, "readWrite", db.getName());
// Test getUsers
- var users = db.getUsers();
+ let users = db.getUsers();
assert.eq(2, users.length);
assert(users[0].user == 'spencer' || users[1].user == 'spencer');
assert(users[0].user == 'andy' || users[1].user == 'andy');
@@ -93,19 +95,7 @@ function runTest(db) {
db.createUser({user: 'user1', pwd: 'x', roles: [], passwordDigestor: 'foo'});
});
db.createUser({user: 'user1', pwd: 'x', roles: [], passwordDigestor: "server"});
-
- // Note that as of SERVER-32974, client-side digestion is only permitted under the SCRAM-SHA-1
- // mechanism.
- db.createUser({
- user: 'user2',
- pwd: 'x',
- roles: [],
- mechanisms: ['SCRAM-SHA-1'],
- passwordDigestor: "client"
- });
assert(db.auth('user1', 'x'));
- assert(db.auth('user2', 'x'));
-
assert.throws(function() {
db.updateUser('user1', {pwd: 'y', digestPassword: true});
});
@@ -115,10 +105,25 @@ function runTest(db) {
assert.throws(function() {
db.updateUser('user1', {pwd: 'y', passwordDigestor: 'foo'});
});
+
+ // Change password and reauth using new credentials.
db.updateUser('user1', {pwd: 'y', passwordDigestor: 'server'});
- db.updateUser('user2', {pwd: 'y', mechanisms: ['SCRAM-SHA-1'], passwordDigestor: 'client'});
assert(db.auth('user1', 'y'));
+ db.logout();
+
+ // Note that as of SERVER-32974, client-side digestion is only permitted under the SCRAM-SHA-1
+ // mechanism.
+ db.createUser({
+ user: 'user2',
+ pwd: 'x',
+ roles: [],
+ mechanisms: ['SCRAM-SHA-1'],
+ passwordDigestor: "client"
+ });
+ assert(db.auth('user2', 'x'));
+ db.updateUser('user2', {pwd: 'y', mechanisms: ['SCRAM-SHA-1'], passwordDigestor: 'client'});
assert(db.auth('user2', 'y'));
+ db.logout();
// Test createUser requires 'user' field
assert.throws(function() {
@@ -132,9 +137,10 @@ function runTest(db) {
}
try {
- runTest(db);
+ runTest(db.getSiblingDB('user_management_helpers'));
} catch (x) {
// BF-836 Print current users on failure to aid debugging
db.getSiblingDB('admin').system.users.find().forEach(printjson);
throw x;
}
+})();
diff --git a/jstests/multiVersion/libs/multi_rs.js b/jstests/multiVersion/libs/multi_rs.js
index 48d8f57bd2e..058f6e7c404 100644
--- a/jstests/multiVersion/libs/multi_rs.js
+++ b/jstests/multiVersion/libs/multi_rs.js
@@ -78,20 +78,21 @@ ReplSetTest.prototype.upgradeArbiters = function(options, user, pwd) {
};
ReplSetTest.prototype.upgradePrimary = function(primary, options, user, pwd) {
+ function authNode(node) {
+ if (user !== undefined) {
+ assert(node.getDB('admin').auth(user, pwd));
+ } else {
+ jsTest.authenticate(node);
+ }
+ }
+
// Merge new options into node settings.
this.nodeOptions = mergeNodeOptions(this.nodeOptions, options);
- jsTest.authenticate(primary);
+ authNode(primary);
let oldPrimary = this.stepdown(primary);
- this.waitForState(oldPrimary, ReplSetTest.State.SECONDARY);
-
- // stepping down the node can close the connection and lose the authentication state, so
- // re-authenticate here before calling awaitNodesAgreeOnPrimary().
- if (user != undefined) {
- oldPrimary.getDB('admin').auth(user, pwd);
- }
- jsTest.authenticate(oldPrimary);
+ this.waitForState(oldPrimary, ReplSetTest.State.SECONDARY, undefined, authNode);
// waitForState() runs the logout command via asCluster() on either the current primary or the
// first node in the replica set so we re-authenticate on all connections before calling
@@ -105,10 +106,7 @@ ReplSetTest.prototype.upgradePrimary = function(primary, options, user, pwd) {
continue;
}
- if (user != undefined) {
- node.getDB('admin').auth(user, pwd);
- }
- jsTest.authenticate(node);
+ authNode(node);
}
this.awaitNodesAgreeOnPrimary();
@@ -126,7 +124,7 @@ ReplSetTest.prototype.upgradePrimary = function(primary, options, user, pwd) {
};
ReplSetTest.prototype.upgradeNode = function(node, opts = {}, user, pwd) {
- if (user != undefined) {
+ if (user !== undefined) {
assert.eq(1, node.getDB("admin").auth(user, pwd));
}
jsTest.authenticate(node);
@@ -145,7 +143,7 @@ ReplSetTest.prototype.upgradeNode = function(node, opts = {}, user, pwd) {
}
var newNode = this.restart(node, opts);
- if (user != undefined) {
+ if (user !== undefined) {
newNode.getDB("admin").auth(user, pwd);
}
@@ -153,6 +151,10 @@ ReplSetTest.prototype.upgradeNode = function(node, opts = {}, user, pwd) {
[ReplSetTest.State.PRIMARY, ReplSetTest.State.SECONDARY, ReplSetTest.State.ARBITER];
this.waitForState(newNode, waitForStates);
+ if (user !== undefined) {
+ newNode.getDB('admin').logout();
+ }
+
return newNode;
};
diff --git a/jstests/noPassthrough/change_streams_required_privileges.js b/jstests/noPassthrough/change_streams_required_privileges.js
index 2beae275bcc..504b641e68d 100644
--- a/jstests/noPassthrough/change_streams_required_privileges.js
+++ b/jstests/noPassthrough/change_streams_required_privileges.js
@@ -136,9 +136,12 @@ const adminDB = db.getSiblingDB("admin");
roles: [],
privileges: [{resource: {cluster: true}, actions: ["changeStream"]}]
});
+ adminDB.logout();
}());
(function createUsers() {
+ assert(adminDB.auth("userAdmin", password));
+
// Create some users for a specific collection. Use the name of the role as the name of the
// user.
for (let role of ["write", "find_only", "find_and_change_stream", "change_stream_only"]) {
@@ -177,6 +180,8 @@ const adminDB = db.getSiblingDB("admin");
"cluster_change_stream_only"]) {
adminDB.createUser({user: role, pwd: password, roles: [role]});
}
+
+ adminDB.logout();
}());
(function testPrivilegesForSingleCollection() {
diff --git a/jstests/noPassthrough/multi_user_forbidden.js b/jstests/noPassthrough/multi_user_forbidden.js
index 33e6d7ca87f..e025c08b245 100644
--- a/jstests/noPassthrough/multi_user_forbidden.js
+++ b/jstests/noPassthrough/multi_user_forbidden.js
@@ -28,10 +28,12 @@ function runTest(conn) {
const vanillaConn = new Mongo(conn.host);
assert(vanillaConn.getDB(db1).auth(user1, pass), "Initial authN should succeed");
- assert(vanillaConn.getDB(db2).auth(user2, pass), "AuthN on another db should succeed");
+ assert(!vanillaConn.getDB(db2).auth(user2, pass), "AuthN on another db should not succeed");
assert(vanillaConn.getDB(db1).auth(user1, pass), "Re-authN as first user should succeed");
- assert(vanillaConn.getDB(db3).auth(user3, pass),
- "AuthN as a new user on the first database should succeed");
+ assert(!vanillaConn.getDB(db3).auth(user3, pass),
+ "AuthN as a new user on the first database should not succeed");
+
+ vanillaConn.getDB(db1).logout();
}
{
@@ -39,10 +41,12 @@ function runTest(conn) {
const laxConn = new Mongo(conn.host, undefined, {api: {version: '1', strict: false}});
assert(laxConn.getDB(db1).auth(user1, pass), "Initial authN should succeed");
- assert(laxConn.getDB(db2).auth(user2, pass), "AuthN on another db should succeed");
+ assert(!laxConn.getDB(db2).auth(user2, pass), "AuthN on another db should not succeed");
assert(laxConn.getDB(db1).auth(user1, pass), "Re-authN as first user should succeed");
- assert(laxConn.getDB(db3).auth(user3, pass),
- "AuthN as a new user on the first database should succeed");
+ assert(!laxConn.getDB(db3).auth(user3, pass),
+ "AuthN as a new user on the first database should not succeed");
+
+ laxConn.getDB(db1).logout();
}
{
@@ -54,6 +58,8 @@ function runTest(conn) {
assert(!strictConn.getDB(db1).auth(user1, pass), "Re-authN as first user should fail");
assert(!strictConn.getDB(db3).auth(user3, pass),
"AuthN as a new user on the first database should fail");
+
+ strictConn.getDB(db1).logout();
}
{
@@ -64,11 +70,13 @@ function runTest(conn) {
const strictishConn = new Mongo(conn.host, undefined, {api: {version: '1', strict: true}});
assert(strictishConn.getDB(db1).auth(user1, pass), "Initial authN should succeed");
- assert(strictishConn.getDB(db2).auth(user2, pass), "AuthN on another db should succeed");
+ assert(!strictishConn.getDB(db2).auth(user2, pass),
+ "AuthN on another db should not succeed");
assert(strictishConn.getDB(db1).auth(user1, pass), "Re-authN as first user should succeed");
- assert(strictishConn.getDB(db3).auth(user3, pass),
- "AuthN as a new user on the first database should succeed");
+ assert(!strictishConn.getDB(db3).auth(user3, pass),
+ "AuthN as a new user on the first database should not succeed");
+ strictishConn.getDB(db1).logout();
fp.off();
}
}
diff --git a/jstests/noPassthrough/start_session_command.js b/jstests/noPassthrough/start_session_command.js
index 5c2bbd4b38b..0ad209c30e7 100644
--- a/jstests/noPassthrough/start_session_command.js
+++ b/jstests/noPassthrough/start_session_command.js
@@ -5,24 +5,20 @@
// implicit sessions.
TestData.disableImplicitSessions = true;
-var conn;
-var admin;
-var foo;
-var result;
const request = {
startSession: 1
};
-conn = MongoRunner.runMongod({setParameter: {maxSessions: 2}});
-admin = conn.getDB("admin");
+let conn = MongoRunner.runMongod({setParameter: {maxSessions: 2}});
+let admin = conn.getDB("admin");
// ensure that the cache is empty
-var serverStatus = assert.commandWorked(admin.adminCommand({serverStatus: 1}));
+let serverStatus = assert.commandWorked(admin.adminCommand({serverStatus: 1}));
assert.eq(0, serverStatus.logicalSessionRecordCache.activeSessionsCount);
// test that we can run startSession unauthenticated when the server is running without --auth
-result = admin.runCommand(request);
+let result = admin.runCommand(request);
assert.commandWorked(
result,
"failed test that we can run startSession unauthenticated when the server is running without --auth");
@@ -53,7 +49,6 @@ MongoRunner.stopMongod(conn);
conn = MongoRunner.runMongod({auth: "", nojournal: ""});
admin = conn.getDB("admin");
-foo = conn.getDB("foo");
// test that we can't run startSession unauthenticated when the server is running with --auth
@@ -66,8 +61,6 @@ assert.commandFailed(
admin.createUser({user: 'admin', pwd: 'admin', roles: jsTest.adminUserRoles});
admin.auth("admin", "admin");
admin.createUser({user: 'user0', pwd: 'password', roles: jsTest.basicUserRoles});
-foo.createUser({user: 'user1', pwd: 'password', roles: jsTest.basicUserRoles});
-admin.createUser({user: 'user2', pwd: 'password', roles: []});
admin.logout();
// test that we can run startSession authenticated as one user with proper permissions
@@ -79,21 +72,7 @@ assert.commandWorked(
"failed test that we can run startSession authenticated as one user with proper permissions");
assert(result.id, "failed test that our session response has an id");
assert.eq(result.timeoutMinutes, 30, "failed test that our session record has the correct timeout");
-
-// test that we cant run startSession authenticated as two users with proper permissions
-
-foo.auth("user1", "password");
-assert.commandFailed(
- admin.runCommand(request),
- "failed test that we cant run startSession authenticated as two users with proper permissions");
-
-// test that we cant run startSession authenticated as one user without proper permissions
-
admin.logout();
-admin.auth("user2", "password");
-assert.commandFailed(
- admin.runCommand(request),
- "failed test that we cant run startSession authenticated as one user without proper permissions");
//
diff --git a/jstests/replsets/advance_cluster_time.js b/jstests/replsets/advance_cluster_time.js
index 86f1637acd7..2e4fdf74b15 100644
--- a/jstests/replsets/advance_cluster_time.js
+++ b/jstests/replsets/advance_cluster_time.js
@@ -54,6 +54,7 @@ function createUsers(primary) {
pwd: kUserWithAdvanceClusterTimePrivilege.pwd,
roles: [{role: "advanceClusterTimeRole", db: "admin"}, "readWrite"]
}));
+ adminDB.logout();
}
const rst1 = new ReplSetTest({
@@ -103,6 +104,9 @@ const rst2TestDB = rst2Primary.getDB(kDbName);
assert.commandFailedWithCode(
rst1TestDB.runCommand({find: kCollName, $clusterTime: rst2ClusterTime}),
[ErrorCodes.TimeProofMismatch, ErrorCodes.KeyNotFound]);
+
+ rst1TestDB.logout();
+ rst2TestDB.logout();
})();
// Test clusterTime gossip when the client does have advanceClusterTime privilege.
@@ -123,6 +127,9 @@ const rst2TestDB = rst2Primary.getDB(kDbName);
jsTest.log("rst2's clusterTime " + tojson(rst2ClusterTime));
assert.commandWorked(rst1TestDB.runCommand({find: kCollName, $clusterTime: rst2ClusterTime}));
+
+ rst1TestDB.logout();
+ rst2TestDB.logout();
})();
rst1.stopSet();
diff --git a/jstests/replsets/auth1.js b/jstests/replsets/auth1.js
index a91137391a8..14f213b96bd 100644
--- a/jstests/replsets/auth1.js
+++ b/jstests/replsets/auth1.js
@@ -105,6 +105,7 @@ print("unauthorized:");
printjson(primary.adminCommand({replSetGetStatus: 1}));
doQueryOn(primary);
+primary.getDB("admin").logout();
result = secondary.getDB("test").auth("bar", "baz");
assert.eq(result, 1);
@@ -119,6 +120,7 @@ for (var i = 0; i < 1000; i++) {
bulk.insert({x: i, foo: "bar"});
}
assert.commandWorked(bulk.execute({w: 3, wtimeout: ReplSetTest.kDefaultTimeoutMS}));
+primary.getDB("test").logout();
print("fail over");
rs.stop(mId);
@@ -132,17 +134,21 @@ for (var i = 0; i < 1000; i++) {
bulk.insert({x: i, foo: "bar"});
}
assert.commandWorked(bulk.execute({w: 2}));
+primary.getDB("test").logout();
print("resync");
rs.restart(mId, {"keyFile": key1_600});
+rs.keyFile = key1_600;
primary = rs.getPrimary();
print("add some more data 2");
+primary.getDB("test").auth("bar", "baz");
bulk = primary.getDB("test").foo.initializeUnorderedBulkOp();
for (var i = 0; i < 1000; i++) {
bulk.insert({x: i, foo: "bar"});
}
bulk.execute({w: 3, wtimeout: ReplSetTest.kDefaultTimeoutMS});
+primary.getDB("test").logout();
print("add member with wrong key");
var conn = MongoRunner.runMongod({
@@ -162,6 +168,8 @@ try {
} catch (e) {
print("error: " + e);
}
+primary.getDB("admin").logout();
+
primary = rs.getPrimary();
primary.getDB("admin").auth("foo", "bar");
@@ -173,6 +181,7 @@ for (var i = 0; i < 10; i++) {
assert(results.members[3].state != 2);
sleep(1000);
}
+primary.getDB("admin").logout();
print("stop member");
MongoRunner.stopMongod(conn);
@@ -186,6 +195,7 @@ var conn = MongoRunner.runMongod({
keyFile: key1_600
});
+primary.getDB('admin').auth("foo", "bar");
wait(function() {
try {
var results = primary.adminCommand({replSetGetStatus: 1});
@@ -196,6 +206,7 @@ wait(function() {
}
return false;
});
+primary.getDB('admin').logout();
print("make sure it has the config, too");
assert.soon(function() {
@@ -203,6 +214,7 @@ assert.soon(function() {
rs.nodes[i].setSecondaryOk();
rs.nodes[i].getDB("admin").auth("foo", "bar");
config = rs.nodes[i].getDB("local").system.replset.findOne();
+ rs.nodes[i].getDB("admin").logout();
// We expect the config version to be 3 due to the initial config and then the
// 'newlyAdded' removal reconfig.
if (config.version !== 3) {
diff --git a/jstests/replsets/rollback_auth.js b/jstests/replsets/rollback_auth.js
index 6a4bb9ec392..5c08e4b3fae 100644
--- a/jstests/replsets/rollback_auth.js
+++ b/jstests/replsets/rollback_auth.js
@@ -17,22 +17,22 @@
TestData.disableImplicitSessions = true;
// helper function for verifying contents at the end of the test
-var checkFinalResults = function(db) {
+function checkFinalResults(db) {
assert.commandWorked(db.runCommand({dbStats: 1}));
assert.commandFailedWithCode(db.runCommand({collStats: 'foo'}), authzErrorCode);
assert.commandFailedWithCode(db.runCommand({collStats: 'bar'}), authzErrorCode);
assert.commandWorked(db.runCommand({collStats: 'baz'}));
assert.commandWorked(db.runCommand({collStats: 'foobar'}));
-};
+}
-var authzErrorCode = 13;
+const authzErrorCode = 13;
jsTestLog("Setting up replica set");
-var name = "rollbackAuth";
-var replTest = new ReplSetTest({name: name, nodes: 3, keyFile: 'jstests/libs/key1'});
-var nodes = replTest.nodeList();
-var conns = replTest.startSet();
+const name = "rollbackAuth";
+const replTest = new ReplSetTest({name: name, nodes: 3, keyFile: 'jstests/libs/key1'});
+const nodes = replTest.nodeList();
+const conns = replTest.startSet();
replTest.initiate({
"_id": "rollbackAuth",
"members": [
@@ -44,41 +44,48 @@ replTest.initiate({
// Make sure we have a primary
replTest.waitForState(replTest.nodes[0], ReplSetTest.State.PRIMARY);
-var primary = replTest.getPrimary();
-var a_conn = conns[0];
-var b_conn = conns[1];
+const primary = replTest.getPrimary();
+const a_conn = conns[0];
+const b_conn = conns[1];
a_conn.setSecondaryOk();
b_conn.setSecondaryOk();
-var A = a_conn.getDB("admin");
-var B = b_conn.getDB("admin");
-var a = a_conn.getDB("test");
-var b = b_conn.getDB("test");
+const A_admin = a_conn.getDB("admin");
+const B_admin = b_conn.getDB("admin");
+const A_test = a_conn.getDB("test");
+const B_test = b_conn.getDB("test");
assert.eq(primary, conns[0], "conns[0] assumed to be primary");
assert.eq(a_conn, primary);
// Make sure we have an arbiter
assert.soon(function() {
- var res = conns[2].getDB("admin").runCommand({replSetGetStatus: 1});
+ const res = conns[2].getDB("admin").runCommand({replSetGetStatus: 1});
return res.myState == 7;
}, "Arbiter failed to initialize.");
jsTestLog("Creating initial data");
// Create collections that will be used in test
-A.createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
-A.auth('admin', 'pwd');
-a.foo.insert({a: 1});
-a.bar.insert({a: 1});
-a.baz.insert({a: 1});
-a.foobar.insert({a: 1});
+A_admin.createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
+A_admin.auth('admin', 'pwd');
// Set up user admin user
-A.createUser({user: 'userAdmin', pwd: 'pwd', roles: ['userAdminAnyDatabase']});
-A.auth('userAdmin', 'pwd'); // Logs out of admin@admin user
-B.auth('userAdmin', 'pwd');
+A_admin.createUser({user: 'userAdmin', pwd: 'pwd', roles: ['userAdminAnyDatabase']});
+
+A_test.foo.insert({a: 1});
+A_test.bar.insert({a: 1});
+A_test.baz.insert({a: 1});
+A_test.foobar.insert({a: 1});
+A_admin.logout();
+
+assert(A_admin.auth('userAdmin', 'pwd'));
+
+// Give replication time to catch up.
+assert.soon(function() {
+ return B_admin.auth('userAdmin', 'pwd');
+});
// Create a basic user and role
-A.createRole({
+A_admin.createRole({
role: 'replStatusRole', // To make awaitReplication() work
roles: [],
privileges: [
@@ -87,64 +94,75 @@ A.createRole({
{resource: {db: 'local', collection: 'system.replset'}, actions: ['find']}
]
});
-a.createRole({
+A_test.createRole({
role: 'myRole',
roles: [],
privileges: [{resource: {db: 'test', collection: ''}, actions: ['dbStats']}]
});
-a.createUser(
+A_test.createUser(
{user: 'spencer', pwd: 'pwd', roles: ['myRole', {role: 'replStatusRole', db: 'admin'}]});
-assert(a.auth('spencer', 'pwd'));
+
+A_admin.logout();
+B_admin.logout();
+
+assert(A_test.auth('spencer', 'pwd'));
// wait for secondary to get this data
assert.soon(function() {
- return b.auth('spencer', 'pwd');
+ return B_test.auth('spencer', 'pwd');
});
-assert.commandWorked(a.runCommand({dbStats: 1}));
-assert.commandFailedWithCode(a.runCommand({collStats: 'foo'}), authzErrorCode);
-assert.commandFailedWithCode(a.runCommand({collStats: 'bar'}), authzErrorCode);
-assert.commandFailedWithCode(a.runCommand({collStats: 'baz'}), authzErrorCode);
-assert.commandFailedWithCode(a.runCommand({collStats: 'foobar'}), authzErrorCode);
+assert.commandWorked(A_test.runCommand({dbStats: 1}));
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'foo'}), authzErrorCode);
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'bar'}), authzErrorCode);
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'baz'}), authzErrorCode);
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'foobar'}), authzErrorCode);
-assert.commandWorked(b.runCommand({dbStats: 1}));
-assert.commandFailedWithCode(b.runCommand({collStats: 'foo'}), authzErrorCode);
-assert.commandFailedWithCode(b.runCommand({collStats: 'bar'}), authzErrorCode);
-assert.commandFailedWithCode(b.runCommand({collStats: 'baz'}), authzErrorCode);
-assert.commandFailedWithCode(b.runCommand({collStats: 'foobar'}), authzErrorCode);
+assert.commandWorked(B_test.runCommand({dbStats: 1}));
+assert.commandFailedWithCode(B_test.runCommand({collStats: 'foo'}), authzErrorCode);
+assert.commandFailedWithCode(B_test.runCommand({collStats: 'bar'}), authzErrorCode);
+assert.commandFailedWithCode(B_test.runCommand({collStats: 'baz'}), authzErrorCode);
+assert.commandFailedWithCode(B_test.runCommand({collStats: 'foobar'}), authzErrorCode);
jsTestLog("Doing writes that will eventually be rolled back");
// down A and wait for B to become primary
+A_test.logout();
replTest.stop(0);
assert.soon(function() {
try {
- return B.hello().isWritablePrimary;
+ return B_admin.hello().isWritablePrimary;
} catch (e) {
return false;
}
}, "B didn't become primary");
-printjson(b.adminCommand('replSetGetStatus'));
+printjson(assert.commandWorked(B_test.adminCommand('replSetGetStatus')));
+B_test.logout();
// Modify the the user and role in a way that will be rolled back.
-b.grantPrivilegesToRole('myRole',
- [{resource: {db: 'test', collection: 'foo'}, actions: ['collStats']}],
- {}); // Default write concern will wait for majority, which will time out.
-b.createRole({
+assert(B_admin.auth('admin', 'pwd'));
+B_test.grantPrivilegesToRole(
+ 'myRole',
+ [{resource: {db: 'test', collection: 'foo'}, actions: ['collStats']}],
+ {}); // Default write concern will wait for majority, which will time out.
+B_test.createRole({
role: 'temporaryRole',
roles: [],
privileges: [{resource: {db: 'test', collection: 'bar'}, actions: ['collStats']}]
},
- {}); // Default write concern will wait for majority, which will time out.
-b.grantRolesToUser('spencer',
- ['temporaryRole'],
- {}); // Default write concern will wait for majority, which will time out.
+ {}); // Default write concern will wait for majority, which will time out.
+B_test.grantRolesToUser('spencer',
+ ['temporaryRole'],
+ {}); // Default write concern will wait for majority, which will time out.
+B_admin.logout();
-assert.commandWorked(b.runCommand({dbStats: 1}));
-assert.commandWorked(b.runCommand({collStats: 'foo'}));
-assert.commandWorked(b.runCommand({collStats: 'bar'}));
-assert.commandFailedWithCode(b.runCommand({collStats: 'baz'}), authzErrorCode);
-assert.commandFailedWithCode(b.runCommand({collStats: 'foobar'}), authzErrorCode);
+assert(B_test.auth('spencer', 'pwd'));
+assert.commandWorked(B_test.runCommand({dbStats: 1}));
+assert.commandWorked(B_test.runCommand({collStats: 'foo'}));
+assert.commandWorked(B_test.runCommand({collStats: 'bar'}));
+assert.commandFailedWithCode(B_test.runCommand({collStats: 'baz'}), authzErrorCode);
+assert.commandFailedWithCode(B_test.runCommand({collStats: 'foobar'}), authzErrorCode);
+B_test.logout();
// down B, bring A back up, then wait for A to become primary
// insert new data into A so that B will need to rollback when it reconnects to A
@@ -153,39 +171,42 @@ replTest.stop(1);
replTest.restart(0);
assert.soon(function() {
try {
- return A.hello().isWritablePrimary;
+ return A_admin.hello().isWritablePrimary;
} catch (e) {
return false;
}
}, "A didn't become primary");
// A should not have the new data as it was down
-assert.commandWorked(a.runCommand({dbStats: 1}));
-assert.commandFailedWithCode(a.runCommand({collStats: 'foo'}), authzErrorCode);
-assert.commandFailedWithCode(a.runCommand({collStats: 'bar'}), authzErrorCode);
-assert.commandFailedWithCode(a.runCommand({collStats: 'baz'}), authzErrorCode);
-assert.commandFailedWithCode(a.runCommand({collStats: 'foobar'}), authzErrorCode);
+assert(A_test.auth('spencer', 'pwd'));
+assert.commandWorked(A_test.runCommand({dbStats: 1}));
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'foo'}), authzErrorCode);
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'bar'}), authzErrorCode);
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'baz'}), authzErrorCode);
+assert.commandFailedWithCode(A_test.runCommand({collStats: 'foobar'}), authzErrorCode);
+A_test.logout();
jsTestLog("Doing writes that should persist after the rollback");
// Modify the user and role in a way that will persist.
-A.auth('userAdmin', 'pwd');
+A_admin.auth('userAdmin', 'pwd');
// Default write concern will wait for majority, which would time out
// so we override it with an empty write concern
-a.grantPrivilegesToRole(
+A_test.grantPrivilegesToRole(
'myRole', [{resource: {db: 'test', collection: 'baz'}, actions: ['collStats']}], {});
-a.createRole({
+A_test.createRole({
role: 'persistentRole',
roles: [],
privileges: [{resource: {db: 'test', collection: 'foobar'}, actions: ['collStats']}]
},
- {});
-a.grantRolesToUser('spencer', ['persistentRole'], {});
-A.logout();
-a.auth('spencer', 'pwd');
+ {});
+A_test.grantRolesToUser('spencer', ['persistentRole'], {});
+A_admin.logout();
+
+A_test.auth('spencer', 'pwd');
// A has the data we just wrote, but not what B wrote before
-checkFinalResults(a);
+checkFinalResults(A_test);
jsTestLog("Triggering rollback");
@@ -197,11 +218,13 @@ assert.soonNoExcept(function() {
replTest.awaitReplication();
});
- return b.auth('spencer', 'pwd');
+ return B_test.auth('spencer', 'pwd');
});
// Now both A and B should agree
-checkFinalResults(a);
-checkFinalResults(b);
+checkFinalResults(A_test);
+checkFinalResults(B_test);
+
+A_test.logout();
// Verify data consistency between nodes.
authutil.asCluster(replTest.nodes, 'jstests/libs/key1', function() {
diff --git a/jstests/sharding/advance_cluster_time_action_type.js b/jstests/sharding/advance_cluster_time_action_type.js
index ef739aa4b03..6cea1521e00 100644
--- a/jstests/sharding/advance_cluster_time_action_type.js
+++ b/jstests/sharding/advance_cluster_time_action_type.js
@@ -30,6 +30,7 @@ assert.commandWorked(testDB.runCommand({
pwd: 'pwd',
roles: [{role: 'advanceClusterTimeRole', db: 'admin'}, 'readWrite']
}));
+adminDB.logout();
assert.eq(1, testDB.auth("NotTrusted", "pwd"));
let res = testDB.runCommand({insert: "foo", documents: [{_id: 0}]});
@@ -49,6 +50,7 @@ jsTestLog("running NonTrusted. command: " + tojson(cmdObj));
res = testDB.runCommand(cmdObj);
assert.commandFailedWithCode(
res, ErrorCodes.TimeProofMismatch, "Command request was: " + tojsononeline(cmdObj));
+testDB.logout();
assert.eq(1, testDB.auth("Trusted", "pwd"));
jsTestLog("running Trusted. command: " + tojson(cmdObj));
diff --git a/jstests/sharding/authCommands.js b/jstests/sharding/authCommands.js
index c82f3b77b19..7d78366b99e 100644
--- a/jstests/sharding/authCommands.js
+++ b/jstests/sharding/authCommands.js
@@ -282,6 +282,7 @@ checkWriteOps(false);
// Authenticate as read-write user
jsTestLog("Checking commands with read-write auth credentials");
+assert(testDB.logout().ok);
assert(testDB.auth(rwUser, password));
checkReadOps(true);
checkWriteOps(true);
diff --git a/jstests/sharding/commands_that_write_accept_wc_configRS.js b/jstests/sharding/commands_that_write_accept_wc_configRS.js
index 7b147aea257..c34b3d40d59 100644
--- a/jstests/sharding/commands_that_write_accept_wc_configRS.js
+++ b/jstests/sharding/commands_that_write_accept_wc_configRS.js
@@ -20,7 +20,7 @@ load('jstests/multiVersion/libs/auth_helpers.js');
// Multiple users cannot be authenticated on one connection within a session.
TestData.disableImplicitSessions = true;
-var st = new ShardingTest({
+const st = new ShardingTest({
// Set priority of secondaries to zero to prevent spurious elections.
shards: {
rs0: {
@@ -36,45 +36,56 @@ var st = new ShardingTest({
mongos: 1
});
-var mongos = st.s;
-var dbName = "wc-test-configRS";
-var db = mongos.getDB(dbName);
-var adminDB = mongos.getDB('admin');
+const mongos = st.s;
+const dbName = "wc-test-configRS";
+const adminDB = mongos.getDB('admin');
// A database connection on a local shard, rather than through the mongos.
-var localDB = st.shard0.getDB('localWCTest');
-var collName = 'leaves';
-var coll = db[collName];
-var counter = 0;
+const localDB = st.shard0.getDB('localWCTest');
-function dropTestData() {
- st.configRS.awaitReplication();
- st.rs0.awaitReplication();
- st.rs1.awaitReplication();
- db.dropUser('username');
- db.dropUser('user1');
- localDB.dropUser('user2');
- assert(!db.auth("username", "password"), "auth should have failed");
- getNewDB();
-}
+// Separate unauthenticated channel for use in confirmFunc().
+// The sharding_auth suite will stealth-authenticate us,
+// using the local.__system account, so we must explicitly deauth.
+// Since mongos has no 'local' database, we use the test-mode workaround
+// via admin DB found in the implementation of the LogoutCommand.
+const noauthConn = new Mongo(mongos.host);
+noauthConn.getDB('admin').logout();
// We get new databases because we do not want to reuse dropped databases that may be in a
// bad state. This test calls dropDatabase when config server secondary nodes are down, so the
// command fails after only the database metadata is dropped from the config servers, but the
// data on the shards still remains. This makes future operations, such as moveChunk, fail.
+let db = mongos.getDB(dbName);
+let noauthDB = noauthConn.getDB(dbName);
+let counter = 0;
+const collName = 'leaves';
+let coll = db[collName];
function getNewDB() {
db = mongos.getDB(dbName + counter);
+ noauthDB = noauthConn.getDB(dbName + counter);
counter++;
coll = db[collName];
}
+function dropTestData() {
+ st.configRS.awaitReplication();
+ st.rs0.awaitReplication();
+ st.rs1.awaitReplication();
+ db.dropUser('username');
+ db.dropUser('user1');
+ localDB.dropUser('user2');
+ assert(!noauthDB.auth("username", "password"), "auth should have failed");
+ getNewDB();
+}
+
// Commands in 'commands' will accept any valid writeConcern.
-var commands = [];
+const commands = [];
commands.push({
req: {createUser: 'username', pwd: 'password', roles: jsTest.basicUserRoles},
setupFunc: function() {},
confirmFunc: function() {
- assert(db.auth("username", "password"), "auth failed");
+ assert(noauthDB.auth("username", "password"), "auth failed");
+ noauthDB.logout();
},
requiresMajority: true,
runsOnShards: false,
@@ -88,8 +99,9 @@ commands.push({
db.runCommand({createUser: 'username', pwd: 'password', roles: jsTest.basicUserRoles});
},
confirmFunc: function() {
- assert(!db.auth("username", "password"), "auth should have failed");
- assert(db.auth("username", "password2"), "auth failed");
+ assert(!noauthDB.auth("username", "password"), "auth should have failed");
+ assert(noauthDB.auth("username", "password2"), "auth failed");
+ noauthDB.logout();
},
requiresMajority: true,
runsOnShards: false,
@@ -99,11 +111,13 @@ commands.push({
commands.push({
req: {dropUser: 'tempUser'},
setupFunc: function() {
- db.runCommand({createUser: 'tempUser', pwd: 'password', roles: jsTest.basicUserRoles});
- assert(db.auth("tempUser", "password"), "auth failed");
+ assert.commandWorked(
+ db.runCommand({createUser: 'tempUser', pwd: 'password', roles: jsTest.basicUserRoles}));
+ assert(noauthDB.auth("tempUser", "password"), "auth failed");
+ noauthDB.logout();
},
confirmFunc: function() {
- assert(!db.auth("tempUser", "password"), "auth should have failed");
+ assert(!noauthDB.auth("tempUser", "password"), "auth should have failed");
},
requiresMajority: true,
runsOnShards: false,
@@ -120,7 +134,7 @@ function testInvalidWriteConcern(wc, cmd) {
dropTestData();
cmd.setupFunc();
- var res = runCommandCheckAdmin(db, cmd);
+ const res = runCommandCheckAdmin(db, cmd);
assert.commandFailed(res);
assert(!res.writeConcernError,
'bad writeConcern on config server had writeConcernError. ' +
@@ -128,8 +142,6 @@ function testInvalidWriteConcern(wc, cmd) {
}
function runCommandFailOnShardsPassOnConfigs(cmd) {
- var req = cmd.req;
- var res;
// This command is run on the shards in addition to the config servers.
if (cmd.runsOnShards) {
if (cmd.failsOnShards) {
@@ -137,8 +149,8 @@ function runCommandFailOnShardsPassOnConfigs(cmd) {
// We set the timeout high enough that the command should not time out against the
// config server, but not exorbitantly high, because it will always time out against
// shards and so will increase the runtime of this test.
- req.writeConcern.wtimeout = 15 * 1000;
- res = runCommandCheckAdmin(db, cmd);
+ cmd.req.writeConcern.wtimeout = 15 * 1000;
+ const res = runCommandCheckAdmin(db, cmd);
restartReplicationOnAllShards(st);
assert.commandFailed(res);
assert(!res.writeConcernError,
@@ -150,8 +162,8 @@ function runCommandFailOnShardsPassOnConfigs(cmd) {
// We set the timeout high enough that the command should not time out against the
// config server, but not exorbitantly high, because it will always time out against
// shards and so will increase the runtime of this test.
- req.writeConcern.wtimeout = 15 * 1000;
- res = runCommandCheckAdmin(db, cmd);
+ cmd.req.writeConcern.wtimeout = 15 * 1000;
+ const res = runCommandCheckAdmin(db, cmd);
restartReplicationOnAllShards(st);
assert.commandWorked(res);
cmd.confirmFunc();
@@ -160,7 +172,7 @@ function runCommandFailOnShardsPassOnConfigs(cmd) {
} else {
// This command is only run on the config servers and so should pass when shards are
// not replicating.
- res = runCommandCheckAdmin(db, cmd);
+ const res = runCommandCheckAdmin(db, cmd);
restartReplicationOnAllShards(st);
assert.commandWorked(res);
cmd.confirmFunc();
@@ -171,25 +183,23 @@ function runCommandFailOnShardsPassOnConfigs(cmd) {
}
function testValidWriteConcern(wc, cmd) {
- var req = cmd.req;
- var setupFunc = cmd.setupFunc;
- var confirmFunc = cmd.confirmFunc;
-
- req.writeConcern = wc;
- jsTest.log("Testing " + tojson(req));
+ cmd.req.writeConcern = wc;
+ jsTest.log("Testing " + tojson(cmd.req));
dropTestData();
- setupFunc();
+ cmd.setupFunc();
// Command with a full cluster should succeed.
- var res = runCommandCheckAdmin(db, cmd);
+ let res = runCommandCheckAdmin(db, cmd);
assert.commandWorked(res);
assert(!res.writeConcernError,
'command on a full cluster had writeConcernError: ' + tojson(res));
- confirmFunc();
+
+ cmd.confirmFunc();
dropTestData();
- setupFunc();
+ cmd.setupFunc();
+
// Stop replication at all shard secondaries.
stopReplicationOnSecondariesOfAllShards(st);
@@ -198,14 +208,15 @@ function testValidWriteConcern(wc, cmd) {
runCommandFailOnShardsPassOnConfigs(cmd);
dropTestData();
- setupFunc();
+ cmd.setupFunc();
+
// Stop replication at all config server secondaries and all shard secondaries.
stopReplicationOnSecondariesOfAllShards(st);
st.configRS.awaitReplication();
stopReplicationOnSecondaries(st.configRS, false /* changeReplicaSetDefaultWCToLocal */);
// Command should fail after two config servers are not replicating.
- req.writeConcern.wtimeout = 3000;
+ cmd.req.writeConcern.wtimeout = 3000;
res = runCommandCheckAdmin(db, cmd);
restartReplicationOnAllShards(st);
assert.commandFailed(res);
@@ -214,10 +225,13 @@ function testValidWriteConcern(wc, cmd) {
'command on config servers with a paused replicaset had writeConcernError: ' + tojson(res));
}
-var majorityWC = {w: 'majority', wtimeout: ReplSetTest.kDefaultTimeoutMS};
+const majorityWC = {
+ w: 'majority',
+ wtimeout: ReplSetTest.kDefaultTimeoutMS
+};
// Config server commands require w: majority writeConcerns.
-var nonMajorityWCs = [{w: 'invalid'}, {w: 2}];
+const nonMajorityWCs = [{w: 'invalid'}, {w: 2}];
commands.forEach(function(cmd) {
nonMajorityWCs.forEach(function(wc) {
diff --git a/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js b/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js
index 855cac557cd..77e5552ce7a 100644
--- a/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js
+++ b/jstests/sharding/mongos_rs_auth_shard_failure_tolerance.js
@@ -71,20 +71,16 @@ assert.commandWorked(admin.runCommand(
{moveChunk: collSharded.toString(), find: {_id: -1}, to: st.shard0.shardName}));
st.printShardingStatus();
-var shardedDBUser = "shardedDBUser";
-var unshardedDBUser = "unshardedDBUser";
+const dbUser = "dbUser";
jsTest.log("Setting up database users...");
-// Create db users
-collSharded.getDB().createUser({user: shardedDBUser, pwd: password, roles: ["readWrite"]});
-collUnsharded.getDB().createUser({user: unshardedDBUser, pwd: password, roles: ["readWrite"]});
-
+// Create db user
+admin.createUser({user: dbUser, pwd: password, roles: ["readWriteAnyDatabase"]});
admin.logout();
function authDBUsers(conn) {
- conn.getDB(collSharded.getDB().toString()).auth(shardedDBUser, password);
- conn.getDB(collUnsharded.getDB().toString()).auth(unshardedDBUser, password);
+ assert(conn.getDB('admin').auth(dbUser, password));
return conn;
}
@@ -92,8 +88,7 @@ function authDBUsers(conn) {
// is received, and refreshing requires communication with the primary to obtain the newest version.
// Read from the secondaries once before taking down primaries to ensure they have loaded the
// routing table into memory.
-var mongosSetupConn = new Mongo(mongos.host);
-authDBUsers(mongosSetupConn);
+var mongosSetupConn = authDBUsers(new Mongo(mongos.host));
mongosSetupConn.setReadPref("secondary");
assert(!mongosSetupConn.getCollection(collSharded.toString()).find({}).hasNext());
@@ -106,7 +101,6 @@ gc(); // Clean up connections
jsTest.log("Inserting initial data...");
var mongosConnActive = authDBUsers(new Mongo(mongos.host));
-authDBUsers(mongosConnActive);
var mongosConnIdle = null;
var mongosConnNew = null;
diff --git a/jstests/sharding/query/aggregation_currentop.js b/jstests/sharding/query/aggregation_currentop.js
index 0c9d1c3eb04..58d63128329 100644
--- a/jstests/sharding/query/aggregation_currentop.js
+++ b/jstests/sharding/query/aggregation_currentop.js
@@ -703,6 +703,7 @@ function runIdleSessionsTests(conn, adminDB, txnDB, useLocalOps) {
])
.itcount(),
0);
+ adminDB.logout();
// Cancel all transactions and close the associated sessions.
for (let i in userNames) {
@@ -714,6 +715,7 @@ function runIdleSessionsTests(conn, adminDB, txnDB, useLocalOps) {
writeConcern: {w: 'majority'}
}));
sessions[i].endSession();
+ adminDB.logout();
}
}
diff --git a/jstests/sharding/query/mrShardedOutputAuth.js b/jstests/sharding/query/mrShardedOutputAuth.js
index 67e278d529d..2518bcc3095 100644
--- a/jstests/sharding/query/mrShardedOutputAuth.js
+++ b/jstests/sharding/query/mrShardedOutputAuth.js
@@ -12,22 +12,16 @@ const st = new ShardingTest(
{name: "mrShardedOutputAuth", shards: 1, mongos: 1, other: {keyFile: 'jstests/libs/key1'}});
// Setup the users to the input, output and admin databases
-const mongos = st.s;
-let adminDb = mongos.getDB("admin");
-adminDb.createUser({user: "user", pwd: "pass", roles: jsTest.adminUserRoles});
+const authenticatedConn = st.s;
+const adminDb = authenticatedConn.getDB('admin');
+adminDb.createUser({user: 'admin', pwd: 'pass', roles: jsTest.adminUserRoles});
+assert(adminDb.auth('admin', 'pass'));
-const authenticatedConn = new Mongo(mongos.host);
-authenticatedConn.getDB('admin').auth("user", "pass");
-adminDb = authenticatedConn.getDB("admin");
assert.commandWorked(adminDb.adminCommand({enablesharding: "output"}));
const configDb = authenticatedConn.getDB("config");
-
const inputDb = authenticatedConn.getDB("input");
-inputDb.createUser({user: "user", pwd: "pass", roles: jsTest.basicUserRoles});
-
const outputDb = authenticatedConn.getDB("output");
-outputDb.createUser({user: "user", pwd: "pass", roles: jsTest.basicUserRoles});
assert.commandWorked(adminDb.runCommand({enableSharding: outputDb.getName()}));
const nDocs = 50;
@@ -73,24 +67,23 @@ function assertFailure(cmdResponse, configDb, outputDb) {
assert.eq(outputDb.numbers_out.count(), 0, "map/reduce should not have succeeded");
}
+function runTest(user, roles, assertion) {
+ authenticatedConn.getDB(user.db).createUser({user: user.user, pwd: 'pass', roles: roles});
+
+ const conn = new Mongo(st.s.host);
+ assert(conn.getDB(user.db).auth(user.user, 'pass'));
+ const response = doMapReduce(conn, outputDb);
+ assertion(response, configDb, outputDb);
+}
+
// Setup a connection authenticated to both input and output db
-const inputOutputAuthConn = new Mongo(mongos.host);
-inputOutputAuthConn.getDB('input').auth("user", "pass");
-inputOutputAuthConn.getDB('output').auth("user", "pass");
-let cmdResponse = doMapReduce(inputOutputAuthConn, outputDb);
-assertSuccess(cmdResponse, configDb, outputDb);
+runTest({user: 'inout', db: 'admin'}, ['readWriteAnyDatabase'], assertSuccess);
// setup a connection authenticated to only input db
-const inputAuthConn = new Mongo(mongos.host);
-inputAuthConn.getDB('input').auth("user", "pass");
-cmdResponse = doMapReduce(inputAuthConn, outputDb);
-assertFailure(cmdResponse, configDb, outputDb);
+runTest({user: 'inonly', db: 'input'}, ['readWrite'], assertFailure);
// setup a connection authenticated to only output db
-const outputAuthConn = new Mongo(mongos.host);
-outputAuthConn.getDB('output').auth("user", "pass");
-cmdResponse = doMapReduce(outputAuthConn, outputDb);
-assertFailure(cmdResponse, configDb, outputDb);
+runTest({user: 'outOnly', db: 'output'}, ['readWrite'], assertFailure);
st.stop();
})();
diff --git a/jstests/ssl/auth-counters.js b/jstests/ssl/auth-counters.js
index 04274ef8578..c8d762e7c5e 100644
--- a/jstests/ssl/auth-counters.js
+++ b/jstests/ssl/auth-counters.js
@@ -15,7 +15,7 @@ const admin = mongod.getDB('admin');
const external = mongod.getDB('$external');
admin.createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
-admin.auth('admin', 'pwd');
+assert(admin.auth('admin', 'pwd'));
const X509USER = 'CN=client,OU=KernelUser,O=MongoDB,L=New York City,ST=New York,C=US';
external.createUser({user: X509USER, roles: []});
@@ -24,10 +24,19 @@ external.createUser({user: X509USER, roles: []});
// For those, see jstests/auth/auth-counters.js
const expected = assert.commandWorked(admin.runCommand({serverStatus: 1}))
.security.authentication.mechanisms[x509];
+admin.logout();
+
+function asAdmin(cmd, db = admin) {
+ // Does not interfere with stats since we only care about X509.
+ assert(admin.auth('admin', 'pwd'));
+ const result = assert.commandWorked(db.runCommand(cmd));
+ admin.logout();
+ return result;
+}
function assertStats() {
- const mechStats = assert.commandWorked(admin.runCommand({serverStatus: 1}))
- .security.authentication.mechanisms[x509];
+ const mechStats = asAdmin({serverStatus: 1}).security.authentication.mechanisms[x509];
+
try {
assert.eq(mechStats.authenticate.received, expected.authenticate.received);
assert.eq(mechStats.authenticate.successful, expected.authenticate.successful);
@@ -90,11 +99,10 @@ assertSuccess({user: X509USER, mechanism: x509});
assertSuccessInternal();
// Fails once the user no longer exists.
-external.dropUser(X509USER);
+asAdmin({dropUser: X509USER}, external);
assertFailure({mechanism: x509});
-const finalStats =
- assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication.mechanisms;
+const finalStats = asAdmin({serverStatus: 1}).security.authentication.mechanisms;
MongoRunner.stopMongod(mongod);
printjson(finalStats);
})();
diff --git a/jstests/sslSpecial/upgrade_to_x509_ssl_nossl.js b/jstests/sslSpecial/upgrade_to_x509_ssl_nossl.js
index 7dca4147ab6..142b16bcabc 100644
--- a/jstests/sslSpecial/upgrade_to_x509_ssl_nossl.js
+++ b/jstests/sslSpecial/upgrade_to_x509_ssl_nossl.js
@@ -12,31 +12,23 @@
load("jstests/ssl/libs/ssl_helpers.js");
-function authAllNodes() {
- for (var n = 0; n < rst.nodes.length; n++) {
- var status = rst.nodes[n].getDB("admin").auth("root", "pwd");
- assert.eq(status, 1);
- }
-}
+(function() {
+'use strict';
// The mongo shell cannot authenticate as the internal __system user in tests that use x509 for
// cluster authentication. Choosing the default value for wcMajorityJournalDefault in
// ReplSetTest cannot be done automatically without the shell performing such authentication, so
// in this test we must make the choice explicitly, based on the global test options.
-var wcMajorityJournalDefault;
-if (jsTestOptions().noJournal || jsTestOptions().storageEngine == "ephemeralForTest" ||
- jsTestOptions().storageEngine == "inMemory") {
- wcMajorityJournalDefault = false;
-} else {
- wcMajorityJournalDefault = true;
-}
+const wcMajorityJournalDefault = !jsTestOptions().noJournal &&
+ (jsTestOptions().storageEngine != "ephemeralForTest") &&
+ (jsTestOptions().storageEngine != "inMemory");
-opts = {
+const opts = {
sslMode: "disabled",
clusterAuthMode: "keyFile",
};
-var NUM_NODES = 3;
-var rst = new ReplSetTest(
+const NUM_NODES = 3;
+const rst = new ReplSetTest(
{name: 'sslSet', nodes: NUM_NODES, waitForKeys: false, keyFile: KEYFILE, nodeOptions: opts});
rst.startSet();
@@ -45,16 +37,55 @@ rst.startSet();
rst.initiateWithAnyNodeAsPrimary(Object.extend(
rst.getReplSetConfig(), {writeConcernMajorityJournalDefault: wcMajorityJournalDefault}));
-// Connect to master and do some basic operations
-var rstConn1 = rst.getPrimary();
-rstConn1.getDB("admin").createUser({user: "root", pwd: "pwd", roles: ["root"]}, {w: NUM_NODES});
-rstConn1.getDB("admin").auth("root", "pwd");
-rstConn1.getDB("test").a.insert({a: 1, str: "TESTTESTTEST"});
-assert.eq(1, rstConn1.getDB("test").a.find().itcount(), "Error interacting with replSet");
+// Make administrative user other than local.__system
+rst.getPrimary().getDB("admin").createUser({user: "root", pwd: "pwd", roles: ["root"]},
+ {w: NUM_NODES});
+
+let entriesWritten = 0;
+function testWrite(str) {
+ const entry = ++entriesWritten;
+
+ const conn = rst.getPrimary();
+ assert(conn.getDB('admin').auth('root', 'pwd'));
+ const test = conn.getDB('test');
+ assert.writeOK(test.a.insert({a: entry, str: str}));
+ assert.eq(entry, test.a.find().itcount(), "Error interacting with replSet");
+}
+
+function authAllNodes(nodes) {
+ for (let n = 0; n < nodes.length; n++) {
+ assert(rst.nodes[n].getDB("admin").auth("root", "pwd"));
+ }
+}
+
+function upgradeAndWrite(newOpts, str) {
+ authAllNodes(rst.nodes);
+ rst.upgradeSet(newOpts, 'root', 'pwd');
+ authAllNodes(rst.nodes);
+ rst.awaitReplication();
+ testWrite(str);
+}
+
+function upgradeWriteAndConnect(newOpts, str) {
+ upgradeAndWrite(newOpts, str);
+
+ assert.eq(0,
+ runMongoProgram("mongo",
+ "--port",
+ rst.ports[0],
+ "--ssl",
+ "--sslAllowInvalidCertificates",
+ "--sslPEMKeyFile",
+ CLIENT_CERT,
+ "--eval",
+ ";"),
+ "SSL Connection attempt failed when it should succeed");
+}
-print("===== UPGRADE disabled,keyFile -> allowSSL,sendKeyfile =====");
-authAllNodes();
-rst.upgradeSet({
+testWrite(rst.getPrimary(), 'TESTTESTTEST');
+
+jsTest.log("===== UPGRADE disabled,keyFile -> allowSSL,sendKeyfile =====");
+upgradeAndWrite({
sslMode: "allowSSL",
sslPEMKeyFile: SERVER_CERT,
sslAllowInvalidCertificates: "",
@@ -62,17 +93,10 @@ rst.upgradeSet({
keyFile: KEYFILE,
sslCAFile: CA_CERT
},
- "root",
- "pwd");
-authAllNodes();
-rst.awaitReplication();
-
-var rstConn2 = rst.getPrimary();
-rstConn2.getDB("test").a.insert({a: 2, str: "CHECKCHECKCHECK"});
-assert.eq(2, rstConn2.getDB("test").a.find().itcount(), "Error interacting with replSet");
+ 'CHECKCHECKCHECK');
-print("===== UPGRADE allowSSL,sendKeyfile -> preferSSL,sendX509 =====");
-rst.upgradeSet({
+jsTest.log("===== UPGRADE allowSSL,sendKeyfile -> preferSSL,sendX509 =====");
+upgradeWriteAndConnect({
sslMode: "preferSSL",
sslPEMKeyFile: SERVER_CERT,
sslAllowInvalidCertificates: "",
@@ -80,29 +104,11 @@ rst.upgradeSet({
keyFile: KEYFILE,
sslCAFile: CA_CERT
},
- "root",
- "pwd");
-authAllNodes();
-rst.awaitReplication();
-
-var rstConn3 = rst.getPrimary();
-rstConn3.getDB("test").a.insert({a: 3, str: "PEASandCARROTS"});
-assert.eq(3, rstConn3.getDB("test").a.find().itcount(), "Error interacting with replSet");
-
-var canConnectSSL = runMongoProgram("mongo",
- "--port",
- rst.ports[0],
- "--ssl",
- "--sslAllowInvalidCertificates",
- "--sslPEMKeyFile",
- CLIENT_CERT,
- "--eval",
- ";");
-assert.eq(0, canConnectSSL, "SSL Connection attempt failed when it should succeed");
-
-print("===== UPGRADE preferSSL,sendX509 -> preferSSL,x509 =====");
+ 'PEASandCARROTS');
+
+jsTest.log("===== UPGRADE preferSSL,sendX509 -> preferSSL,x509 =====");
// we cannot upgrade past preferSSL here because it will break the test client
-rst.upgradeSet({
+upgradeWriteAndConnect({
sslMode: "preferSSL",
sslPEMKeyFile: SERVER_CERT,
sslAllowInvalidCertificates: "",
@@ -110,24 +116,7 @@ rst.upgradeSet({
keyFile: KEYFILE,
sslCAFile: CA_CERT
},
- "root",
- "pwd");
-authAllNodes();
-rst.awaitReplication();
-var rstConn4 = rst.getPrimary();
-rstConn4.getDB("test").a.insert({a: 4, str: "BEEP BOOP"});
-rst.awaitReplication();
-assert.eq(4, rstConn4.getDB("test").a.find().itcount(), "Error interacting with replSet");
-
-// Test that an ssl connection can still be made
-var canConnectSSL = runMongoProgram("mongo",
- "--port",
- rst.ports[0],
- "--ssl",
- "--sslAllowInvalidCertificates",
- "--sslPEMKeyFile",
- CLIENT_CERT,
- "--eval",
- ";");
-assert.eq(0, canConnectSSL, "SSL Connection attempt failed when it should succeed");
+ 'BEEP BOOP');
+
rst.stopSet();
+})();
diff --git a/jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js b/jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js
index 17b6ab30f21..33513246931 100644
--- a/jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js
+++ b/jstests/ssl_x509/upgrade_noauth_to_x509_ssl.js
@@ -12,6 +12,8 @@
load('jstests/ssl/libs/ssl_helpers.js');
+TestData.disableImplicitSessions = true;
+
(function() {
'use strict';
var dbName = 'upgradeToX509';
@@ -47,10 +49,15 @@ assert.commandWorked(testDB.a.insert({a: 1, str: 'TESTTESTTEST'}));
assert.eq(2, testDB.a.count(), 'Error interacting with replSet');
print('=== UPGRADE transition to x509/preferSSL -> x509/requireSSL ===');
+
+// Pre-logout so that upgradeSet() can authenticate for itself.
+rst.nodes.forEach((node) => node.getDB('admin').logout());
rst.upgradeSet(x509RequireSSL, 'root', 'root');
-// upgradeSet leaves its connections logged in as root
-testDB = rst.getPrimary().getDB(dbName);
+// Reauth and commit one last write.
+const finalPrimary = rst.getPrimary();
+assert(finalPrimary.getDB('admin').auth('root', 'root'));
+testDB = finalPrimary.getDB(dbName);
assert.commandWorked(testDB.a.insert({a: 1, str: 'TESTTESTTEST'}));
assert.eq(3, testDB.a.count(), 'Error interacting with replSet');
diff --git a/src/mongo/db/auth/authorization_session_impl.cpp b/src/mongo/db/auth/authorization_session_impl.cpp
index 70fa0e11309..8c2be85d37c 100644
--- a/src/mongo/db/auth/authorization_session_impl.cpp
+++ b/src/mongo/db/auth/authorization_session_impl.cpp
@@ -206,40 +206,29 @@ Status AuthorizationSessionImpl::addAndAuthorizeUser(OperationContext* opCtx,
// This is the first authentication.
return;
}
+ invariant(userCount == 1);
- auto previousUser = _authenticatedUsers.lookupByDBName(userName.getDB());
- if (previousUser) {
- const auto& previousUserName = previousUser->getName();
- if (previousUserName.getUser() == userName.getUser()) {
- LOGV2_WARNING(5626700,
- "Client has attempted to reauthenticate as a single user",
- "user"_attr = userName);
- } else {
- LOGV2_WARNING(5626701,
- "Client has attempted to authenticate as multiple users on the "
- "same database",
- "previousUser"_attr = previousUserName,
- "user"_attr = userName);
- }
- } else {
- LOGV2_WARNING(5626702,
- "Client has attempted to authenticate on multiple databases",
- "previousUsers"_attr = _authenticatedUsers.toBSON(),
+ auto previousUser = _authenticatedUsers.begin()->get()->getName();
+ if (previousUser == userName) {
+ // Allow reauthenticating as the same user, but warn.
+ LOGV2_WARNING(5626700,
+ "Client has attempted to reauthenticate as a single user",
"user"_attr = userName);
- }
-
- const auto hasStrictAPI = APIParameters::get(opCtx).getAPIStrict().value_or(false);
- if (!hasStrictAPI) {
- // We're allowed to skip the uassert because we're not so strict.
- return;
- }
- if (allowMultipleUsersWithApiStrict.shouldFail()) {
- // We've explicitly allowed this for testing.
- return;
+ // Strict API requires no reauth, even as same user, unless FP is enabled.
+ const bool hasStrictAPI = APIParameters::get(opCtx).getAPIStrict().value_or(false);
+ uassert(5626703,
+ "Each client connection may only be authenticated once",
+ !hasStrictAPI || allowMultipleUsersWithApiStrict.shouldFail());
+ } else {
+ uassert(5626701,
+ str::stream() << "Each client connection may only be authenticated once. "
+ << "Previously authenticated as: " << previousUser,
+ previousUser.getDB() == userName.getDB());
+ uasserted(5626702,
+ str::stream() << "Client has attempted to authenticate on multiple databases."
+ << "Already authenticated as: " << previousUser);
}
-
- uasserted(5626703, "Each client connection may only be authenticated once");
};
// Check before we start to reveal as little as possible. Note that we do not need the lock
@@ -394,6 +383,16 @@ RoleNameIterator AuthorizationSessionImpl::getAuthenticatedRoleNames() {
void AuthorizationSessionImpl::grantInternalAuthorization(Client* client) {
stdx::lock_guard<Client> lk(*client);
+ if (MONGO_unlikely(_authenticatedUsers.count() > 0)) {
+ invariant(_authenticatedUsers.count() == 1);
+ auto previousUser = _authenticatedUsers.begin()->get()->getName();
+ uassert(ErrorCodes::Unauthorized,
+ str::stream() << "Unable to grant internal authorization, previously authorized as "
+ << previousUser.getUnambiguousName(),
+ previousUser == internalSecurity.getUser()->get()->getName());
+ return;
+ }
+
_authenticatedUsers.add(*internalSecurity.getUser());
_updateInternalAuthorizationState();
}
diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp
index 51633ca828c..4ecb9cca692 100644
--- a/src/mongo/db/auth/authorization_session_test.cpp
+++ b/src/mongo/db/auth/authorization_session_test.cpp
@@ -116,6 +116,21 @@ public:
authzSession->logoutAllDatabases(_client.get(), "Ending AuthorizationSessionTest");
}
+ Status createUser(const UserName& username, const std::vector<RoleName>& roles) {
+ BSONObjBuilder userDoc;
+ userDoc.append("_id", username.getUnambiguousName());
+ username.appendToBSON(&userDoc);
+ userDoc.append("credentials", credentials);
+
+ BSONArrayBuilder rolesBSON(userDoc.subarrayStart("roles"));
+ for (const auto& role : roles) {
+ role.serializeToBSON(&rolesBSON);
+ }
+ rolesBSON.doneFast();
+
+ return managerState->insertPrivilegeDocument(_opCtx.get(), userDoc.obj(), {});
+ }
+
protected:
FailureCapableAuthzManagerExternalStateMock* managerState;
transport::TransportLayerMock transportLayer;
@@ -157,6 +172,37 @@ const ResourcePattern otherProfileCollResource(
const ResourcePattern thirdProfileCollResource(
ResourcePattern::forExactNamespace(NamespaceString("third.system.profile")));
+TEST_F(AuthorizationSessionTest, MultiAuthSameUserAllowed) {
+ authzSession->startContractTracking();
+
+ ASSERT_OK(createUser({"user1", "test"}, {}));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user1", "test"}));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user1", "test"}));
+ authzSession->logoutAllDatabases(_client.get(), "Test finished");
+}
+
+TEST_F(AuthorizationSessionTest, MultiAuthSameDBDisallowed) {
+ authzSession->startContractTracking();
+
+ ASSERT_OK(createUser({"user1", "test"}, {}));
+ ASSERT_OK(createUser({"user2", "test"}, {}));
+
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user1", "test"}));
+ ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user2", "test"}));
+ authzSession->logoutAllDatabases(_client.get(), "Test finished");
+}
+
+TEST_F(AuthorizationSessionTest, MultiAuthMultiDBDisallowed) {
+ authzSession->startContractTracking();
+
+ ASSERT_OK(createUser({"user", "test1"}, {}));
+ ASSERT_OK(createUser({"user", "test2"}, {}));
+
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user", "test1"}));
+ ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user", "test2"}));
+ authzSession->logoutAllDatabases(_client.get(), "Test finished");
+}
+
TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
authzSession->startContractTracking();
@@ -175,21 +221,7 @@ TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
// Add a user with readWrite and dbAdmin on the test DB
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "readWrite"
- << "db"
- << "test")
- << BSON("role"
- << "dbAdmin"
- << "db"
- << "test"))),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
ASSERT_TRUE(
@@ -198,20 +230,10 @@ TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
authzSession->isAuthorizedForActionsOnResource(testDBResource, ActionType::dbStats));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
// Add an admin user with readWriteAnyDatabase
- ASSERT_OK(
- managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "admin"
- << "db"
- << "admin"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "readWriteAnyDatabase"
- << "db"
- << "admin"))),
- BSONObj()));
+ ASSERT_OK(createUser({"admin", "admin"}, {{"readWriteAnyDatabase", "admin"}}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "admin")));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
@@ -226,7 +248,6 @@ TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
- authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
ASSERT_TRUE(
@@ -265,25 +286,8 @@ TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
// Add a user with doubled-up readWrite and single dbAdmin on the test DB
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "readWrite"
- << "db"
- << "test")
- << BSON("role"
- << "dbAdmin"
- << "db"
- << "test")
- << BSON("role"
- << "readWrite"
- << "db"
- << "test"))),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"},
+ {{"readWrite", "test"}, {"dbAdmin", "test"}, {"readWrite", "test"}}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
ASSERT_TRUE(
@@ -292,63 +296,15 @@ TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
authzSession->isAuthorizedForActionsOnResource(testDBResource, ActionType::dbStats));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "rw"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "readWrite"
- << "db"
- << "test")
- << BSON("role"
- << "dbAdmin"
- << "db"
- << "test"))),
- BSONObj()));
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "useradmin"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "userAdmin"
- << "db"
- << "test"))),
- BSONObj()));
- ASSERT_OK(
- managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "rwany"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "readWriteAnyDatabase"
- << "db"
- << "admin")
- << BSON("role"
- << "dbAdminAnyDatabase"
- << "db"
- << "admin"))),
- BSONObj()));
- ASSERT_OK(
- managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "useradminany"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "userAdminAnyDatabase"
- << "db"
- << "admin"))),
- BSONObj()));
+ ASSERT_OK(createUser({"rw", "test"}, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
+ ASSERT_OK(createUser({"useradmin", "test"}, {{"userAdmin", "test"}}));
+ ASSERT_OK(createUser({"rwany", "test"},
+ {{"readWriteAnyDatabase", "admin"}, {"dbAdminAnyDatabase", "admin"}}));
+ ASSERT_OK(createUser({"useradminany", "test"}, {{"userAdminAnyDatabase", "admin"}}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("rwany", "test")));
@@ -364,8 +320,8 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
- // Logging in as useradminany@test implicitly logs out rwany@test.
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("useradminany", "test")));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
@@ -379,8 +335,8 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
- // Logging in as rw@test implicitly logs out useradminany@test.
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("rw", "test")));
ASSERT_FALSE(
@@ -395,9 +351,8 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
-
- // Logging in as useradmin@test implicitly logs out rw@test.
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("useradmin", "test")));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
@@ -411,21 +366,12 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest, InvalidateUser) {
// Add a readWrite user
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "readWrite"
- << "db"
- << "test"))),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
ASSERT_TRUE(
@@ -442,17 +388,7 @@ TEST_F(AuthorizationSessionTest, InvalidateUser) {
BSONObj(),
BSONObj(),
&ignored));
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "read"
- << "db"
- << "test"))),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"}, {{"read", "test"}}));
// Make sure that invalidating the user causes the session to reload its privileges.
authzManager->invalidateUserByName(_opCtx.get(), user->getName());
@@ -478,21 +414,12 @@ TEST_F(AuthorizationSessionTest, InvalidateUser) {
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
ASSERT_FALSE(authzSession->lookupUser(UserName("spencer", "test")));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
// Add a readWrite user
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "readWrite"
- << "db"
- << "test"))),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
ASSERT_TRUE(
@@ -510,17 +437,7 @@ TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
BSONObj(),
BSONObj(),
&ignored));
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSON_ARRAY(BSON("role"
- << "read"
- << "db"
- << "test"))),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"}, {{"read", "test"}}));
// Even though the user's privileges have been reduced, since we've configured user
// document lookup to fail, the authz session should continue to use its known out-of-date
@@ -540,6 +457,7 @@ TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest, AcquireUserObtainsAndValidatesAuthenticationRestrictions) {
@@ -574,6 +492,7 @@ TEST_F(AuthorizationSessionTest, AcquireUserObtainsAndValidatesAuthenticationRes
SockAddr::create(clientSource, 5555, AF_UNSPEC),
SockAddr::create(serverAddress, 27017, AF_UNSPEC)));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
};
auto assertFails = [this](StringData clientSource, StringData serverAddress) {
@@ -1158,113 +1077,23 @@ TEST_F(AuthorizationSessionTest,
}
TEST_F(AuthorizationSessionTest, AuthorizedSessionIsNotCoauthorizedWithEmptyUserSet) {
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"}, {}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
std::vector<UserName> userSet;
ASSERT_FALSE(
authzSession->isCoauthorizedWith(makeUserNameIterator(userSet.begin(), userSet.end())));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest,
AuthorizedSessionIsCoauthorizedWithEmptyUserSetWhenAuthIsDisabled) {
authzManager->setAuthEnabled(false);
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
- std::vector<UserName> userSet;
- ASSERT_TRUE(
- authzSession->isCoauthorizedWith(makeUserNameIterator(userSet.begin(), userSet.end())));
-}
-
-TEST_F(AuthorizationSessionTest, AuthorizedSessionIsCoauthorizedWithIntersectingUserSet) {
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "admin"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "test")));
- std::vector<UserName> userSet;
- userSet.emplace_back("admin", "test");
- userSet.emplace_back("tess", "test");
- ASSERT_TRUE(
- authzSession->isCoauthorizedWith(makeUserNameIterator(userSet.begin(), userSet.end())));
-}
-
-TEST_F(AuthorizationSessionTest, AuthorizedSessionIsNotCoauthorizedWithNonintersectingUserSet) {
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "admin"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "test")));
- std::vector<UserName> userSet;
- userSet.emplace_back("tess", "test");
- ASSERT_FALSE(
- authzSession->isCoauthorizedWith(makeUserNameIterator(userSet.begin(), userSet.end())));
-}
-
-TEST_F(AuthorizationSessionTest,
- AuthorizedSessionIsCoauthorizedWithNonintersectingUserSetWhenAuthIsDisabled) {
- authzManager->setAuthEnabled(false);
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "spencer"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
- ASSERT_OK(managerState->insertPrivilegeDocument(_opCtx.get(),
- BSON("user"
- << "admin"
- << "db"
- << "test"
- << "credentials" << credentials << "roles"
- << BSONArray()),
- BSONObj()));
+ ASSERT_OK(createUser({"spencer", "test"}, {}));
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test")));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "test")));
std::vector<UserName> userSet;
- userSet.emplace_back("tess", "test");
ASSERT_TRUE(
authzSession->isCoauthorizedWith(makeUserNameIterator(userSet.begin(), userSet.end())));
+ authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest, CannotListCollectionsWithoutListCollectionsPrivilege) {
@@ -1661,6 +1490,8 @@ TEST_F(AuthorizationSessionTest, MayBypassWriteBlockingModeIsSetCorrectly) {
<< "db"
<< "admin"))),
BSONObj()));
+ authzSession->logoutDatabase(_client.get(), "test", "End of test");
+
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("gmarks", "admin")));
ASSERT_TRUE(authzSession->mayBypassWriteBlockingMode());
@@ -1681,6 +1512,8 @@ TEST_F(AuthorizationSessionTest, MayBypassWriteBlockingModeIsSetCorrectly) {
<< "db"
<< "admin"))),
BSONObj()));
+ authzSession->logoutDatabase(_client.get(), "admin", "");
+
ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "admin")));
ASSERT_TRUE(authzSession->mayBypassWriteBlockingMode());
diff --git a/src/mongo/db/logical_session_id_test.cpp b/src/mongo/db/logical_session_id_test.cpp
index 4585b419dd8..a54fc2316d7 100644
--- a/src/mongo/db/logical_session_id_test.cpp
+++ b/src/mongo/db/logical_session_id_test.cpp
@@ -272,20 +272,6 @@ TEST_F(LogicalSessionIdTest, GenWithUser) {
ASSERT_EQ(lsid.getUid(), user->getDigest());
}
-TEST_F(LogicalSessionIdTest, GenWithMultipleAuthedUsers) {
- addSimpleUser(UserName("simple", "test"));
- addSimpleUser(UserName("simple", "test2"));
-
- ASSERT_THROWS_WITH_CHECK(makeLogicalSessionId(_opCtx.get()),
- AssertionException,
- [](const AssertionException& exception) {
- ASSERT_EQ(exception.code(), ErrorCodes::Unauthorized);
- ASSERT_STRING_CONTAINS(
- exception.reason(),
- "docs.mongodb.com/manual/core/authentication");
- });
-}
-
TEST_F(LogicalSessionIdTest, GenWithoutAuthedUser) {
ASSERT_THROWS(makeLogicalSessionId(_opCtx.get()), AssertionException);
}
@@ -461,22 +447,5 @@ TEST_F(LogicalSessionIdTest, ConstructorFromClientWithTooLongName) {
ASSERT_THROWS(makeLogicalSessionId(req, _opCtx.get()), AssertionException);
}
-TEST_F(LogicalSessionIdTest, MultipleUsersPerSessionIsNotAllowed) {
- addSimpleUser(UserName("simple", "test"));
- addSimpleUser(UserName("simple", "test2"));
-
- LogicalSessionFromClient lsid;
- lsid.setId(UUID::gen());
-
- ASSERT_THROWS_CODE(initializeOperationSessionInfo(
- _opCtx.get(),
- BSON("TestCmd" << 1 << "lsid" << lsid.toBSON() << "txnNumber" << 100LL),
- true,
- true,
- true),
- AssertionException,
- ErrorCodes::Unauthorized);
-}
-
} // namespace
} // namespace mongo
diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js
index 6379f2c81b3..b101d022f1e 100644
--- a/src/mongo/shell/replsettest.js
+++ b/src/mongo/shell/replsettest.js
@@ -187,7 +187,7 @@ var ReplSetTest = function(opts) {
* assume that it already has the correct privileges. It is up to the caller of this function to
* ensure that the connection is appropriately authenticated.
*/
- function asCluster(conn, fn, keyFileParam = self.keyFile) {
+ function asCluster(conn, fn, keyFileParam = undefined) {
let connArray = conn;
if (conn.length == null)
connArray = [conn];
@@ -202,6 +202,7 @@ var ReplSetTest = function(opts) {
const authMode = connOptions.clusterAuthMode || connArray[0].clusterAuthMode ||
jsTest.options().clusterAuthMode;
+ keyFileParam = keyFileParam || connOptions.keyFile || self.keyFile;
let needsAuth = (keyFileParam || authMode === "x509" || authMode === "sendX509" ||
authMode === "sendKeyFile") &&
unauthenticatedConns.length > 0;
@@ -356,6 +357,11 @@ var ReplSetTest = function(opts) {
if (!conn)
return false;
+ if (reconnectNode instanceof Function) {
+ // Allow caller to perform tasks on reconnect.
+ reconnectNode(conn);
+ }
+
asCluster(conn, function() {
status = conn.getDB('admin').runCommand({replSetGetStatus: 1});
});
@@ -364,6 +370,11 @@ var ReplSetTest = function(opts) {
return false;
}
+ if (status.code == ErrorCodes.Unauthorized) {
+ // If we're not authorized already, then we never will be.
+ assert.commandWorked(status); // throws
+ }
+
var printStatus = false;
if (lastTime == null || (currTime = new Date().getTime()) - (1000 * 5) > lastTime) {
if (lastTime == null) {