Status AuthzManagerExternalStateMongod::_getUserDocument(const UserName& userName, BSONObj* userDoc) { Client::ReadContext ctx("admin"); int authzVersion; Status status = getStoredAuthorizationVersion(&authzVersion); if (!status.isOK()) return status; switch (authzVersion) { case AuthorizationManager::schemaVersion26Upgrade: case AuthorizationManager::schemaVersion26Final: break; default: return Status(ErrorCodes::AuthSchemaIncompatible, mongoutils::str::stream() << "Unsupported schema version for getUserDescription(): " << authzVersion); } status = findOne( (authzVersion == AuthorizationManager::schemaVersion26Final ? AuthorizationManager::usersCollectionNamespace : AuthorizationManager::usersAltCollectionNamespace), BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() << AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()), userDoc); if (status == ErrorCodes::NoMatchingDocument) { status = Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "Could not find user " << userName.getFullName()); } return status; }
Status AuthzManagerExternalStateMongos::updatePrivilegeDocument( const UserName& user, const BSONObj& updateObj) { try { string userNS = mongoutils::str::stream() << user.getDB() << ".system.users"; scoped_ptr<ScopedDbConnection> conn(getConnectionForUsersCollection(userNS)); conn->get()->update(userNS, QUERY("user" << user.getUser() << "userSource" << BSONNULL), updateObj); // 30 second timeout for w:majority BSONObj res = conn->get()->getLastErrorDetailed(false, false, -1, 30*1000); 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 AuthzManagerExternalStateMongod::updatePrivilegeDocument( const UserName& user, const BSONObj& updateObj) const { string userNS = mongoutils::str::stream() << user.getDB() << ".system.users"; Client::GodScope gs; Client::WriteContext ctx(userNS); DBDirectClient client; client.update(userNS, QUERY("user" << user.getUser() << "userSource" << BSONNULL), updateObj); // 30 second timeout for w:majority BSONObj res = client.getLastErrorDetailed(false, false, -1, 30*1000); string err = client.getLastErrorString(res); 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(); }
bool run(const string& dbname, BSONObj& cmdObj, int options, string& errmsg, BSONObjBuilder& result, bool fromRepl) { AuthorizationManager* authzManager = getGlobalAuthorizationManager(); AuthzDocumentsUpdateGuard updateGuard(authzManager); if (!updateGuard.tryLock("Remove user")) { addStatus(Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."), result); return false; } UserName userName; BSONObj writeConcern; Status status = auth::parseAndValidateRemoveUserCommand(cmdObj, dbname, &userName, &writeConcern); if (!status.isOK()) { addStatus(status, result); return false; } int numUpdated; status = authzManager->removePrivilegeDocuments( BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() << AuthorizationManager::USER_SOURCE_FIELD_NAME << userName.getDB()), writeConcern, &numUpdated); // Must invalidate even on bad status - what if the write succeeded but the GLE failed? authzManager->invalidateUserByName(userName); if (!status.isOK()) { addStatus(status, result); return false; } if (numUpdated == 0) { addStatus(Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "User '" << userName.getFullName() << "' not found"), result); return false; } return true; }
Status AuthzManagerExternalStateLocal::_getUserDocument(OperationContext* txn, const UserName& userName, BSONObj* userDoc) { Status status = findOne( txn, AuthorizationManager::usersCollectionNamespace, BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() << AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()), userDoc); if (status == ErrorCodes::NoMatchingDocument) { status = Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "Could not find user " << userName.getFullName()); } return status; }
Status AuthzManagerExternalStateMongod::updatePrivilegeDocument( const UserName& user, const BSONObj& updateObj, const BSONObj& writeConcern) { try { const std::string userNS = "admin.system.users"; DBDirectClient client; { Client::GodScope gs; // TODO(spencer): Once we're no longer fully rebuilding the user cache on every // change to user data we should remove the global lock and uncomment the // WriteContext below Lock::GlobalWrite w; // Client::WriteContext ctx(userNS); client.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; client.runCommand("admin", gleBuilder.done(), res); string err = client.getLastErrorString(res); 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 AuthzManagerExternalState::updatePrivilegeDocument( const UserName& user, const BSONObj& updateObj, const BSONObj& writeConcern) { Status status = updateOne( NamespaceString("admin.system.users"), BSON(AuthorizationManager::USER_NAME_FIELD_NAME << user.getUser() << AuthorizationManager::USER_DB_FIELD_NAME << user.getDB()), updateObj, false, writeConcern); if (status.isOK()) { return status; } if (status.code() == ErrorCodes::NoMatchingDocument) { return Status(ErrorCodes::UserNotFound, mongoutils::str::stream() << "User " << user.getFullName() << " not found"); } if (status.code() == ErrorCodes::UnknownError) { return Status(ErrorCodes::UserModificationFailed, status.reason()); } return status; }
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 AuthzManagerExternalStateMongod::updatePrivilegeDocument( const UserName& user, const BSONObj& updateObj) { try { string userNS = mongoutils::str::stream() << user.getDB() << ".system.users"; DBDirectClient client; { Client::GodScope gs; // TODO(spencer): Once we're no longer fully rebuilding the user cache on every // change to user data we should remove the global lock and uncomment the // WriteContext below Lock::GlobalWrite w; // Client::WriteContext ctx(userNS); client.update(userNS, QUERY("user" << user.getUser() << "userSource" << BSONNULL), updateObj); } // 30 second timeout for w:majority BSONObj res = client.getLastErrorDetailed(false, false, -1, 30*1000); string err = client.getLastErrorString(res); 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(); } }