Status checkAuthForRolesInfoCommand(ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); auth::RolesInfoArgs args; Status status = auth::parseRolesInfoCommand(cmdObj, dbname, &args); if (!status.isOK()) { return status; } if (args.allForDB) { if (!authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forDatabaseName(dbname), ActionType::viewRole)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to view roles from the " << dbname << " database"); } } else { for (size_t i = 0; i < args.roleNames.size(); ++i) { if (authzSession->isAuthenticatedAsUserWithRole(args.roleNames[i])) { continue; // Can always see roles that you are a member of } if (!authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forDatabaseName(args.roleNames[i].getDB()), ActionType::viewRole)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to view roles from the " << args.roleNames[i].getDB() << " database"); } } } return Status::OK(); }
Status checkAuthForUsersInfoCommand(ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); auth::UsersInfoArgs args; Status status = auth::parseUsersInfoCommand(cmdObj, dbname, &args); if (!status.isOK()) { return status; } if (args.allForDB) { if (!authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forDatabaseName(dbname), ActionType::viewUser)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to view users from the " << dbname << " database"); } } else { for (size_t i = 0; i < args.userNames.size(); ++i) { if (authzSession->lookupUser(args.userNames[i])) { continue; // Can always view users you are logged in as } if (!authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forDatabaseName(args.userNames[i].getDB()), ActionType::viewUser)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to view users from the " << dbname << " database"); } } } return Status::OK(); }
Status checkAuthForCreateUserCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); auth::CreateOrUpdateUserArgs args; Status status = auth::parseCreateOrUpdateUserCommands(cmdObj, "createUser", dbname, &args); if (!status.isOK()) { return status; } if (!authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forDatabaseName(args.userName.getDB()), ActionType::createUser)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to create users on db: " << args.userName.getDB()); } status = checkAuthorizedToGrantRoles(authzSession, args.roles); if (!status.isOK()) { return status; } status = checkAuthorizedToSetRestrictions( authzSession, static_cast<bool>(args.authenticationRestrictions), args.userName.getDB()); if (!status.isOK()) { return status; } return Status::OK(); }
Status checkAuthForUpdateRoleCommand(ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); auth::CreateOrUpdateRoleArgs args; Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "updateRole", dbname, &args); if (!status.isOK()) { return status; } // You don't know what roles or privileges you might be revoking, so require the ability // to revoke any role (or privilege) in the system. if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forAnyNormalResource(), ActionType::revokeRole)) { return Status(ErrorCodes::Unauthorized, "updateRole command required the ability to revoke any role in the " "system"); } status = checkAuthorizedToGrantRoles(authzSession, args.roles); if (!status.isOK()) { return status; } return checkAuthorizedToGrantPrivileges(authzSession, args.privileges); }
Status checkAuthForCreateRoleCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); auth::CreateOrUpdateRoleArgs args; Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "createRole", dbname, &args); if (!status.isOK()) { return status; } if (!authzSession->isAuthorizedToCreateRole(args)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to create roles on db: " << args.roleName.getDB()); } status = checkAuthorizedToGrantRoles(authzSession, args.roles); if (!status.isOK()) { return status; } status = checkAuthorizedToGrantPrivileges(authzSession, args.privileges); if (!status.isOK()) { return status; } status = checkAuthorizedToSetRestrictions( authzSession, static_cast<bool>(args.authenticationRestrictions), args.roleName.getDB()); if (!status.isOK()) { return status; } return Status::OK(); }
Status checkAuthForAuthSchemaUpgradeCommand(ClientBasic* client) { AuthorizationSession* authzSession = AuthorizationSession::get(client); if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), ActionType::authSchemaUpgrade)) { return Status(ErrorCodes::Unauthorized, "Not authorized to run authSchemaUpgrade command."); } return Status::OK(); }
Status checkAuthForInvalidateUserCacheCommand(Client* client) { AuthorizationSession* authzSession = AuthorizationSession::get(client); if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), ActionType::invalidateUserCache)) { return Status(ErrorCodes::Unauthorized, "Not authorized to invalidate user cache"); } return Status::OK(); }
Status checkAuthForGetUserCacheGenerationCommand(Client* client) { AuthorizationSession* authzSession = AuthorizationSession::get(client); if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), ActionType::internal)) { return Status(ErrorCodes::Unauthorized, "Not authorized to get cache generation"); } return Status::OK(); }
Status checkAuthForDropAllRolesFromDatabaseCommand(Client* client, const std::string& dbname) { AuthorizationSession* authzSession = AuthorizationSession::get(client); if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(dbname), ActionType::dropRole)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to drop roles from the " << dbname << " database"); } return Status::OK(); }
Status checkAuthForCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); ResourcePattern pattern = parseResourcePattern(dbname, cmdObj); if (authzSession->isAuthorizedForActionsOnResource(pattern, _actionType)) { return Status::OK(); } return Status(ErrorCodes::Unauthorized, "unauthorized"); }
Status checkAuthForCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) final { AuthorizationSession* authzSession = AuthorizationSession::get(client); if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), ActionType::replSetResizeOplog)) { return Status::OK(); } return Status(ErrorCodes::Unauthorized, "Unauthorized"); }
Status CmdAuthenticate::_authenticateX509(const UserName& user, const BSONObj& cmdObj) { if (!getSSLManager()) { return Status(ErrorCodes::ProtocolError, "SSL support is required for the MONGODB-X509 mechanism."); } if(user.getDB() != "$external") { return Status(ErrorCodes::ProtocolError, "X.509 authentication must always use the $external database."); } ClientBasic *client = ClientBasic::getCurrent(); AuthorizationSession* authorizationSession = client->getAuthorizationSession(); std::string subjectName = client->port()->getX509SubjectName(); if (user.getUser() != subjectName) { return Status(ErrorCodes::AuthenticationFailed, "There is no x.509 client certificate matching the user."); } else { std::string srvSubjectName = getSSLManager()->getServerSubjectName(); size_t srvClusterIdPos = srvSubjectName.find(",OU="); size_t peerClusterIdPos = subjectName.find(",OU="); std::string srvClusterId = srvClusterIdPos != std::string::npos ? srvSubjectName.substr(srvClusterIdPos) : ""; std::string peerClusterId = peerClusterIdPos != std::string::npos ? subjectName.substr(peerClusterIdPos) : ""; // Handle internal cluster member auth, only applies to server-server connections int clusterAuthMode = serverGlobalParams.clusterAuthMode.load(); if (srvClusterId == peerClusterId && !srvClusterId.empty()) { if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_undefined || clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile) { return Status(ErrorCodes::AuthenticationFailed, "The provided certificate " "can only be used for cluster authentication, not client " "authentication. The current configuration does not allow " "x.509 cluster authentication, check the --clusterAuthMode flag"); } authorizationSession->grantInternalAuthorization(); } // Handle normal client authentication, only applies to client-server connections else { if (_isX509AuthDisabled) { return Status(ErrorCodes::BadValue, _x509AuthenticationDisabledMessage); } Status status = authorizationSession->addAndAuthorizeUser(user); if (!status.isOK()) { return status; } } return Status::OK(); } }
Status IndexFilterCommand::checkAuthForCommand(ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = client->getAuthorizationSession(); ResourcePattern pattern = parseResourcePattern(dbname, cmdObj); if (authzSession->isAuthorizedForActionsOnResource(pattern, ActionType::planCacheIndexFilter)) { return Status::OK(); } return Status(ErrorCodes::Unauthorized, "unauthorized"); }
bool run(const string& dbname, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl) { AuthorizationSession* authSession = ClientBasic::getCurrent()->getAuthorizationSession(); authSession->logoutDatabase(dbname); return true; }
Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) const override { AuthorizationSession* authSession = AuthorizationSession::get(opCtx->getClient()); if (!authSession->isAuthorizedForPrivilege( Privilege{ResourcePattern::forClusterResource(), ActionType::killAnySession})) { return Status(ErrorCodes::Unauthorized, "Unauthorized"); } return Status::OK(); }
Status checkAuthForCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) const final { AuthorizationSession* authzSession = AuthorizationSession::get(client); if (authzSession->isAuthorizedToListCollections(dbname, cmdObj)) { return Status::OK(); } return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to list collections on db: " << dbname); }
Status CmdAuthenticate::_authenticateX509( OperationContext* txn, const UserName& user, const BSONObj& cmdObj) { if (!getSSLManager()) { return Status(ErrorCodes::ProtocolError, "SSL support is required for the MONGODB-X509 mechanism."); } if(user.getDB() != "$external") { return Status(ErrorCodes::ProtocolError, "X.509 authentication must always use the $external database."); } ClientBasic *client = ClientBasic::getCurrent(); AuthorizationSession* authorizationSession = AuthorizationSession::get(client); std::string subjectName = client->port()->getX509SubjectName(); if (!getSSLManager()->getSSLConfiguration().hasCA) { return Status(ErrorCodes::AuthenticationFailed, "Unable to verify x.509 certificate, as no CA has been provided."); } else if (user.getUser() != subjectName) { return Status(ErrorCodes::AuthenticationFailed, "There is no x.509 client certificate matching the user."); } else { std::string srvSubjectName = getSSLManager()->getSSLConfiguration().serverSubjectName; // Handle internal cluster member auth, only applies to server-server connections if (_clusterIdMatch(subjectName, srvSubjectName)) { int clusterAuthMode = serverGlobalParams.clusterAuthMode.load(); if (clusterAuthMode == ServerGlobalParams::ClusterAuthMode_undefined || clusterAuthMode == ServerGlobalParams::ClusterAuthMode_keyFile) { return Status(ErrorCodes::AuthenticationFailed, "The provided certificate " "can only be used for cluster authentication, not client " "authentication. The current configuration does not allow " "x.509 cluster authentication, check the --clusterAuthMode flag"); } authorizationSession->grantInternalAuthorization(); } // Handle normal client authentication, only applies to client-server connections else { if (_isX509AuthDisabled) { return Status(ErrorCodes::BadValue, _x509AuthenticationDisabledMessage); } Status status = authorizationSession->addAndAuthorizeUser(txn, user); if (!status.isOK()) { return status; } } return Status::OK(); } }
KillAllSessionsByPatternSet makeSessionFilterForAuthenticatedUsers(OperationContext* opCtx) { AuthorizationSession* authSession = AuthorizationSession::get(opCtx->getClient()); KillAllSessionsByPatternSet patterns; for (auto it = authSession->getAuthenticatedUserNames(); it.more(); it.next()) { if (auto user = authSession->lookupUser(*it)) { KillAllSessionsByPattern pattern; pattern.setUid(user->getDigest()); patterns.emplace(std::move(pattern)); } } return patterns; }
Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) const override { // It is always ok to run this command, as long as you are authenticated // as some user, if auth is enabled. AuthorizationSession* authSession = AuthorizationSession::get(opCtx->getClient()); try { auto user = authSession->getSingleUser(); invariant(user); return Status::OK(); } catch (...) { return exceptionToStatus(); } }
void Strategy::killCursors(OperationContext* txn, Request& request) { if (!useClusterClientCursor) { cursorCache.gotKillCursors(request.m()); return; } DbMessage& dbMessage = request.d(); const int numCursors = dbMessage.pullInt(); massert(28793, str::stream() << "Invalid killCursors message. numCursors: " << numCursors << ", message size: " << dbMessage.msg().dataSize() << ".", dbMessage.msg().dataSize() == 8 + (8 * numCursors)); uassert(28794, str::stream() << "numCursors must be between 1 and 29999. numCursors: " << numCursors << ".", numCursors >= 1 && numCursors < 30000); ConstDataCursor cursors(dbMessage.getArray(numCursors)); Client* client = txn->getClient(); AuthorizationSession* authSession = AuthorizationSession::get(client); ClusterCursorManager* manager = grid.getCursorManager(); for (int i = 0; i < numCursors; ++i) { CursorId cursorId = cursors.readAndAdvance<LittleEndian<int64_t>>(); boost::optional<NamespaceString> nss = manager->getNamespaceForCursorId(cursorId); if (!nss) { LOG(3) << "Can't find cursor to kill. Cursor id: " << cursorId << "."; continue; } Status authorizationStatus = authSession->checkAuthForKillCursors(*nss, cursorId); audit::logKillCursorsAuthzCheck(client, *nss, cursorId, authorizationStatus.isOK() ? ErrorCodes::OK : ErrorCodes::Unauthorized); if (!authorizationStatus.isOK()) { LOG(3) << "Not authorized to kill cursor. Namespace: '" << *nss << "', cursor id: " << cursorId << "."; continue; } Status killCursorStatus = manager->killCursor(*nss, cursorId); if (!killCursorStatus.isOK()) { LOG(3) << "Can't find cursor to kill. Namespace: '" << *nss << "', cursor id: " << cursorId << "."; continue; } LOG(3) << "Killed cursor. Namespace: '" << *nss << "', cursor id: " << cursorId << "."; } }
Status checkAuthForApplyOpsCommand(OperationContext* txn, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authSession = AuthorizationSession::get(txn->getClient()); ApplyOpsValidity validity = validateApplyOpsCommand(cmdObj); if (validity == ApplyOpsValidity::kNeedsSuperuser) { std::vector<Privilege> universalPrivileges; RoleGraph::generateUniversalPrivileges(&universalPrivileges); if (!authSession->isAuthorizedForPrivileges(universalPrivileges)) { return Status(ErrorCodes::Unauthorized, "Unauthorized"); } return Status::OK(); } fassert(40314, validity == ApplyOpsValidity::kOk); boost::optional<DisableDocumentValidation> maybeDisableValidation; if (shouldBypassDocumentValidationForCommand(cmdObj)) maybeDisableValidation.emplace(txn); const bool alwaysUpsert = cmdObj.hasField("alwaysUpsert") ? cmdObj["alwaysUpsert"].trueValue() : true; checkBSONType(BSONType::Array, cmdObj.firstElement()); for (const BSONElement& e : cmdObj.firstElement().Array()) { checkBSONType(BSONType::Object, e); Status status = checkOperationAuthorization(txn, dbname, e.Obj(), alwaysUpsert); if (!status.isOK()) { return status; } } BSONElement preconditions = cmdObj["preCondition"]; if (!preconditions.eoo()) { for (const BSONElement& precondition : preconditions.Array()) { checkBSONType(BSONType::Object, precondition); BSONElement nsElem = precondition.Obj()["ns"]; checkBSONType(BSONType::String, nsElem); NamespaceString nss(nsElem.checkAndGetStringData()); if (!authSession->isAuthorizedForActionsOnResource( ResourcePattern::forExactNamespace(nss), ActionType::find)) { return Status(ErrorCodes::Unauthorized, "Unauthorized to check precondition"); } } } return Status::OK(); }
Status checkAuthForCommand(Client* client, const std::string& dbName, const BSONObj& cmdObj) const final { AuthorizationSession* authzSession = AuthorizationSession::get(client); if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), ActionType::inprog)) { return Status::OK(); } if (authzSession->isAuthenticated() && cmdObj["$ownOps"].trueValue()) { return Status::OK(); } return Status(ErrorCodes::Unauthorized, "Unauthorized"); }
bool run(OperationContext* opCtx, const string& dbname, const BSONObj& cmdObj, BSONObjBuilder& result) { AuthorizationSession* authSession = AuthorizationSession::get(Client::getCurrent()); authSession->logoutDatabase(dbname); if (Command::testCommandsEnabled && dbname == "admin") { // Allows logging out as the internal user against the admin database, however // this actually logs out of the local database as well. This is to // support the auth passthrough test framework on mongos (since you can't use the // local database on a mongos, so you can't logout as the internal user // without this). authSession->logoutDatabase("local"); } return true; }
Status checkAuthForDropRoleCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); RoleName roleName; Status status = auth::parseDropRoleCommand(cmdObj, dbname, &roleName); if (!status.isOK()) { return status; } if (!authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forDatabaseName(roleName.getDB()), ActionType::dropRole)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to drop roles from the " << roleName.getDB() << " database"); } return Status::OK(); }
virtual Status checkAuthForCommand(ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); // Check for the listCollections ActionType on the database // or find on system.namespaces for pre 3.0 systems. if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(dbname), ActionType::listCollections) || authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forExactNamespace(NamespaceString(dbname, "system.namespaces")), ActionType::find)) { return Status::OK(); } return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to create users on db: " << dbname); }
Status checkAuthForDropUserCommand(ClientBasic* client, const std::string& dbname, const BSONObj& cmdObj) { AuthorizationSession* authzSession = AuthorizationSession::get(client); UserName userName; BSONObj unusedWriteConcern; Status status = auth::parseAndValidateDropUserCommand(cmdObj, dbname, &userName, &unusedWriteConcern); if (!status.isOK()) { return status; } if (!authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forDatabaseName(userName.getDB()), ActionType::dropUser)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to drop users from the " << userName.getDB() << " database"); } return Status::OK(); }
Status checkAuthForCommand(Client* client, const std::string& dbname, const BSONObj& cmdObj) const override { AuthorizationSession* authzSession = AuthorizationSession::get(client); // Check for the listIndexes ActionType on the database, or find on system.indexes for pre // 3.0 systems. const NamespaceString ns(parseNs(dbname, cmdObj)); if (authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forExactNamespace(ns), ActionType::listIndexes) || authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forExactNamespace(NamespaceString(dbname, "system.indexes")), ActionType::find)) { return Status::OK(); } return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to list indexes on collection: " << ns.coll()); }
static StatusWith<std::tuple<stdx::unique_lock<Client>, OperationContext*>> _findOp( ClientBasic* client, unsigned int opId) { AuthorizationSession* authzSession = AuthorizationSession::get(client); for (ServiceContext::LockedClientsCursor cursor(client->getServiceContext()); Client* opClient = cursor.next();) { stdx::unique_lock<Client> lk(*opClient); OperationContext* opCtx = opClient->getOperationContext(); if (opCtx && opCtx->getOpID() == opId) { if (authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forClusterResource(), ActionType::killop) || authzSession->isCoauthorizedWithClient(opClient)) { return {std::make_tuple(std::move(lk), opCtx)}; } break; } } return Status(ErrorCodes::NoSuchKey, str::stream() << "Could not access opID: " << opId); }
bool CmdAuthenticate::authenticateX509(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result) { if(dbname != "$external") { errmsg = "X.509 authentication must always use the $external database."; result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed); return false; } std::string user = cmdObj.getStringField("user"); ClientBasic *client = ClientBasic::getCurrent(); AuthorizationSession* authorizationSession = client->getAuthorizationSession(); StringData subjectName = client->port()->getX509SubjectName(); if (user != subjectName) { errmsg = "There is no x.509 client certificate matching the user."; result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed); return false; } else { StringData srvSubjectName = getSSLManager()->getSubjectName(); StringData srvClusterId = srvSubjectName.substr(0, srvSubjectName.find("/CN")+1); StringData peerClusterId = subjectName.substr(0, subjectName.find("/CN")+1); // Handle internal cluster member if (srvClusterId == peerClusterId) { authorizationSession->grantInternalAuthorization(UserName(user, "$external")); } // Handle normal client authentication else { Principal* principal = new Principal(UserName(user, "$external")); principal->setImplicitPrivilegeAcquisition(true); authorizationSession->addAuthorizedPrincipal(principal); } result.append( "dbname" , dbname ); result.append( "user" , user ); return true; } }
Status checkAuthForMergeAuthzCollectionsCommand(Client* client, const BSONObj& cmdObj) { auth::MergeAuthzCollectionsArgs args; Status status = auth::parseMergeAuthzCollectionsCommand(cmdObj, &args); if (!status.isOK()) { return status; } AuthorizationSession* authzSession = AuthorizationSession::get(client); ActionSet actions; actions.addAction(ActionType::createUser); actions.addAction(ActionType::createRole); actions.addAction(ActionType::grantRole); actions.addAction(ActionType::revokeRole); if (args.drop) { actions.addAction(ActionType::dropUser); actions.addAction(ActionType::dropRole); } if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forAnyNormalResource(), actions)) { return Status(ErrorCodes::Unauthorized, "Not authorized to update user/role data using _mergeAuthzCollections" " command"); } if (!args.usersCollName.empty() && !authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forExactNamespace(NamespaceString(args.usersCollName)), ActionType::find)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to read " << args.usersCollName); } if (!args.rolesCollName.empty() && !authzSession->isAuthorizedForActionsOnResource( ResourcePattern::forExactNamespace(NamespaceString(args.rolesCollName)), ActionType::find)) { return Status(ErrorCodes::Unauthorized, str::stream() << "Not authorized to read " << args.rolesCollName); } return Status::OK(); }