Status AuthzManagerExternalStateMongos::getUserDescription(OperationContext* txn, const UserName& userName, BSONObj* result) { BSONObj usersInfoCmd = BSON("usersInfo" << BSON_ARRAY(BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() << AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB())) << "showPrivileges" << true << "showCredentials" << true); BSONObjBuilder builder; const bool ok = grid.catalogManager(txn) ->runUserManagementReadCommand(txn, "admin", usersInfoCmd, &builder); BSONObj cmdResult = builder.obj(); if (!ok) { return Command::getStatusFromCommandResult(cmdResult); } std::vector<BSONElement> foundUsers = cmdResult["users"].Array(); if (foundUsers.size() == 0) { return Status(ErrorCodes::UserNotFound, "User \"" + userName.toString() + "\" not found"); } if (foundUsers.size() > 1) { return Status(ErrorCodes::UserDataInconsistent, str::stream() << "Found multiple users on the \"" << userName.getDB() << "\" database with name \"" << userName.getUser() << "\""); } *result = foundUsers[0].Obj().getOwned(); return Status::OK(); }
Status AuthzManagerExternalState::getPrivilegeDocument(const UserName& userName, int authzVersion, BSONObj* result) { if (userName == internalSecurity.user->getName()) { return Status(ErrorCodes::InternalError, "Requested privilege document for the internal user"); } StringData dbname = userName.getDB(); // Make sure the dbname is actually a database if (dbname == StringData("$external", StringData::LiteralTag()) || dbname == AuthorizationManager::SERVER_RESOURCE_NAME || dbname == AuthorizationManager::CLUSTER_RESOURCE_NAME) { return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "No privilege documents stored in the " << dbname << " user source."); } if (!NamespaceString::validDBName(dbname)) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << "Bad database name \"" << dbname << "\""); } // Build the query needed to get the privilege document std::string usersNamespace; BSONObjBuilder queryBuilder; if (authzVersion == 1) { usersNamespace = mongoutils::str::stream() << dbname << ".system.users"; queryBuilder.append(AuthorizationManager::V1_USER_NAME_FIELD_NAME, userName.getUser()); queryBuilder.appendNull(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME); } else if (authzVersion == 2) { usersNamespace = "admin.system.users"; queryBuilder.append(AuthorizationManager::USER_NAME_FIELD_NAME, userName.getUser()); queryBuilder.append(AuthorizationManager::USER_SOURCE_FIELD_NAME, userName.getDB()); } else { return Status(ErrorCodes::UnsupportedFormat, mongoutils::str::stream() << "Unrecognized authorization format version: " << authzVersion); } // Query for the privilege document BSONObj userBSONObj; Status found = _findUser(usersNamespace, queryBuilder.obj(), &userBSONObj); if (!found.isOK()) { if (found.code() == ErrorCodes::UserNotFound) { // Return more detailed status that includes user name. return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "auth: couldn't find user " << userName.toString() << ", " << usersNamespace, 0); } else { return found; } } *result = userBSONObj.getOwned(); return Status::OK(); }
Status AuthzManagerExternalState::getPrivilegeDocument(const std::string& dbname, const UserName& userName, BSONObj* result) const { if (dbname == StringData("$external", StringData::LiteralTag()) || dbname == AuthorizationManager::SERVER_RESOURCE_NAME || dbname == AuthorizationManager::CLUSTER_RESOURCE_NAME) { return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "No privilege documents stored in the " << dbname << " user source."); } if (!NamespaceString::validDBName(dbname)) { return Status(ErrorCodes::BadValue, "Bad database name \"" + dbname + "\""); } if (userName == internalSecurity.user) { if (internalSecurity.pwd.empty()) { return Status(ErrorCodes::UserNotFound, "key file must be used to log in with internal user", 15889); } *result = BSON(AuthorizationManager::USER_NAME_FIELD_NAME << internalSecurity.user.getUser() << AuthorizationManager::PASSWORD_FIELD_NAME << internalSecurity.pwd).getOwned(); return Status::OK(); } std::string usersNamespace = dbname + ".system.users"; BSONObj userBSONObj; BSONObjBuilder queryBuilder; queryBuilder.append(AuthorizationManager::USER_NAME_FIELD_NAME, userName.getUser()); if (userName.getDB() == dbname) { queryBuilder.appendNull(AuthorizationManager::USER_SOURCE_FIELD_NAME); } else { queryBuilder.append(AuthorizationManager::USER_SOURCE_FIELD_NAME, userName.getDB()); } Status found = _findUser(usersNamespace, queryBuilder.obj(), &userBSONObj); if (!found.isOK()) { if (found.code() == ErrorCodes::UserNotFound) { // Return more detailed status that includes user name. return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "auth: couldn't find user " << userName.toString() << ", " << usersNamespace, 0); } else { return found; } } *result = userBSONObj.getOwned(); return Status::OK(); }
Status AuthzManagerExternalState::getPrivilegeDocumentV1(const StringData& dbname, const UserName& userName, BSONObj* result) { if (userName == internalSecurity.user->getName()) { return Status(ErrorCodes::InternalError, "Requested privilege document for the internal user"); } if (!NamespaceString::validDBName(dbname)) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << "Bad database name \"" << dbname << "\""); } const bool isUserFromTargetDB = (dbname == userName.getDB()); // Build the query needed to get the privilege document BSONObjBuilder queryBuilder; const NamespaceString usersNamespace(dbname, "system.users"); queryBuilder.append(AuthorizationManager::V1_USER_NAME_FIELD_NAME, userName.getUser()); if (isUserFromTargetDB) { queryBuilder.appendNull(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME); } else { queryBuilder.append(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME, userName.getDB()); } // Query for the privilege document BSONObj userBSONObj; Status found = findOne(usersNamespace, queryBuilder.done(), &userBSONObj); if (!found.isOK()) { if (found.code() == ErrorCodes::NoMatchingDocument) { // Return more detailed status that includes user name. return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "auth: couldn't find user " << userName.toString() << ", " << usersNamespace.ns(), 0); } else { return found; } } if (isUserFromTargetDB) { if (userBSONObj[AuthorizationManager::PASSWORD_FIELD_NAME].eoo()) { return Status(ErrorCodes::AuthSchemaIncompatible, mongoutils::str::stream() << "User documents with schema version " << AuthorizationManager::schemaVersion24 << " must have a \"" << AuthorizationManager::PASSWORD_FIELD_NAME << "\" field."); } } *result = userBSONObj.getOwned(); return Status::OK(); }
StatusWith<UserHandle> AuthorizationManagerImpl::acquireUserForSessionRefresh( OperationContext* opCtx, const UserName& userName, const User::UserId& uid) { auto swUserHandle = acquireUser(opCtx, userName); if (!swUserHandle.isOK()) { return swUserHandle.getStatus(); } auto ret = std::move(swUserHandle.getValue()); if (uid != ret->getID()) { return {ErrorCodes::UserNotFound, str::stream() << "User id from privilege document '" << userName.toString() << "' does not match user id in session."}; } return ret; }
Status AuthzManagerExternalState::getPrivilegeDocumentV1(const StringData& dbname, const UserName& userName, BSONObj* result) { if (userName == internalSecurity.user->getName()) { return Status(ErrorCodes::InternalError, "Requested privilege document for the internal user"); } if (!NamespaceString::validDBName(dbname)) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << "Bad database name \"" << dbname << "\""); } // Build the query needed to get the privilege document std::string usersNamespace; BSONObjBuilder queryBuilder; usersNamespace = mongoutils::str::stream() << dbname << ".system.users"; queryBuilder.append(AuthorizationManager::V1_USER_NAME_FIELD_NAME, userName.getUser()); if (dbname == userName.getDB()) { queryBuilder.appendNull(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME); } else { queryBuilder.append(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME, userName.getDB()); } // Query for the privilege document BSONObj userBSONObj; Status found = _findUser(usersNamespace, queryBuilder.done(), &userBSONObj); if (!found.isOK()) { if (found.code() == ErrorCodes::UserNotFound) { // Return more detailed status that includes user name. return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "auth: couldn't find user " << userName.toString() << ", " << usersNamespace, 0); } else { return found; } } *result = userBSONObj.getOwned(); return Status::OK(); }
Status AuthzManagerExternalStateMongos::getUserDescription( OperationContext* txn, const UserName& userName, BSONObj* result) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection( AuthorizationManager::usersCollectionNamespace)); BSONObj cmdResult; conn->get()->runCommand( "admin", BSON("usersInfo" << BSON_ARRAY(BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() << AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB())) << "showPrivileges" << true << "showCredentials" << true), cmdResult); if (!cmdResult["ok"].trueValue()) { int code = cmdResult["code"].numberInt(); if (code == 0) code = ErrorCodes::UnknownError; return Status(ErrorCodes::Error(code), cmdResult["errmsg"].str()); } std::vector<BSONElement> foundUsers = cmdResult["users"].Array(); if (foundUsers.size() == 0) { return Status(ErrorCodes::UserNotFound, "User \"" + userName.toString() + "\" not found"); } if (foundUsers.size() > 1) { return Status(ErrorCodes::UserDataInconsistent, mongoutils::str::stream() << "Found multiple users on the \"" << userName.getDB() << "\" database with name \"" << userName.getUser() << "\""); } *result = foundUsers[0].Obj().getOwned(); conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::getUserDescription(OperationContext* opCtx, const UserName& userName, BSONObj* result) { if (!shouldUseRolesFromConnection(opCtx, userName)) { BSONObj usersInfoCmd = BSON("usersInfo" << BSON_ARRAY(BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() << AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB())) << "showPrivileges" << true << "showCredentials" << true); BSONObjBuilder builder; const bool ok = Grid::get(opCtx)->catalogClient()->runUserManagementReadCommand( opCtx, "admin", usersInfoCmd, &builder); BSONObj cmdResult = builder.obj(); if (!ok) { return getStatusFromCommandResult(cmdResult); } std::vector<BSONElement> foundUsers = cmdResult["users"].Array(); if (foundUsers.size() == 0) { return Status(ErrorCodes::UserNotFound, "User \"" + userName.toString() + "\" not found"); } if (foundUsers.size() > 1) { return Status(ErrorCodes::UserDataInconsistent, str::stream() << "Found multiple users on the \"" << userName.getDB() << "\" database with name \"" << userName.getUser() << "\""); } *result = foundUsers[0].Obj().getOwned(); return Status::OK(); } else { // Obtain privilege information from the config servers for all roles acquired from the X509 // certificate. BSONArrayBuilder userRolesBuilder; auto& sslPeerInfo = SSLPeerInfo::forSession(opCtx->getClient()->session()); for (const RoleName& role : sslPeerInfo.roles) { userRolesBuilder.append(BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << role.getRole() << AuthorizationManager::ROLE_DB_FIELD_NAME << role.getDB())); } BSONArray providedRoles = userRolesBuilder.arr(); BSONObj rolesInfoCmd = BSON("rolesInfo" << providedRoles << "showPrivileges" << "asUserFragment"); BSONObjBuilder cmdResultBuilder; const bool cmdOk = Grid::get(opCtx)->catalogClient()->runUserManagementReadCommand( opCtx, "admin", rolesInfoCmd, &cmdResultBuilder); BSONObj cmdResult = cmdResultBuilder.obj(); if (!cmdOk || !cmdResult["userFragment"].ok()) { return Status(ErrorCodes::FailedToParse, "Unable to get resolved X509 roles from config server: " + getStatusFromCommandResult(cmdResult).toString()); } cmdResult = cmdResult["userFragment"].Obj().getOwned(); BSONElement userRoles = cmdResult["roles"]; BSONElement userInheritedRoles = cmdResult["inheritedRoles"]; BSONElement userInheritedPrivileges = cmdResult["inheritedPrivileges"]; if (userRoles.eoo() || userInheritedRoles.eoo() || userInheritedPrivileges.eoo() || !userRoles.isABSONObj() || !userInheritedRoles.isABSONObj() || !userInheritedPrivileges.isABSONObj()) { return Status( ErrorCodes::UserDataInconsistent, "Recieved malformed response to request for X509 roles from config server"); } *result = BSON("_id" << userName.getUser() << "user" << userName.getUser() << "db" << userName.getDB() << "credentials" << BSON("external" << true) << "roles" << BSONArray(cmdResult["roles"].Obj()) << "inheritedRoles" << BSONArray(cmdResult["inheritedRoles"].Obj()) << "inheritedPrivileges" << BSONArray(cmdResult["inheritedPrivileges"].Obj())); return Status::OK(); } }