diff options
Diffstat (limited to 'src/mongo/db/auth/authorization_manager_impl.cpp')
-rw-r--r-- | src/mongo/db/auth/authorization_manager_impl.cpp | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp index 9a50ec921ab..db1081b8bf3 100644 --- a/src/mongo/db/auth/authorization_manager_impl.cpp +++ b/src/mongo/db/auth/authorization_manager_impl.cpp @@ -68,8 +68,7 @@ namespace mongo { namespace { std::shared_ptr<UserHandle> createSystemUserHandle() { - UserRequest request(UserName("__system", "local"), boost::none); - auto user = std::make_shared<UserHandle>(User(std::move(request))); + auto user = std::make_shared<UserHandle>(User(UserName("__system", "local"))); ActionSet allActions; allActions.addAllActions(); @@ -285,6 +284,29 @@ 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, @@ -472,17 +494,29 @@ MONGO_FAIL_POINT_DEFINE(authUserCacheSleep); } // namespace StatusWith<UserHandle> AuthorizationManagerImpl::acquireUser(OperationContext* opCtx, - const UserRequest& request) try { - const auto& userName = request.name; - + const UserName& userName) try { 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); + +#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())); + } +#endif + if (authUserCacheBypass.shouldFail()) { // Bypass cache and force a fresh load of the user. auto loadedUser = uassertStatusOK(_externalState->getUserObject(opCtx, request)); @@ -525,7 +559,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, user->getUserRequest()); + auto swUserHandle = acquireUser(opCtx, userName); if (!swUserHandle.isOK()) { return swUserHandle.getStatus(); } @@ -611,18 +645,6 @@ 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; @@ -630,14 +652,7 @@ void AuthorizationManagerImpl::_pinnedUsersThreadRoutine() noexcept try { continue; } - auto request = ([&] { - if (auto it = pinNow.find(userName); it != pinNow.end()) { - return it->second; - } - return UserRequest(userName, boost::none); - })(); - - auto swUser = acquireUser(opCtx.get(), request); + auto swUser = acquireUser(opCtx.get(), userName); if (swUser.isOK()) { LOGV2_DEBUG(20232, 2, "Pinned user", "user"_attr = userName); |