Status AuthzManagerExternalStateMongos::getRoleDescription(const RoleName& roleName, BSONObj* result) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection( AuthorizationManager::rolesCollectionNamespace)); BSONObj cmdResult; conn->get()->runCommand( "admin", BSON("rolesInfo" << BSON_ARRAY(BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << roleName.getRole() << AuthorizationManager::ROLE_SOURCE_FIELD_NAME << roleName.getDB()))), cmdResult); if (!cmdResult["ok"].trueValue()) { int code = cmdResult["code"].numberInt(); if (code == 0) code = ErrorCodes::UnknownError; return Status(ErrorCodes::Error(code), cmdResult["errmsg"].str()); } *result = cmdResult["roles"]["0"].Obj().getOwned(); conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::createIndex( const NamespaceString& collectionName, const BSONObj& pattern, bool unique, const BSONObj& writeConcern) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName)); if (conn->get()->ensureIndex(collectionName.ns(), pattern, unique)) { // Handle write concern BSONObjBuilder gleBuilder; gleBuilder.append("getLastError", 1); gleBuilder.appendElements(writeConcern); BSONObj res; conn->get()->runCommand("admin", gleBuilder.done(), res); string err = conn->get()->getLastErrorString(res); if (!err.empty()) { conn->done(); return Status(ErrorCodes::UnknownError, err); } } conn->done(); return Status::OK(); } catch (const DBException& ex) { return ex.toStatus(); } }
Status AuthzManagerExternalStateMongos::insert( const NamespaceString& collectionName, const BSONObj& document, const BSONObj& writeConcern) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName)); conn->get()->insert(collectionName, document); // Handle write concern BSONObjBuilder gleBuilder; gleBuilder.append("getLastError", 1); gleBuilder.appendElements(writeConcern); BSONObj res; conn->get()->runCommand("admin", gleBuilder.done(), res); string errstr = conn->get()->getLastErrorString(res); conn->done(); if (errstr.empty()) { return Status::OK(); } if (res.hasField("code") && res["code"].Int() == ASSERT_ID_DUPKEY) { return Status(ErrorCodes::DuplicateKey, errstr); } return Status(ErrorCodes::UnknownError, errstr); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::remove( const NamespaceString& collectionName, const BSONObj& query, const BSONObj& writeConcern, int* numRemoved) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName)); conn->get()->remove(collectionName, query); // Handle write concern BSONObjBuilder gleBuilder; gleBuilder.append("getLastError", 1); gleBuilder.appendElements(writeConcern); BSONObj res; conn->get()->runCommand("admin", gleBuilder.done(), res); string err = conn->get()->getLastErrorString(res); conn->done(); if (!err.empty()) { return Status(ErrorCodes::UnknownError, err); } *numRemoved = res["n"].numberInt(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::removePrivilegeDocuments(const BSONObj& query, const BSONObj& writeConcern, int* numRemoved) { try { string userNS = "admin.system.users"; scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(userNS)); conn->get()->remove(userNS, query); // Handle write concern BSONObjBuilder gleBuilder; gleBuilder.append("getLastError", 1); gleBuilder.appendElements(writeConcern); BSONObj res; conn->get()->runCommand("admin", gleBuilder.done(), res); string err = conn->get()->getLastErrorString(res); conn->done(); if (!err.empty()) { return Status(ErrorCodes::UserModificationFailed, err); } *numRemoved = res["n"].numberInt(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::getUserDescription(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()); } *result = cmdResult["users"]["0"].Obj().getOwned(); conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::insertPrivilegeDocument(const string& dbname, const BSONObj& userObj, const BSONObj& writeConcern) { try { const std::string userNS = "admin.system.users"; scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(userNS)); conn->get()->insert(userNS, userObj); // Handle write concern BSONObjBuilder gleBuilder; gleBuilder.append("getLastError", 1); gleBuilder.appendElements(writeConcern); BSONObj res; conn->get()->runCommand("admin", gleBuilder.done(), res); string errstr = conn->get()->getLastErrorString(res); conn->done(); if (errstr.empty()) { return Status::OK(); } if (res.hasField("code") && res["code"].Int() == ASSERT_ID_DUPKEY) { std::string name = userObj[AuthorizationManager::USER_NAME_FIELD_NAME].String(); std::string source = userObj[AuthorizationManager::USER_SOURCE_FIELD_NAME].String(); return Status(ErrorCodes::DuplicateKey, mongoutils::str::stream() << "User \"" << name << "@" << source << "\" already exists"); } return Status(ErrorCodes::UserModificationFailed, errstr); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::getStoredAuthorizationVersion(int* outVersion) { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection( AuthorizationManager::usersCollectionNamespace)); Status status = auth::getRemoteStoredAuthorizationVersion(conn->get(), outVersion); conn->done(); return status; }
Status AuthzManagerExternalStateMongos::getRoleDescriptionsForDB(const std::string dbname, bool showPrivileges, bool showBuiltinRoles, vector<BSONObj>* result) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection( AuthorizationManager::rolesCollectionNamespace)); BSONObj cmdResult; conn->get()->runCommand( dbname, BSON("rolesInfo" << 1 << "showPrivileges" << showPrivileges << "showBuiltinRoles" << showBuiltinRoles), cmdResult); if (!cmdResult["ok"].trueValue()) { int code = cmdResult["code"].numberInt(); if (code == 0) code = ErrorCodes::UnknownError; return Status(ErrorCodes::Error(code), cmdResult["errmsg"].str()); } for (BSONObjIterator it(cmdResult["roles"].Obj()); it.more(); it.next()) { result->push_back((*it).Obj().getOwned()); } conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::query( const NamespaceString& collectionName, const BSONObj& query, const boost::function<void(const BSONObj&)>& resultProcessor) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName)); conn->get()->query(resultProcessor, collectionName.ns(), query); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::query( const NamespaceString& collectionName, const BSONObj& queryDoc, const BSONObj& projection, const stdx::function<void(const BSONObj&)>& resultProcessor) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName)); Query query(queryDoc); query.readPref(ReadPreference_PrimaryPreferred, BSONArray()); conn->get()->query(resultProcessor, collectionName.ns(), query, &projection); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::_findUser(const string& usersNamespace, const BSONObj& query, BSONObj* result) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(usersNamespace)); *result = conn->get()->findOne(usersNamespace, query).getOwned(); conn->done(); if (result->isEmpty()) { return userNotFoundStatus; } return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::getAllV1PrivilegeDocsForDB( const std::string& dbname, std::vector<BSONObj>* privDocs) { try { NamespaceString usersNamespace(dbname, "system.users"); scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(usersNamespace)); auto_ptr<DBClientCursor> c = conn->get()->query(usersNamespace, Query()); while (c->more()) { privDocs->push_back(c->nextSafe().getOwned()); } conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::findOne( const NamespaceString& collectionName, const BSONObj& queryDoc, BSONObj* result) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(collectionName)); Query query(queryDoc); query.readPref(ReadPreference_PrimaryPreferred, BSONArray()); *result = conn->get()->findOne(collectionName, query).getOwned(); conn->done(); if (result->isEmpty()) { return Status(ErrorCodes::NoMatchingDocument, mongoutils::str::stream() << "No document in " << collectionName.ns() << " matches " << queryDoc); } return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::getRoleDescription(const RoleName& roleName, bool showPrivileges, BSONObj* result) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection( AuthorizationManager::rolesCollectionNamespace)); BSONObj cmdResult; conn->get()->runCommand( "admin", BSON("rolesInfo" << BSON_ARRAY(BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << roleName.getRole() << AuthorizationManager::ROLE_SOURCE_FIELD_NAME << roleName.getDB())) << "showPrivileges" << showPrivileges), 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> foundRoles = cmdResult["roles"].Array(); if (foundRoles.size() == 0) { return Status(ErrorCodes::RoleNotFound, "Role \"" + roleName.toString() + "\" not found"); } if (foundRoles.size() > 1) { return Status(ErrorCodes::RoleDataInconsistent, mongoutils::str::stream() << "Found multiple roles on the \"" << roleName.getDB() << "\" database with name \"" << roleName.getRole() << "\""); } *result = foundRoles[0].Obj().getOwned(); conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
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(const UserName& userName, BSONObj* result) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection( AuthorizationManager::usersCollectionNamespace)); BSONObj cmdResult; conn->get()->runCommand( userName.getDB().toString(), // TODO: Change usersInfo so this command can always go to "admin". BSON("usersInfo" << userName.getUser() << "details" << 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()); } *result = cmdResult["users"]["0"].Obj().getOwned(); conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::getAllDatabaseNames( std::vector<std::string>* dbnames) { try { scoped_ptr<ScopedDbConnection> conn( getConnectionForAuthzCollection(NamespaceString(DatabaseType::ConfigNS))); auto_ptr<DBClientCursor> c = conn->get()->query(DatabaseType::ConfigNS, Query()); while (c->more()) { DatabaseType dbInfo; std::string errmsg; if (!dbInfo.parseBSON( c->nextSafe(), &errmsg) || !dbInfo.isValid( &errmsg )) { return Status(ErrorCodes::FailedToParse, errmsg); } dbnames->push_back(dbInfo.getName()); } conn->done(); dbnames->push_back("config"); // config db isn't listed in config.databases return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::updatePrivilegeDocument( const UserName& user, const BSONObj& updateObj, const BSONObj& writeConcern) { try { const std::string userNS = "admin.system.users"; scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection(userNS)); conn->get()->update( userNS, QUERY(AuthorizationManager::USER_NAME_FIELD_NAME << user.getUser() << AuthorizationManager::USER_SOURCE_FIELD_NAME << user.getDB()), updateObj); // Handle write concern BSONObjBuilder gleBuilder; gleBuilder.append("getLastError", 1); gleBuilder.appendElements(writeConcern); BSONObj res; conn->get()->runCommand("admin", gleBuilder.done(), res); string err = conn->get()->getLastErrorString(res); conn->done(); if (!err.empty()) { return Status(ErrorCodes::UserModificationFailed, err); } int numUpdated = res["n"].numberInt(); dassert(numUpdated <= 1 && numUpdated >= 0); if (numUpdated == 0) { return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "User " << user.getFullName() << " not found"); } return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }
Status AuthzManagerExternalStateMongos::getStoredAuthorizationVersion(int* outVersion) { try { scoped_ptr<ScopedDbConnection> conn(getConnectionForAuthzCollection( AuthorizationManager::usersCollectionNamespace)); BSONObj cmdResult; conn->get()->runCommand( "admin", BSON("getParameter" << 1 << AuthorizationManager::schemaVersionServerParameter << 1), cmdResult); if (!cmdResult["ok"].trueValue()) { std::string errmsg = cmdResult["errmsg"].str(); if (errmsg == "no option found to get" || StringData(errmsg).startsWith("no such cmd")) { *outVersion = 1; conn->done(); return Status::OK(); } int code = cmdResult["code"].numberInt(); if (code == 0) { code = ErrorCodes::UnknownError; } return Status(ErrorCodes::Error(code), errmsg); } BSONElement versionElement = cmdResult[AuthorizationManager::schemaVersionServerParameter]; if (versionElement.eoo()) return Status(ErrorCodes::UnknownError, "getParameter misbehaved."); *outVersion = versionElement.numberInt(); conn->done(); return Status::OK(); } catch (const DBException& e) { return e.toStatus(); } }