summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/auth/SConscript1
-rw-r--r--src/mongo/db/auth/authorization_manager.h6
-rw-r--r--src/mongo/db/auth/authorization_manager_impl.cpp86
-rw-r--r--src/mongo/db/auth/authorization_manager_impl.h3
-rw-r--r--src/mongo/db/auth/authorization_manager_test.cpp53
-rw-r--r--src/mongo/db/auth/authorization_session.h2
-rw-r--r--src/mongo/db/auth/authorization_session_for_test.cpp3
-rw-r--r--src/mongo/db/auth/authorization_session_impl.cpp6
-rw-r--r--src/mongo/db/auth/authorization_session_impl.h2
-rw-r--r--src/mongo/db/auth/authorization_session_test.cpp164
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.cpp2
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_s.cpp2
-rw-r--r--src/mongo/db/auth/sasl_commands.cpp4
-rw-r--r--src/mongo/db/auth/sasl_mechanism_registry.cpp3
-rw-r--r--src/mongo/db/auth/sasl_mechanism_registry.h7
-rw-r--r--src/mongo/db/auth/sasl_mechanism_registry_test.cpp3
-rw-r--r--src/mongo/db/auth/sasl_plain_server_conversation.cpp3
-rw-r--r--src/mongo/db/auth/sasl_scram_server_conversation.cpp2
-rw-r--r--src/mongo/db/auth/security_key_test.cpp3
-rw-r--r--src/mongo/db/auth/security_token_authentication_guard.cpp4
-rw-r--r--src/mongo/db/auth/user.cpp10
-rw-r--r--src/mongo/db/auth/user.h83
-rw-r--r--src/mongo/db/auth/user_document_parser_test.cpp4
-rw-r--r--src/mongo/db/auth/validated_tenancy_scope_test.cpp2
-rw-r--r--src/mongo/db/commands/SConscript1
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp37
-rw-r--r--src/mongo/db/commands/authentication_commands.h3
-rw-r--r--src/mongo/db/commands/user_management_commands.cpp5
-rw-r--r--src/mongo/db/commands_test.cpp15
-rw-r--r--src/mongo/db/session/SConscript1
-rw-r--r--src/mongo/db/session/kill_sessions.cpp8
-rw-r--r--src/mongo/db/session/logical_session_id_test.cpp4
-rw-r--r--src/mongo/embedded/embedded_auth_manager.cpp2
-rw-r--r--src/mongo/embedded/embedded_auth_session.cpp2
-rw-r--r--src/mongo/rpc/op_msg_test.cpp2
-rw-r--r--src/mongo/util/net/network_interface_ssl_test.cpp3
36 files changed, 305 insertions, 236 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index 09f7d8e3cc9..0d23ae77bd4 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -199,6 +199,7 @@ env.Library(
LIBDEPS=[
'$BUILD_DIR/mongo/base/secure_allocator',
'$BUILD_DIR/mongo/bson/util/bson_extract',
+ '$BUILD_DIR/mongo/db/commands/authentication_commands',
'$BUILD_DIR/mongo/db/common',
'$BUILD_DIR/mongo/db/curop',
'$BUILD_DIR/mongo/db/global_settings',
diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h
index a23905406da..bdcfba3a7b7 100644
--- a/src/mongo/db/auth/authorization_manager.h
+++ b/src/mongo/db/auth/authorization_manager.h
@@ -316,14 +316,14 @@ public:
std::vector<BSONObj>* result) = 0;
/**
- * Returns a Status or UserHandle for the given userName. If the user cache already has a
+ * Returns a Status or UserHandle for the given userRequest. If the user cache already has a
* user object for this user, it returns a handle from the cache, otherwise it reads the
- * user document from disk or LDAP - this may block for a long time.
+ * user document from the AuthzManagerExternalState - this may block for a long time.
*
* The returned user may be invalid by the time the caller gets access to it.
*/
virtual StatusWith<UserHandle> acquireUser(OperationContext* opCtx,
- const UserName& userName) = 0;
+ const UserRequest& userRequest) = 0;
/**
* Validate the ID associated with a known user while refreshing session cache.
diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp
index 6b95652f6bb..0da6eeef244 100644
--- a/src/mongo/db/auth/authorization_manager_impl.cpp
+++ b/src/mongo/db/auth/authorization_manager_impl.cpp
@@ -51,6 +51,7 @@
#include "mongo/db/auth/sasl_options.h"
#include "mongo/db/auth/user_document_parser.h"
#include "mongo/db/auth/user_management_commands_parser.h"
+#include "mongo/db/commands/authentication_commands.h"
#include "mongo/db/curop.h"
#include "mongo/db/global_settings.h"
#include "mongo/db/mongod_options.h"
@@ -68,7 +69,8 @@ namespace mongo {
namespace {
std::shared_ptr<UserHandle> createSystemUserHandle() {
- auto user = std::make_shared<UserHandle>(User(UserName("__system", "local")));
+ UserRequest request(UserName("__system", "local"), boost::none);
+ auto user = std::make_shared<UserHandle>(User(std::move(request)));
ActionSet allActions;
allActions.addAllActions();
@@ -284,29 +286,6 @@ bool appliesToAuthzData(StringData op, const NamespaceString& nss, const BSONObj
}
}
-/**
- * Returns true if roles for this user were provided by the client, and can be obtained from
- * the connection.
- */
-bool shouldUseRolesFromConnection(OperationContext* opCtx, const UserName& userName) {
-#ifdef MONGO_CONFIG_SSL
- if (!opCtx || !opCtx->getClient() || !opCtx->getClient()->session()) {
- return false;
- }
-
- if (!allowRolesFromX509Certificates) {
- return false;
- }
-
- auto& sslPeerInfo = SSLPeerInfo::forSession(opCtx->getClient()->session());
- return sslPeerInfo.subjectName.toString() == userName.getUser() &&
- userName.getDB() == "$external"_sd && !sslPeerInfo.roles.empty();
-#else
- return false;
-#endif
-}
-
-
std::unique_ptr<AuthorizationManager> authorizationManagerCreateImpl(
ServiceContext* serviceContext) {
return std::make_unique<AuthorizationManagerImpl>(serviceContext,
@@ -527,26 +506,24 @@ MONGO_FAIL_POINT_DEFINE(authUserCacheSleep);
} // namespace
StatusWith<UserHandle> AuthorizationManagerImpl::acquireUser(OperationContext* opCtx,
- const UserName& userName) try {
+ const UserRequest& request) try {
+ const auto& userName = request.name;
+
auto systemUser = internalSecurity.getUser();
if (userName == (*systemUser)->getName()) {
+ uassert(ErrorCodes::OperationFailed,
+ "Attempted to acquire system user with predefined roles",
+ request.roles == boost::none);
return *systemUser;
}
- UserRequest request(userName, boost::none);
-
+ UserRequest userRequest(request);
#ifdef MONGO_CONFIG_SSL
- // Clients connected via TLS may present an X.509 certificate which contains an authorization
- // grant. If this is the case, the roles must be provided to the external state, for expansion
- // into privileges.
- if (shouldUseRolesFromConnection(opCtx, userName)) {
- auto& sslPeerInfo = SSLPeerInfo::forSession(opCtx->getClient()->session());
- request.roles = std::set<RoleName>();
-
- // In order to be hashable, the role names must be converted from unordered_set to a set.
- std::copy(sslPeerInfo.roles.begin(),
- sslPeerInfo.roles.end(),
- std::inserter(*request.roles, request.roles->begin()));
+ // X.509 will give us our roles for initial acquire, but we have to lose them during
+ // reacquire (for now) so reparse those roles into the request if not already present.
+ if ((request.roles == boost::none) && request.mechanismData.empty() &&
+ (userName.getDB() == "$external"_sd)) {
+ userRequest = getX509UserRequest(opCtx, std::move(userRequest));
}
#endif
@@ -571,7 +548,7 @@ StatusWith<UserHandle> AuthorizationManagerImpl::acquireUser(OperationContext* o
sleepsecs(1);
}
- auto cachedUser = _userCache.acquire(opCtx, request);
+ auto cachedUser = _userCache.acquire(opCtx, userRequest);
userAcquisitionStatsHandle.recordTimerEnd();
invariant(cachedUser);
@@ -592,7 +569,7 @@ StatusWith<UserHandle> AuthorizationManagerImpl::reacquireUser(OperationContext*
// Make a good faith effort to acquire an up-to-date user object, since the one
// we've cached is marked "out-of-date."
- auto swUserHandle = acquireUser(opCtx, userName);
+ auto swUserHandle = acquireUser(opCtx, UserRequest(userName, boost::none));
if (!swUserHandle.isOK()) {
return swUserHandle.getStatus();
}
@@ -678,6 +655,18 @@ void AuthorizationManagerImpl::_pinnedUsersThreadRoutine() noexcept try {
}
}
+ // Find UserRequests for UserNames we need to pin if they exist in the cache.
+ std::map<UserName, UserRequest> pinNow;
+ _userCache.peekLatestCachedIf([&](const UserRequest& request, const User& user) {
+ if (std::any_of(usersToPin.begin(), usersToPin.end(), [&](const auto& userName) {
+ return user.getName() == userName;
+ })) {
+ pinNow.emplace(request.name, request);
+ }
+ // Don't need any output vector.
+ return false;
+ });
+
for (const auto& userName : usersToPin) {
if (std::any_of(pinnedUsers.begin(), pinnedUsers.end(), [&](const auto& user) {
return user->getName() == userName;
@@ -685,7 +674,22 @@ void AuthorizationManagerImpl::_pinnedUsersThreadRoutine() noexcept try {
continue;
}
- auto swUser = acquireUser(opCtx.get(), userName);
+ auto request = ([&] {
+ if (auto it = pinNow.find(userName); it != pinNow.end()) {
+ return it->second;
+ }
+ return UserRequest(userName, boost::none);
+ })();
+
+ if (!request.mechanismData.empty()) {
+ LOGV2_DEBUG(7070000,
+ 2,
+ "Refusing to pin user with mechanism metadata",
+ "user"_attr = request.name);
+ continue;
+ }
+
+ auto swUser = acquireUser(opCtx.get(), request);
if (swUser.isOK()) {
LOGV2_DEBUG(20232, 2, "Pinned user", "user"_attr = userName);
diff --git a/src/mongo/db/auth/authorization_manager_impl.h b/src/mongo/db/auth/authorization_manager_impl.h
index 0cb99f041f9..db7fd95b70d 100644
--- a/src/mongo/db/auth/authorization_manager_impl.h
+++ b/src/mongo/db/auth/authorization_manager_impl.h
@@ -101,7 +101,8 @@ public:
bool showBuiltinRoles,
std::vector<BSONObj>* result) override;
- StatusWith<UserHandle> acquireUser(OperationContext* opCtx, const UserName& userName) override;
+ StatusWith<UserHandle> acquireUser(OperationContext* opCtx,
+ const UserRequest& userRequest) override;
StatusWith<UserHandle> reacquireUser(OperationContext* opCtx, const UserHandle& user) override;
/**
diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp
index f91f3f0a329..3363aead426 100644
--- a/src/mongo/db/auth/authorization_manager_test.cpp
+++ b/src/mongo/db/auth/authorization_manager_test.cpp
@@ -140,7 +140,7 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) {
<< "admin"))),
BSONObj()));
- auto swu = authzManager->acquireUser(opCtx.get(), UserName("v2read", "test"));
+ auto swu = authzManager->acquireUser(opCtx.get(), {{"v2read", "test"}, boost::none});
ASSERT_OK(swu.getStatus());
auto v2read = std::move(swu.getValue());
ASSERT_EQUALS(UserName("v2read", "test"), v2read->getName());
@@ -153,7 +153,7 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) {
ASSERT(testDBPrivilege.getActions().contains(ActionType::find));
// Make sure user's refCount is 0 at the end of the test to avoid an assertion failure
- swu = authzManager->acquireUser(opCtx.get(), UserName("v2cluster", "admin"));
+ swu = authzManager->acquireUser(opCtx.get(), {{"v2cluster", "admin"}, boost::none});
ASSERT_OK(swu.getStatus());
auto v2cluster = std::move(swu.getValue());
ASSERT_EQUALS(UserName("v2cluster", "admin"), v2cluster->getName());
@@ -169,24 +169,19 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) {
#ifdef MONGO_CONFIG_SSL
TEST_F(AuthorizationManagerTest, testLocalX509Authorization) {
- setX509PeerInfo(session,
- SSLPeerInfo(buildX509Name(),
- boost::none,
- {RoleName("read", "test"), RoleName("readWrite", "test")}));
+ std::set<RoleName> roles({{"read", "test"}, {"readWrite", "test"}});
+ UserRequest request(UserName("CN=mongodb.com", "$external"), roles);
- auto swu = authzManager->acquireUser(opCtx.get(), UserName("CN=mongodb.com", "$external"));
+ auto swu = authzManager->acquireUser(opCtx.get(), request);
ASSERT_OK(swu.getStatus());
auto x509User = std::move(swu.getValue());
ASSERT(x509User.isValid());
- stdx::unordered_set<RoleName> expectedRoles{RoleName("read", "test"),
- RoleName("readWrite", "test")};
- RoleNameIterator roles = x509User->getRoles();
- stdx::unordered_set<RoleName> acquiredRoles;
- while (roles.more()) {
- acquiredRoles.insert(roles.next());
+ std::set<RoleName> gotRoles;
+ for (auto it = x509User->getRoles(); it.more();) {
+ gotRoles.emplace(it.next());
}
- ASSERT_TRUE(expectedRoles == acquiredRoles);
+ ASSERT_TRUE(roles == gotRoles);
const User::ResourcePrivilegeMap& privileges = x509User->getPrivileges();
ASSERT_FALSE(privileges.empty());
@@ -202,14 +197,16 @@ TEST_F(AuthorizationManagerTest, testLocalX509AuthorizationInvalidUser) {
{RoleName("read", "test"), RoleName("write", "test")}));
ASSERT_NOT_OK(
- authzManager->acquireUser(opCtx.get(), UserName("CN=10gen.com", "$external")).getStatus());
+ authzManager->acquireUser(opCtx.get(), {{"CN=10gen.com", "$external"}, boost::none})
+ .getStatus());
}
TEST_F(AuthorizationManagerTest, testLocalX509AuthenticationNoAuthorization) {
setX509PeerInfo(session, {});
- ASSERT_NOT_OK(authzManager->acquireUser(opCtx.get(), UserName("CN=mongodb.com", "$external"))
- .getStatus());
+ ASSERT_NOT_OK(
+ authzManager->acquireUser(opCtx.get(), {{"CN=mongodb.com", "$external"}, boost::none})
+ .getStatus());
}
#endif
@@ -240,7 +237,7 @@ TEST_F(AuthorizationManagerTest, testAcquireV2UserWithUnrecognizedActions) {
<< "insert")))),
BSONObj()));
- auto swu = authzManager->acquireUser(opCtx.get(), UserName("myUser", "test"));
+ auto swu = authzManager->acquireUser(opCtx.get(), {{"myUser", "test"}, boost::none});
ASSERT_OK(swu.getStatus());
auto myUser = std::move(swu.getValue());
ASSERT_EQUALS(UserName("myUser", "test"), myUser->getName());
@@ -317,14 +314,12 @@ TEST_F(AuthorizationManagerTest, testRefreshExternalV2User) {
std::vector<UserHandle> checkedOutUsers;
checkedOutUsers.reserve(userDocs.size());
for (const auto& userDoc : userDocs) {
- auto swUser = authzManager->acquireUser(
- opCtx.get(),
- UserName(userDoc.getStringField(kUserFieldName), userDoc.getStringField(kDbFieldName)));
+ const UserName userName(userDoc.getStringField(kUserFieldName),
+ userDoc.getStringField(kDbFieldName));
+ auto swUser = authzManager->acquireUser(opCtx.get(), {userName, boost::none});
ASSERT_OK(swUser.getStatus());
auto user = std::move(swUser.getValue());
- ASSERT_EQUALS(
- UserName(userDoc.getStringField(kUserFieldName), userDoc.getStringField(kDbFieldName)),
- user->getName());
+ ASSERT_EQUALS(userName, user->getName());
ASSERT(user.isValid());
RoleNameIterator cachedUserRoles = user->getRoles();
@@ -364,14 +359,12 @@ TEST_F(AuthorizationManagerTest, testRefreshExternalV2User) {
// Retrieve all users from the cache and verify that only the external ones contain the newly
// added role.
for (const auto& userDoc : userDocs) {
- auto swUser = authzManager->acquireUser(
- opCtx.get(),
- UserName(userDoc.getStringField(kUserFieldName), userDoc.getStringField(kDbFieldName)));
+ const UserName userName(userDoc.getStringField(kUserFieldName),
+ userDoc.getStringField(kDbFieldName));
+ auto swUser = authzManager->acquireUser(opCtx.get(), {userName, boost::none});
ASSERT_OK(swUser.getStatus());
auto user = std::move(swUser.getValue());
- ASSERT_EQUALS(
- UserName(userDoc.getStringField(kUserFieldName), userDoc.getStringField(kDbFieldName)),
- user->getName());
+ ASSERT_EQUALS(userName, user->getName());
ASSERT(user.isValid());
RoleNameIterator cachedUserRolesIt = user->getRoles();
diff --git a/src/mongo/db/auth/authorization_session.h b/src/mongo/db/auth/authorization_session.h
index 72d107e5253..4c63ebeb1e6 100644
--- a/src/mongo/db/auth/authorization_session.h
+++ b/src/mongo/db/auth/authorization_session.h
@@ -145,7 +145,7 @@ public:
* for it in the process.
*/
virtual Status addAndAuthorizeUser(OperationContext* opCtx,
- const UserName& userName,
+ const UserRequest& userRequest,
boost::optional<Date_t> expirationTime) = 0;
// Returns the authenticated user with the given name. Returns NULL
diff --git a/src/mongo/db/auth/authorization_session_for_test.cpp b/src/mongo/db/auth/authorization_session_for_test.cpp
index 620716c5e4f..e88dd65ebc4 100644
--- a/src/mongo/db/auth/authorization_session_for_test.cpp
+++ b/src/mongo/db/auth/authorization_session_for_test.cpp
@@ -48,7 +48,8 @@ void AuthorizationSessionForTest::assumePrivilegesForDB(Privilege privilege, Str
void AuthorizationSessionForTest::assumePrivilegesForDB(PrivilegeVector privileges,
StringData dbName) {
- _authenticatedUser = UserHandle(User(UserName("authorizationSessionForTestUser", dbName)));
+ UserRequest request(UserName("authorizationSessionForTestUser"_sd, dbName), boost::none);
+ _authenticatedUser = UserHandle(User(request));
_authenticatedUser.value()->addPrivileges(privileges);
_authenticationMode = AuthorizationSession::AuthenticationMode::kConnection;
_updateInternalAuthorizationState();
diff --git a/src/mongo/db/auth/authorization_session_impl.cpp b/src/mongo/db/auth/authorization_session_impl.cpp
index 981e3649bdd..a95df5f97ea 100644
--- a/src/mongo/db/auth/authorization_session_impl.cpp
+++ b/src/mongo/db/auth/authorization_session_impl.cpp
@@ -210,8 +210,10 @@ void AuthorizationSessionImpl::startContractTracking() {
}
Status AuthorizationSessionImpl::addAndAuthorizeUser(OperationContext* opCtx,
- const UserName& userName,
+ const UserRequest& userRequest,
boost::optional<Date_t> expirationTime) try {
+ const auto& userName = userRequest.name;
+
// Check before we start to reveal as little as possible. Note that we do not need the lock
// because only the Client thread can mutate _authenticatedUser.
if (_authenticatedUser) {
@@ -253,7 +255,7 @@ Status AuthorizationSessionImpl::addAndAuthorizeUser(OperationContext* opCtx,
}
AuthorizationManager* authzManager = AuthorizationManager::get(opCtx->getServiceContext());
- auto user = uassertStatusOK(authzManager->acquireUser(opCtx, userName));
+ auto user = uassertStatusOK(authzManager->acquireUser(opCtx, userRequest));
auto restrictionStatus = user->validateRestrictions(opCtx);
if (!restrictionStatus.isOK()) {
diff --git a/src/mongo/db/auth/authorization_session_impl.h b/src/mongo/db/auth/authorization_session_impl.h
index fc8a903ac59..7aab611d2c2 100644
--- a/src/mongo/db/auth/authorization_session_impl.h
+++ b/src/mongo/db/auth/authorization_session_impl.h
@@ -77,7 +77,7 @@ public:
void startContractTracking() override;
Status addAndAuthorizeUser(OperationContext* opCtx,
- const UserName& userName,
+ const UserRequest& userRequest,
boost::optional<Date_t> expirationTime) override;
User* lookupUser(const UserName& name) override;
diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp
index 0241901ee41..4f5b6a7c1f6 100644
--- a/src/mongo/db/auth/authorization_session_test.cpp
+++ b/src/mongo/db/auth/authorization_session_test.cpp
@@ -226,31 +226,42 @@ const ResourcePattern otherProfileCollResource(
const ResourcePattern thirdProfileCollResource(
ResourcePattern::forExactNamespace(NamespaceString("third.system.profile")));
+const UserName kUser1Test("user1"_sd, "test"_sd);
+const UserRequest kUser1TestRequest(kUser1Test, boost::none);
+const UserName kUser2Test("user2"_sd, "test"_sd);
+const UserRequest kUser2TestRequest(kUser2Test, boost::none);
+
TEST_F(AuthorizationSessionTest, MultiAuthSameUserAllowed) {
- ASSERT_OK(createUser({"user1", "test"}, {}));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user1", "test"}, boost::none));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user1", "test"}, boost::none));
+ ASSERT_OK(createUser(kUser1Test, {}));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kUser1TestRequest, boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kUser1TestRequest, boost::none));
authzSession->logoutAllDatabases(_client.get(), "Test finished");
}
TEST_F(AuthorizationSessionTest, MultiAuthSameDBDisallowed) {
- ASSERT_OK(createUser({"user1", "test"}, {}));
- ASSERT_OK(createUser({"user2", "test"}, {}));
+ ASSERT_OK(createUser(kUser1Test, {}));
+ ASSERT_OK(createUser(kUser2Test, {}));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user1", "test"}, boost::none));
- ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user2", "test"}, boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kUser1TestRequest, boost::none));
+ ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kUser2TestRequest, boost::none));
authzSession->logoutAllDatabases(_client.get(), "Test finished");
}
TEST_F(AuthorizationSessionTest, MultiAuthMultiDBDisallowed) {
- ASSERT_OK(createUser({"user", "test1"}, {}));
- ASSERT_OK(createUser({"user", "test2"}, {}));
+ ASSERT_OK(createUser(kUser1Test, {}));
+ ASSERT_OK(createUser(kUser2Test, {}));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user", "test1"}, boost::none));
- ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {"user", "test2"}, boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kUser1TestRequest, boost::none));
+ ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kUser2TestRequest, boost::none));
authzSession->logoutAllDatabases(_client.get(), "Test finished");
}
+const UserName kSpencerTest("spencer"_sd, "test"_sd);
+const UserRequest kSpencerTestRequest(kSpencerTest, boost::none);
+
+const UserName kAdminAdmin("admin"_sd, "admin"_sd);
+const UserRequest kAdminAdminRequest(kAdminAdmin, boost::none);
+
TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
// Check that disabling auth checks works
ASSERT_FALSE(
@@ -265,12 +276,11 @@ TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
// Check that you can't authorize a user that doesn't exist.
ASSERT_EQUALS(
ErrorCodes::UserNotFound,
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
// Add a user with readWrite and dbAdmin on the test DB
ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
@@ -282,8 +292,7 @@ TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
// Add an admin user with readWriteAnyDatabase
ASSERT_OK(createUser({"admin", "admin"}, {{"readWriteAnyDatabase", "admin"}}));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "admin"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kAdminAdminRequest, boost::none));
ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
ResourcePattern::forExactNamespace(NamespaceString("anydb.somecollection")),
@@ -335,10 +344,9 @@ TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
// Add a user with doubled-up readWrite and single dbAdmin on the test DB
- ASSERT_OK(createUser({"spencer", "test"},
+ ASSERT_OK(createUser(kSpencerTest,
{{"readWrite", "test"}, {"dbAdmin", "test"}, {"readWrite", "test"}}));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
@@ -349,15 +357,24 @@ TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
+const UserName kRWTest("rw"_sd, "test"_sd);
+const UserName kUserAdminTest("useradmin"_sd, "test"_sd);
+const UserName kRWAnyTest("rwany"_sd, "test"_sd);
+const UserName kUserAdminAnyTest("useradminany"_sd, "test"_sd);
+
+const UserRequest kRWTestRequest(kRWTest, boost::none);
+const UserRequest kUserAdminTestRequest(kUserAdminTest, boost::none);
+const UserRequest kRWAnyTestRequest(kRWAnyTest, boost::none);
+const UserRequest kUserAdminAnyTestRequest(kUserAdminAnyTest, boost::none);
+
TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
- ASSERT_OK(createUser({"rw", "test"}, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
- ASSERT_OK(createUser({"useradmin", "test"}, {{"userAdmin", "test"}}));
- ASSERT_OK(createUser({"rwany", "test"},
+ ASSERT_OK(createUser(kRWTest, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
+ ASSERT_OK(createUser(kUserAdminTest, {{"userAdmin", "test"}}));
+ ASSERT_OK(createUser(kRWAnyTest,
{{"readWriteAnyDatabase", "admin"}, {"dbAdminAnyDatabase", "admin"}}));
- ASSERT_OK(createUser({"useradminany", "test"}, {{"userAdminAnyDatabase", "admin"}}));
+ ASSERT_OK(createUser(kUserAdminAnyTest, {{"userAdminAnyDatabase", "admin"}}));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("rwany", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kRWAnyTestRequest, boost::none));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
@@ -373,8 +390,8 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
- ASSERT_OK(authzSession->addAndAuthorizeUser(
- _opCtx.get(), UserName("useradminany", "test"), boost::none));
+ ASSERT_OK(
+ authzSession->addAndAuthorizeUser(_opCtx.get(), kUserAdminAnyTestRequest, boost::none));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
ASSERT_TRUE(
@@ -389,7 +406,7 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("rw", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kRWTestRequest, boost::none));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
@@ -405,8 +422,7 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
- ASSERT_OK(authzSession->addAndAuthorizeUser(
- _opCtx.get(), UserName("useradmin", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kUserAdminTestRequest, boost::none));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
ASSERT_FALSE(
@@ -424,16 +440,15 @@ TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
TEST_F(AuthorizationSessionTest, InvalidateUser) {
// Add a readWrite user
- ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}}));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_OK(createUser(kSpencerTest, {{"readWrite", "test"}}));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
- User* user = authzSession->lookupUser(UserName("spencer", "test"));
+ User* user = authzSession->lookupUser(kSpencerTest);
// Change the user to be read-only
int ignored;
@@ -442,7 +457,7 @@ TEST_F(AuthorizationSessionTest, InvalidateUser) {
BSONObj(),
BSONObj(),
&ignored));
- ASSERT_OK(createUser({"spencer", "test"}, {{"read", "test"}}));
+ ASSERT_OK(createUser(kSpencerTest, {{"read", "test"}}));
// Make sure that invalidating the user causes the session to reload its privileges.
authzManager->invalidateUserByName(_opCtx.get(), user->getName());
@@ -452,7 +467,7 @@ TEST_F(AuthorizationSessionTest, InvalidateUser) {
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
- user = authzSession->lookupUser(UserName("spencer", "test"));
+ user = authzSession->lookupUser(kSpencerTest);
// Delete the user.
ASSERT_OK(managerState->remove(_opCtx.get(),
@@ -467,22 +482,21 @@ TEST_F(AuthorizationSessionTest, InvalidateUser) {
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
ASSERT_FALSE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->lookupUser(UserName("spencer", "test")));
+ ASSERT_FALSE(authzSession->lookupUser(kSpencerTest));
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
// Add a readWrite user
ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}}));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
ASSERT_TRUE(
authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
- User* user = authzSession->lookupUser(UserName("spencer", "test"));
+ User* user = authzSession->lookupUser(kSpencerTest);
// Change the user to be read-only
int ignored;
@@ -492,7 +506,7 @@ TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
BSONObj(),
BSONObj(),
&ignored));
- ASSERT_OK(createUser({"spencer", "test"}, {{"read", "test"}}));
+ ASSERT_OK(createUser(kSpencerTest, {{"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
@@ -546,8 +560,8 @@ TEST_F(AuthorizationSessionTest, AcquireUserObtainsAndValidatesAuthenticationRes
std::make_unique<RestrictionEnvironment>(
SockAddr::create(clientSource, 5555, AF_UNSPEC),
SockAddr::create(serverAddress, 27017, AF_UNSPEC)));
- ASSERT_OK(authzSession->addAndAuthorizeUser(
- _opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_OK(
+ authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
};
@@ -556,13 +570,13 @@ TEST_F(AuthorizationSessionTest, AcquireUserObtainsAndValidatesAuthenticationRes
std::make_unique<RestrictionEnvironment>(
SockAddr::create(clientSource, 5555, AF_UNSPEC),
SockAddr::create(serverAddress, 27017, AF_UNSPEC)));
- ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(
- _opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_NOT_OK(
+ authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
};
// The empty RestrictionEnvironment will cause addAndAuthorizeUser to fail.
ASSERT_NOT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
// A clientSource from the 192.168.0.0/24 block will succeed in connecting to a server
// listening on 192.168.0.2.
@@ -1117,28 +1131,26 @@ TEST_F(AuthorizationSessionTest, UnauthorizedSessionIsCoauthorizedWithNobody) {
}
TEST_F(AuthorizationSessionTest, UnauthorizedSessionIsNotCoauthorizedWithAnybody) {
- ASSERT_FALSE(authzSession->isCoauthorizedWith(UserName("spencer", "test")));
+ ASSERT_FALSE(authzSession->isCoauthorizedWith(kSpencerTest));
}
TEST_F(AuthorizationSessionTest, UnauthorizedSessionIsCoauthorizedWithAnybodyWhenAuthIsDisabled) {
authzManager->setAuthEnabled(false);
- ASSERT_TRUE(authzSession->isCoauthorizedWith(UserName("spencer", "test")));
+ ASSERT_TRUE(authzSession->isCoauthorizedWith(kSpencerTest));
}
TEST_F(AuthorizationSessionTest, AuthorizedSessionIsNotCoauthorizedNobody) {
- UserName user("spencer", "test");
- ASSERT_OK(createUser(user, {}));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), user, boost::none));
+ ASSERT_OK(createUser(kSpencerTest, {}));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
ASSERT_FALSE(authzSession->isCoauthorizedWith(boost::none));
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
TEST_F(AuthorizationSessionTest, AuthorizedSessionIsCoauthorizedNobodyWhenAuthIsDisabled) {
- UserName user("spencer", "test");
authzManager->setAuthEnabled(false);
- ASSERT_OK(createUser(user, {}));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), user, boost::none));
- ASSERT_TRUE(authzSession->isCoauthorizedWith(user));
+ ASSERT_OK(createUser(kSpencerTest, {}));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
+ ASSERT_TRUE(authzSession->isCoauthorizedWith(kSpencerTest));
authzSession->logoutDatabase(_client.get(), "test", "Kill the test!");
}
@@ -1252,6 +1264,9 @@ TEST_F(AuthorizationSessionTest, CanUseUUIDNamespacesWithPrivilege) {
authzSession->verifyContract(&ac);
}
+const UserName kGMarksAdmin("gmarks", "admin");
+const UserRequest kGMarksAdminRequest(kGMarksAdmin, boost::none);
+
TEST_F(AuthorizationSessionTest, MayBypassWriteBlockingModeIsSetCorrectly) {
ASSERT_FALSE(authzSession->mayBypassWriteBlockingMode());
@@ -1267,8 +1282,7 @@ TEST_F(AuthorizationSessionTest, MayBypassWriteBlockingModeIsSetCorrectly) {
<< "db"
<< "test"))),
BSONObj()));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
ASSERT_FALSE(authzSession->mayBypassWriteBlockingMode());
// Add a user with restore role on admin db and ensure we can bypass
@@ -1285,8 +1299,7 @@ TEST_F(AuthorizationSessionTest, MayBypassWriteBlockingModeIsSetCorrectly) {
BSONObj()));
authzSession->logoutDatabase(_client.get(), "test", "End of test");
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("gmarks", "admin"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kGMarksAdminRequest, boost::none));
ASSERT_TRUE(authzSession->mayBypassWriteBlockingMode());
// Remove that user by logging out of the admin db and ensure we can't bypass anymore
@@ -1308,8 +1321,7 @@ TEST_F(AuthorizationSessionTest, MayBypassWriteBlockingModeIsSetCorrectly) {
BSONObj()));
authzSession->logoutDatabase(_client.get(), "admin", "");
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "admin"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kAdminAdminRequest, boost::none));
ASSERT_TRUE(authzSession->mayBypassWriteBlockingMode());
// Remove non-privileged user by logging out of test db and ensure we can still bypass
@@ -1325,15 +1337,14 @@ TEST_F(AuthorizationSessionTest, InvalidExpirationTime) {
// Create and authorize valid user with invalid expiration.
Date_t expirationTime = clockSource()->now() - Hours(1);
ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
- ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(
- _opCtx.get(), UserName("spencer", "test"), expirationTime));
+ ASSERT_NOT_OK(
+ authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, expirationTime));
}
TEST_F(AuthorizationSessionTest, NoExpirationTime) {
// Create and authorize valid user with no expiration.
ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
- ASSERT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("spencer", "test"), boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, boost::none));
assertActive(testFooCollResource, ActionType::insert);
// Assert that moving the clock forward has no impact on a session without expiration time.
@@ -1354,8 +1365,7 @@ TEST_F(AuthorizationSessionTest, ExpiredSessionWithReauth) {
Date_t expirationTime = clockSource()->now() + Hours(1);
ASSERT_OK(createUser({"spencer", "test"}, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
ASSERT_OK(createUser({"admin", "admin"}, {{"readWriteAnyDatabase", "admin"}}));
- ASSERT_OK(authzSession->addAndAuthorizeUser(
- _opCtx.get(), UserName("spencer", "test"), expirationTime));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, expirationTime));
// Assert that advancing the clock by 30 minutes does not trigger expiration.
auto clock = clockSource();
@@ -1373,8 +1383,7 @@ TEST_F(AuthorizationSessionTest, ExpiredSessionWithReauth) {
// Authorize the same user again to simulate re-login.
expirationTime += Hours(2);
- ASSERT_OK(authzSession->addAndAuthorizeUser(
- _opCtx.get(), UserName("spencer", "test"), expirationTime));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kSpencerTestRequest, expirationTime));
assertActive(testFooCollResource, ActionType::insert);
// Expire the user again, this time by setting clock to the exact expiration time boundary.
@@ -1383,8 +1392,7 @@ TEST_F(AuthorizationSessionTest, ExpiredSessionWithReauth) {
assertExpired(testFooCollResource, ActionType::insert);
// Assert that a different user cannot log in on the expired connection.
- ASSERT_NOT_OK(
- authzSession->addAndAuthorizeUser(_opCtx.get(), UserName("admin", "admin"), boost::none));
+ ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), kAdminAdminRequest, boost::none));
assertExpired(testFooCollResource, ActionType::insert);
// Check that explicit logout from an expired connection works as expected.
@@ -1402,8 +1410,10 @@ TEST_F(AuthorizationSessionTest, ExpirationWithSecurityTokenNOK) {
constexpr auto authUserFieldName = auth::SecurityToken::kAuthenticatedUserFieldName;
auto kOid = OID::gen();
auto body = BSON("ping" << 1 << "$tenant" << kOid);
- UserName user("spencer", "test", TenantId(kOid));
- UserName adminUser("admin", "admin");
+ const UserName user("spencer", "test", TenantId(kOid));
+ const UserRequest userRequest(user, boost::none);
+ const UserName adminUser("admin", "admin");
+ const UserRequest adminUserRequest(adminUser, boost::none);
ASSERT_OK(createUser(user, {{"readWrite", "test"}, {"dbAdmin", "test"}}));
ASSERT_OK(createUser(adminUser, {{"readWriteAnyDatabase", "admin"}}));
@@ -1414,14 +1424,14 @@ TEST_F(AuthorizationSessionTest, ExpirationWithSecurityTokenNOK) {
// Make sure that security token users can't be authorized with an expiration date.
Date_t expirationTime = clockSource()->now() + Hours(1);
- ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), user, expirationTime));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), user, boost::none));
+ ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), userRequest, expirationTime));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), userRequest, boost::none));
// Assert that the session is authenticated and authorized as expected.
assertSecurityToken(testFooCollResource, ActionType::insert);
// Assert that another user can't be authorized while the security token is auth'd.
- ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), adminUser, boost::none));
+ ASSERT_NOT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), adminUserRequest, boost::none));
// Check that starting a new request without the security token decoration results in token user
// logout.
@@ -1431,7 +1441,7 @@ TEST_F(AuthorizationSessionTest, ExpirationWithSecurityTokenNOK) {
// Assert that a connection-based user with an expiration policy can be authorized after token
// logout.
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), adminUser, expirationTime));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), adminUserRequest, expirationTime));
assertActive(ResourcePattern::forExactNamespace(NamespaceString("anydb.somecollection")),
ActionType::insert);
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.cpp b/src/mongo/db/auth/authz_manager_external_state_local.cpp
index 39d6da595f3..0b38920150f 100644
--- a/src/mongo/db/auth/authz_manager_external_state_local.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_local.cpp
@@ -313,7 +313,7 @@ StatusWith<User> AuthzManagerExternalStateLocal::getUserObject(OperationContext*
const UserRequest& userReq) try {
const UserName& userName = userReq.name;
std::vector<RoleName> directRoles;
- User user(userReq.name);
+ User user(userReq);
auto rolesLock = _lockRoles(opCtx, userName.getTenant());
diff --git a/src/mongo/db/auth/authz_manager_external_state_s.cpp b/src/mongo/db/auth/authz_manager_external_state_s.cpp
index 61705c9c9b9..4f415fd7247 100644
--- a/src/mongo/db/auth/authz_manager_external_state_s.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_s.cpp
@@ -118,7 +118,7 @@ StatusWith<User> AuthzManagerExternalStateMongos::getUserObject(OperationContext
return status;
}
- User user(userReq.name);
+ User user(userReq);
V2UserDocumentParser dp;
dp.setTenantId(getActiveTenant(opCtx));
status = dp.initializeUserFromUserDocument(userDoc, &user);
diff --git a/src/mongo/db/auth/sasl_commands.cpp b/src/mongo/db/auth/sasl_commands.cpp
index 5a50334a6ce..5e06de862f8 100644
--- a/src/mongo/db/auth/sasl_commands.cpp
+++ b/src/mongo/db/auth/sasl_commands.cpp
@@ -205,10 +205,10 @@ SaslReply doSaslStep(OperationContext* opCtx,
}
if (mechanism.isSuccess()) {
- UserName userName(mechanism.getPrincipalName(), mechanism.getAuthenticationDatabase());
+ auto request = mechanism.getUserRequest();
auto expirationTime = mechanism.getExpirationTime();
uassertStatusOK(AuthorizationSession::get(opCtx->getClient())
- ->addAndAuthorizeUser(opCtx, userName, expirationTime));
+ ->addAndAuthorizeUser(opCtx, request, expirationTime));
if (!serverGlobalParams.quiet.load()) {
auto attrs = makeLogAttributes();
diff --git a/src/mongo/db/auth/sasl_mechanism_registry.cpp b/src/mongo/db/auth/sasl_mechanism_registry.cpp
index fbc1caa8511..e3136ddfbe4 100644
--- a/src/mongo/db/auth/sasl_mechanism_registry.cpp
+++ b/src/mongo/db/auth/sasl_mechanism_registry.cpp
@@ -103,7 +103,6 @@ void SASLServerMechanismRegistry::advertiseMechanismNamesForUser(OperationContex
AuthorizationManager* authManager = AuthorizationManager::get(opCtx->getServiceContext());
UserHandle user;
-
const auto swUser = [&] {
ScopedCallbackTimer timer([&](Microseconds elapsed) {
LOGV2(6788603,
@@ -111,7 +110,7 @@ void SASLServerMechanismRegistry::advertiseMechanismNamesForUser(OperationContex
"metric"_attr = "sasl_acquireUser",
"micros"_attr = elapsed.count());
});
- return authManager->acquireUser(opCtx, userName);
+ return authManager->acquireUser(opCtx, UserRequest(userName, boost::none));
}();
if (!swUser.isOK()) {
diff --git a/src/mongo/db/auth/sasl_mechanism_registry.h b/src/mongo/db/auth/sasl_mechanism_registry.h
index f2011909368..2112ad06e7d 100644
--- a/src/mongo/db/auth/sasl_mechanism_registry.h
+++ b/src/mongo/db/auth/sasl_mechanism_registry.h
@@ -220,6 +220,13 @@ public:
virtual boost::optional<unsigned int> currentStep() const = 0;
virtual boost::optional<unsigned int> totalSteps() const = 0;
+ /**
+ * Create a UserRequest to send to AuthorizationSession.
+ */
+ virtual UserRequest getUserRequest() const {
+ return UserRequest(UserName(getPrincipalName(), getAuthenticationDatabase()), boost::none);
+ }
+
protected:
/**
* Mechanism provided step implementation.
diff --git a/src/mongo/db/auth/sasl_mechanism_registry_test.cpp b/src/mongo/db/auth/sasl_mechanism_registry_test.cpp
index 38a65af5f10..a8942d99052 100644
--- a/src/mongo/db/auth/sasl_mechanism_registry_test.cpp
+++ b/src/mongo/db/auth/sasl_mechanism_registry_test.cpp
@@ -233,7 +233,8 @@ public:
<< "roles" << BSONArray()),
BSONObj()));
- internalSecurity.setUser(std::make_shared<UserHandle>(User(UserName("__system", "local"))));
+ UserRequest systemLocal(UserName("__system"_sd, "local"_sd), boost::none);
+ internalSecurity.setUser(std::make_shared<UserHandle>(User(systemLocal)));
}
BSONObj getMechsFor(const UserName user) {
diff --git a/src/mongo/db/auth/sasl_plain_server_conversation.cpp b/src/mongo/db/auth/sasl_plain_server_conversation.cpp
index b9e1df67504..cf3ed62176a 100644
--- a/src/mongo/db/auth/sasl_plain_server_conversation.cpp
+++ b/src/mongo/db/auth/sasl_plain_server_conversation.cpp
@@ -135,8 +135,7 @@ StatusWith<std::tuple<bool, std::string>> SASLPlainServerMechanism::stepImpl(
"metric"_attr = "plain_acquireUser",
"micros"_attr = elapsed.count());
});
- return authManager->acquireUser(
- opCtx, UserName(ServerMechanismBase::_principalName, _authenticationDatabase));
+ return authManager->acquireUser(opCtx, getUserRequest());
}();
if (!swUser.isOK()) {
diff --git a/src/mongo/db/auth/sasl_scram_server_conversation.cpp b/src/mongo/db/auth/sasl_scram_server_conversation.cpp
index a8351aafbaf..eb1cbf2287d 100644
--- a/src/mongo/db/auth/sasl_scram_server_conversation.cpp
+++ b/src/mongo/db/auth/sasl_scram_server_conversation.cpp
@@ -213,7 +213,7 @@ StatusWith<std::tuple<bool, std::string>> SaslSCRAMServerMechanism<Policy>::_fir
"metric"_attr = "acquireUser",
"micros"_attr = elapsed.count());
});
- return authManager->acquireUser(opCtx, user);
+ return authManager->acquireUser(opCtx, UserRequest(user, boost::none));
}();
if (!swUser.isOK()) {
diff --git a/src/mongo/db/auth/security_key_test.cpp b/src/mongo/db/auth/security_key_test.cpp
index e64aded89f6..7a33cfbbad7 100644
--- a/src/mongo/db/auth/security_key_test.cpp
+++ b/src/mongo/db/auth/security_key_test.cpp
@@ -160,7 +160,8 @@ TEST(SecurityFile, Test) {
}
TEST(SecurityKey, Test) {
- internalSecurity.setUser(std::make_shared<UserHandle>(User(UserName("__system", "local"))));
+ UserRequest systemLocal(UserName("__system"_sd, "local"_sd), boost::none);
+ internalSecurity.setUser(std::make_shared<UserHandle>(User(systemLocal)));
for (const auto& testCase : testCases) {
TestFile file(testCase.fileContents, testCase.mode != TestCase::FailureMode::Permissions);
diff --git a/src/mongo/db/auth/security_token_authentication_guard.cpp b/src/mongo/db/auth/security_token_authentication_guard.cpp
index a989a356089..04462ee0a3d 100644
--- a/src/mongo/db/auth/security_token_authentication_guard.cpp
+++ b/src/mongo/db/auth/security_token_authentication_guard.cpp
@@ -41,10 +41,10 @@ namespace auth {
SecurityTokenAuthenticationGuard::SecurityTokenAuthenticationGuard(
OperationContext* opCtx, const ValidatedTenancyScope& token) {
if (token.hasAuthenticatedUser()) {
- const auto& userName = token.authenticatedUser();
+ UserRequest request(token.authenticatedUser(), boost::none);
auto* client = opCtx->getClient();
uassertStatusOK(
- AuthorizationSession::get(client)->addAndAuthorizeUser(opCtx, userName, boost::none));
+ AuthorizationSession::get(client)->addAndAuthorizeUser(opCtx, request, boost::none));
_client = client;
LOGV2_DEBUG(5838100,
diff --git a/src/mongo/db/auth/user.cpp b/src/mongo/db/auth/user.cpp
index a80e833c9e7..c50de72a546 100644
--- a/src/mongo/db/auth/user.cpp
+++ b/src/mongo/db/auth/user.cpp
@@ -66,8 +66,8 @@ SHA256Block computeDigest(const UserName& name) {
} // namespace
-User::User(const UserName& name)
- : _name(name), _isInvalidated(false), _digest(computeDigest(_name)) {}
+User::User(UserRequest request)
+ : _request(std::move(request)), _isInvalidated(false), _digest(computeDigest(_request.name)) {}
template <>
User::SCRAMCredentials<SHA1Block>& User::CredentialData::scram<SHA1Block>() {
@@ -201,10 +201,10 @@ void User::reportForUsersInfo(BSONObjBuilder* builder,
bool showCredentials,
bool showPrivileges,
bool showAuthenticationRestrictions) const {
- builder->append(kIdFieldName, _name.getUnambiguousName());
+ builder->append(kIdFieldName, getName().getUnambiguousName());
UUID::fromCDR(ConstDataRange(_id)).appendToBuilder(builder, kUserIdFieldName);
- builder->append(kUserFieldName, _name.getUser());
- builder->append(kDbFieldName, _name.getDB());
+ builder->append(kUserFieldName, getName().getUser());
+ builder->append(kDbFieldName, getName().getDB());
BSONArrayBuilder mechanismNamesBuilder(builder->subarrayStart(kMechanismsFieldName));
for (const StringData& mechanism : _credentials.toMechanismsVector()) {
diff --git a/src/mongo/db/auth/user.h b/src/mongo/db/auth/user.h
index 52b9e4e38d9..f9ca505322b 100644
--- a/src/mongo/db/auth/user.h
+++ b/src/mongo/db/auth/user.h
@@ -47,6 +47,47 @@
namespace mongo {
/**
+ * Represents the properties required to request a UserHandle.
+ * This type is hashable and may be used as a key describing requests
+ */
+struct UserRequest {
+ UserRequest(UserName name, boost::optional<std::set<RoleName>> roles)
+ : name(std::move(name)), roles(std::move(roles)) {}
+
+
+ template <typename H>
+ friend H AbslHashValue(H h, const UserRequest& key) {
+ auto state = H::combine(std::move(h), key.name, key.mechanismData);
+ if (key.roles) {
+ for (const auto& role : *key.roles) {
+ state = H::combine(std::move(state), role);
+ }
+ }
+ return state;
+ }
+
+ auto equalityLens() const {
+ return std::tie(name, roles, mechanismData);
+ }
+
+ bool operator==(const UserRequest& key) const {
+ return equalityLens() == key.equalityLens();
+ }
+
+ bool operator!=(const UserRequest& key) const {
+ return equalityLens() != key.equalityLens();
+ }
+
+ // The name of the requested user
+ UserName name;
+ // Any authorization grants which should override and be used in favor of roles acquisition.
+ boost::optional<std::set<RoleName>> roles;
+
+ // Mechanism specific metadata which may be used during User acquisition.
+ std::string mechanismData;
+};
+
+/**
* Represents a MongoDB user. Stores information about the user necessary for access control
* checks and authentications, such as what privileges this user has, as well as what roles
* the user belongs to.
@@ -158,7 +199,7 @@ public:
using ResourcePrivilegeMap = stdx::unordered_map<ResourcePattern, Privilege>;
- explicit User(const UserName& name);
+ explicit User(UserRequest request);
User(User&&) = default;
User& operator=(User&&) = default;
@@ -170,11 +211,15 @@ public:
_id = std::move(id);
}
+ const UserRequest& getUserRequest() const {
+ return _request;
+ }
+
/**
* Returns the user name for this user.
*/
const UserName& getName() const {
- return _name;
+ return _request.name;
}
/**
@@ -326,8 +371,8 @@ private:
// Unique ID (often UUID) for this user. May be empty for legacy users.
UserId _id;
- // The full user name (as specified by the administrator)
- UserName _name;
+ // The original UserRequest which resolved into this user
+ UserRequest _request;
// User was explicitly invalidated
bool _isInvalidated;
@@ -354,36 +399,6 @@ private:
RestrictionDocuments _indirectRestrictions;
};
-/**
- * Represents the properties required to request a UserHandle.
- * This type is hashable and may be used as a key describing requests
- */
-struct UserRequest {
- UserRequest(const UserName& name, boost::optional<std::set<RoleName>> roles)
- : name(name), roles(std::move(roles)) {}
-
-
- template <typename H>
- friend H AbslHashValue(H h, const UserRequest& key) {
- auto state = H::combine(std::move(h), key.name);
- if (key.roles) {
- for (const auto& role : *key.roles) {
- state = H::combine(std::move(state), role);
- }
- }
- return state;
- }
-
- bool operator==(const UserRequest& key) const {
- return name == key.name && roles == key.roles;
- }
-
- // The name of the requested user
- UserName name;
- // Any authorization grants which should override and be used in favor of roles acquisition.
- boost::optional<std::set<RoleName>> roles;
-};
-
using UserCache = ReadThroughCache<UserRequest, User>;
using UserHandle = UserCache::ValueHandle;
diff --git a/src/mongo/db/auth/user_document_parser_test.cpp b/src/mongo/db/auth/user_document_parser_test.cpp
index 00ff394a222..9773927ad50 100644
--- a/src/mongo/db/auth/user_document_parser_test.cpp
+++ b/src/mongo/db/auth/user_document_parser_test.cpp
@@ -63,8 +63,8 @@ public:
BSONObj sha1_creds, sha256_creds;
void setUp() {
- user.reset(new User(UserName("spencer", "test")));
- adminUser.reset(new User(UserName("admin", "admin")));
+ user.reset(new User(UserRequest(UserName("spencer", "test"), boost::none)));
+ adminUser.reset(new User(UserRequest(UserName("admin", "admin"), boost::none)));
sha1_creds = scram::Secrets<SHA1Block>::generateCredentials(
"a", saslGlobalParams.scramSHA1IterationCount.load());
diff --git a/src/mongo/db/auth/validated_tenancy_scope_test.cpp b/src/mongo/db/auth/validated_tenancy_scope_test.cpp
index 0f2049c893f..ee2859f70a7 100644
--- a/src/mongo/db/auth/validated_tenancy_scope_test.cpp
+++ b/src/mongo/db/auth/validated_tenancy_scope_test.cpp
@@ -48,7 +48,7 @@ public:
* Synthesize a user with the useTenant privilege and add them to the authorization session.
*/
static void grantUseTenant(Client& client) {
- User user(UserName("useTenant", "admin"));
+ User user(UserRequest(UserName("useTenant"_sd, "admin"_sd), boost::none));
user.setPrivileges(
{Privilege(ResourcePattern::forClusterResource(), ActionType::useTenant)});
auto* as = dynamic_cast<AuthorizationSessionImpl*>(AuthorizationSession::get(client));
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index 6b2077cc3ce..66214acb7da 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -177,6 +177,7 @@ env.Library(
'$BUILD_DIR/mongo/db/auth/auth',
'$BUILD_DIR/mongo/db/auth/auth_options',
'$BUILD_DIR/mongo/db/auth/authentication_session',
+ '$BUILD_DIR/mongo/db/auth/authorization_manager_global',
'$BUILD_DIR/mongo/db/auth/cluster_auth_mode',
'$BUILD_DIR/mongo/db/commands',
'$BUILD_DIR/mongo/db/server_base',
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index 13b62c1bef8..661b1d03e9f 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -40,6 +40,7 @@
#include "mongo/config.h"
#include "mongo/db/auth/auth_options_gen.h"
#include "mongo/db/auth/authentication_session.h"
+#include "mongo/db/auth/authorization_manager_global_parameters_gen.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/cluster_auth_mode.h"
#include "mongo/db/commands.h"
@@ -136,6 +137,33 @@ public:
} cmdLogout;
#ifdef MONGO_CONFIG_SSL
+} // namespace
+
+UserRequest getX509UserRequest(OperationContext* opCtx, UserRequest request) {
+ std::shared_ptr<transport::Session> session;
+ if (opCtx && opCtx->getClient()) {
+ session = opCtx->getClient()->session();
+ }
+
+ if (!allowRolesFromX509Certificates || !session || request.roles) {
+ return request;
+ }
+
+ auto& sslPeerInfo = SSLPeerInfo::forSession(session);
+ if (sslPeerInfo.roles.empty() ||
+ (sslPeerInfo.subjectName.toString() != request.name.getUser())) {
+ return request;
+ }
+
+ // In order to be hashable, the role names must be converted from unordered_set to a set.
+ request.roles = std::set<RoleName>();
+ std::copy(sslPeerInfo.roles.begin(),
+ sslPeerInfo.roles.end(),
+ std::inserter(*request.roles, request.roles->begin()));
+ return request;
+}
+
+namespace {
constexpr auto kX509AuthenticationDisabledMessage = "x.509 authentication is disabled."_sd;
/**
@@ -159,7 +187,7 @@ void _authenticateX509(OperationContext* opCtx, AuthenticationSession* session)
"No verified subject name available from client",
!clientName.empty());
- auto user = [&] {
+ UserName userName = ([&] {
if (session->getUserName().empty()) {
auto user = UserName(clientName.toString(), session->getDatabase().toString());
session->updateUserName(user, true /* isMechX509 */);
@@ -170,7 +198,7 @@ void _authenticateX509(OperationContext* opCtx, AuthenticationSession* session)
session->getUserName() == clientName.toString());
return UserName(session->getUserName().toString(), session->getDatabase().toString());
}
- }();
+ })();
uassert(ErrorCodes::ProtocolError,
"SSL support is required for the MONGODB-X509 mechanism.",
@@ -186,7 +214,7 @@ void _authenticateX509(OperationContext* opCtx, AuthenticationSession* session)
uassert(ErrorCodes::ProtocolError,
"X.509 authentication must always use the $external database.",
- user.getDB() == kExternalDB);
+ userName.getDB() == kExternalDB);
auto isInternalClient = [&]() -> bool {
return opCtx->getClient()->session()->getTags() & transport::Session::kInternalClient;
@@ -194,11 +222,12 @@ void _authenticateX509(OperationContext* opCtx, AuthenticationSession* session)
const auto clusterAuthMode = ClusterAuthMode::get(opCtx->getServiceContext());
+ auto request = getX509UserRequest(opCtx, UserRequest(userName, boost::none));
auto authorizeExternalUser = [&] {
uassert(ErrorCodes::BadValue,
kX509AuthenticationDisabledMessage,
!isX509AuthDisabled(opCtx->getServiceContext()));
- uassertStatusOK(authorizationSession->addAndAuthorizeUser(opCtx, user, boost::none));
+ uassertStatusOK(authorizationSession->addAndAuthorizeUser(opCtx, request, boost::none));
};
if (sslConfiguration->isClusterMember(clientName)) {
diff --git a/src/mongo/db/commands/authentication_commands.h b/src/mongo/db/commands/authentication_commands.h
index 2e82168e050..725f40afde0 100644
--- a/src/mongo/db/commands/authentication_commands.h
+++ b/src/mongo/db/commands/authentication_commands.h
@@ -32,6 +32,8 @@
#include "mongo/base/string_data.h"
#include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/auth/user.h"
+#include "mongo/db/auth/user_name.h"
#include "mongo/db/service_context.h"
namespace mongo {
@@ -41,6 +43,7 @@ constexpr StringData kX509AuthMechanism = "MONGODB-X509"_sd;
void disableX509Auth(ServiceContext* svcCtx);
bool isX509AuthDisabled(ServiceContext* svcCtx);
+UserRequest getX509UserRequest(OperationContext* opCtx, UserRequest request);
void doSpeculativeAuthenticate(OperationContext* opCtx, BSONObj isMaster, BSONObjBuilder* result);
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp
index 3cbff434678..8358ae25c05 100644
--- a/src/mongo/db/commands/user_management_commands.cpp
+++ b/src/mongo/db/commands/user_management_commands.cpp
@@ -139,7 +139,7 @@ Status getCurrentUserRoles(OperationContext* opCtx,
AuthorizationManager* authzManager,
const UserName& userName,
stdx::unordered_set<RoleName>* roles) {
- auto swUser = authzManager->acquireUser(opCtx, userName);
+ auto swUser = authzManager->acquireUser(opCtx, UserRequest(userName, boost::none));
if (!swUser.isOK()) {
return swUser.getStatus();
}
@@ -1385,7 +1385,8 @@ UsersInfoReply CmdUMCTyped<UsersInfoCommand, UMCInfoParams>::Invocation::typedRu
} else {
// Custom data is not required in the output, so it can be generated from a cached
// user object.
- auto swUserHandle = authzManager->acquireUser(opCtx, userName);
+ auto swUserHandle =
+ authzManager->acquireUser(opCtx, UserRequest(userName, boost::none));
if (swUserHandle.getStatus().code() == ErrorCodes::UserNotFound) {
continue;
}
diff --git a/src/mongo/db/commands_test.cpp b/src/mongo/db/commands_test.cpp
index 40dff290ee1..6a82edd45fe 100644
--- a/src/mongo/db/commands_test.cpp
+++ b/src/mongo/db/commands_test.cpp
@@ -476,10 +476,13 @@ protected:
AuthorizationSession* _authzSession;
};
+const UserName kVarunTest("varun", "test");
+const UserRequest kVarunTestRequest(kVarunTest, boost::none);
+
TEST_F(TypedCommandTest, runTyped) {
{
auto opCtx = _client->makeOperationContext();
- ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), {"varun", "test"}, boost::none));
+ ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), kVarunTestRequest, boost::none));
_authzSession->startRequest(opCtx.get());
}
@@ -492,7 +495,7 @@ TEST_F(TypedCommandTest, runTyped) {
TEST_F(TypedCommandTest, runMinimal) {
{
auto opCtx = _client->makeOperationContext();
- ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), {"varun", "test"}, boost::none));
+ ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), kVarunTestRequest, boost::none));
_authzSession->startRequest(opCtx.get());
}
@@ -505,7 +508,7 @@ TEST_F(TypedCommandTest, runMinimal) {
TEST_F(TypedCommandTest, runVoid) {
{
auto opCtx = _client->makeOperationContext();
- ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), {"varun", "test"}, boost::none));
+ ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), kVarunTestRequest, boost::none));
_authzSession->startRequest(opCtx.get());
}
@@ -518,7 +521,7 @@ TEST_F(TypedCommandTest, runVoid) {
TEST_F(TypedCommandTest, runThrowStatus) {
{
auto opCtx = _client->makeOperationContext();
- ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), {"varun", "test"}, boost::none));
+ ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), kVarunTestRequest, boost::none));
_authzSession->startRequest(opCtx.get());
}
@@ -539,7 +542,7 @@ TEST_F(TypedCommandTest, runThrowStatus) {
TEST_F(TypedCommandTest, runThrowDoCheckAuthorization) {
{
auto opCtx = _client->makeOperationContext();
- ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), {"varun", "test"}, boost::none));
+ ASSERT_OK(_authzSession->addAndAuthorizeUser(opCtx.get(), kVarunTestRequest, boost::none));
_authzSession->startRequest(opCtx.get());
}
@@ -578,7 +581,7 @@ TEST_F(TypedCommandTest, runThrowAuthzSessionExpired) {
auto opCtx = _client->makeOperationContext();
auto expirationTime = clockSource()->now() + Hours{1};
ASSERT_OK(
- _authzSession->addAndAuthorizeUser(opCtx.get(), {"varun", "test"}, expirationTime));
+ _authzSession->addAndAuthorizeUser(opCtx.get(), kVarunTestRequest, expirationTime));
// Fast-forward time before starting a new request.
clockSource()->advance(Hours(2));
diff --git a/src/mongo/db/session/SConscript b/src/mongo/db/session/SConscript
index 9862c8a660b..a0021e3ac81 100644
--- a/src/mongo/db/session/SConscript
+++ b/src/mongo/db/session/SConscript
@@ -155,6 +155,7 @@ env.Library(
'$BUILD_DIR/mongo/db/api_parameters',
'$BUILD_DIR/mongo/db/auth/auth',
'$BUILD_DIR/mongo/db/auth/authprivilege',
+ '$BUILD_DIR/mongo/db/auth/user',
'$BUILD_DIR/mongo/idl/idl_parser',
'$BUILD_DIR/mongo/rpc/client_metadata',
'logical_session_id_helpers',
diff --git a/src/mongo/db/session/kill_sessions.cpp b/src/mongo/db/session/kill_sessions.cpp
index 7626afa111b..99d8fd5122a 100644
--- a/src/mongo/db/session/kill_sessions.cpp
+++ b/src/mongo/db/session/kill_sessions.cpp
@@ -109,12 +109,8 @@ KillAllSessionsByPatternItem makeKillAllSessionsByPattern(OperationContext* opCt
const KillAllSessionsUser& kasu) {
KillAllSessionsByPatternItem item = makeKillAllSessionsByPattern(opCtx);
- auto authMgr = AuthorizationManager::get(opCtx->getServiceContext());
-
- UserName un(kasu.getUser(), kasu.getDb());
-
- auto user = uassertStatusOK(authMgr->acquireUser(opCtx, un));
- item.pattern.setUid(user->getDigest());
+ User user(UserRequest(UserName(kasu.getUser(), kasu.getDb()), boost::none));
+ item.pattern.setUid(user.getDigest());
return item;
}
diff --git a/src/mongo/db/session/logical_session_id_test.cpp b/src/mongo/db/session/logical_session_id_test.cpp
index 5b5f59fbb83..a338ca5ddae 100644
--- a/src/mongo/db/session/logical_session_id_test.cpp
+++ b/src/mongo/db/session/logical_session_id_test.cpp
@@ -111,7 +111,7 @@ public:
<< "db"
<< "test"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), un, boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {un, boost::none}, boost::none));
return authzSession->lookupUser(un);
}
@@ -126,7 +126,7 @@ public:
<< "db"
<< "admin"))),
BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), un, boost::none));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(_opCtx.get(), {un, boost::none}, boost::none));
return authzSession->lookupUser(un);
}
};
diff --git a/src/mongo/embedded/embedded_auth_manager.cpp b/src/mongo/embedded/embedded_auth_manager.cpp
index 6604e4a2756..b0da468f787 100644
--- a/src/mongo/embedded/embedded_auth_manager.cpp
+++ b/src/mongo/embedded/embedded_auth_manager.cpp
@@ -116,7 +116,7 @@ public:
UASSERT_NOT_IMPLEMENTED;
}
- StatusWith<UserHandle> acquireUser(OperationContext*, const UserName&) override {
+ StatusWith<UserHandle> acquireUser(OperationContext*, const UserRequest&) override {
UASSERT_NOT_IMPLEMENTED;
}
diff --git a/src/mongo/embedded/embedded_auth_session.cpp b/src/mongo/embedded/embedded_auth_session.cpp
index 1925afdf14c..135f0d2c95b 100644
--- a/src/mongo/embedded/embedded_auth_session.cpp
+++ b/src/mongo/embedded/embedded_auth_session.cpp
@@ -71,7 +71,7 @@ public:
void startContractTracking() override {}
Status addAndAuthorizeUser(OperationContext*,
- const UserName&,
+ const UserRequest&,
boost::optional<Date_t>) override {
UASSERT_NOT_IMPLEMENTED;
}
diff --git a/src/mongo/rpc/op_msg_test.cpp b/src/mongo/rpc/op_msg_test.cpp
index 95da2298ec4..def7ff23975 100644
--- a/src/mongo/rpc/op_msg_test.cpp
+++ b/src/mongo/rpc/op_msg_test.cpp
@@ -61,7 +61,7 @@ public:
* Synthesize a user with the useTenant privilege and add them to the authorization session.
*/
static void grantUseTenant(Client& client) {
- User user(UserName("useTenant", "admin"));
+ User user(UserRequest(UserName("useTenant", "admin"), boost::none));
user.setPrivileges(
{Privilege(ResourcePattern::forClusterResource(), ActionType::useTenant)});
auto* as = dynamic_cast<AuthorizationSessionImpl*>(AuthorizationSession::get(client));
diff --git a/src/mongo/util/net/network_interface_ssl_test.cpp b/src/mongo/util/net/network_interface_ssl_test.cpp
index fadbb694257..cc4fae14287 100644
--- a/src/mongo/util/net/network_interface_ssl_test.cpp
+++ b/src/mongo/util/net/network_interface_ssl_test.cpp
@@ -60,7 +60,8 @@ public:
NetworkInterfaceIntegrationFixture::setUp();
// Setup an internal user so that we can use it for external auth
- auto user = std::make_shared<UserHandle>(User(UserName("__system", "local")));
+ UserRequest systemLocal(UserName("__system"_sd, "local"_sd), boost::none);
+ auto user = std::make_shared<UserHandle>(User(systemLocal));
internalSecurity.setUser(user);