From d3df81cac59e3dd216c60e87b74ac7c444343201 Mon Sep 17 00:00:00 2001 From: Kaloian Manassiev Date: Tue, 25 Feb 2020 06:30:34 -0500 Subject: SERVER-44978 Move the "cache generation" to AuthorizationManagerImpl The "cache generation" concept is something specific to the Authorization Manager and doesn't fit with an asynchronous (non totally-ordered cache). This change moves it out of the ReadThroughCache and makes it an AuthorizationManager concept. --- src/mongo/db/auth/authorization_manager.h | 7 +- src/mongo/db/auth/authorization_manager_impl.cpp | 14 +- src/mongo/db/auth/authorization_manager_impl.h | 17 +- src/mongo/db/commands/user_management_commands.cpp | 301 ++++++++++----------- src/mongo/db/commands/user_management_commands.h | 139 ---------- .../commands/user_management_commands_common.cpp | 2 +- .../db/commands/user_management_commands_common.h | 138 ++++++++++ .../commands/cluster_user_management_commands.cpp | 2 +- src/mongo/util/read_through_cache.cpp | 5 - src/mongo/util/read_through_cache.h | 12 +- 10 files changed, 312 insertions(+), 325 deletions(-) delete mode 100644 src/mongo/db/commands/user_management_commands.h create mode 100644 src/mongo/db/commands/user_management_commands_common.h (limited to 'src/mongo') diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h index a14122cad30..7f8d1a8197c 100644 --- a/src/mongo/db/auth/authorization_manager.h +++ b/src/mongo/db/auth/authorization_manager.h @@ -186,7 +186,12 @@ public: virtual Status getAuthorizationVersion(OperationContext* opCtx, int* version) = 0; /** - * Returns the user cache generation identifier. + * The value reported by this method must change every time some persisted authorization rule + * gets modified. It serves as a means for consumers of authorization data to discover that + * something changed and that they need to re-cache. + * + * The most prominent consumer of this value is MongoS, which uses it to determine whether it + * needs to re-fetch the authentication info from the config server. */ virtual OID getCacheGeneration() = 0; diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp index ec3c90bcc99..9fa3ae2bcf5 100644 --- a/src/mongo/db/auth/authorization_manager_impl.cpp +++ b/src/mongo/db/auth/authorization_manager_impl.cpp @@ -364,7 +364,8 @@ Status AuthorizationManagerImpl::getAuthorizationVersion(OperationContext* opCtx } OID AuthorizationManagerImpl::getCacheGeneration() { - return _userCache.getCacheGeneration(); + stdx::lock_guard lg(_cacheGenerationMutex); + return _cacheGeneration; } void AuthorizationManagerImpl::setAuthEnabled(bool enabled) { @@ -472,6 +473,11 @@ void AuthorizationManagerImpl::updatePinnedUsersList(std::vector names }); } +void AuthorizationManagerImpl::_updateCacheGeneration() { + stdx::lock_guard lg(_cacheGenerationMutex); + _cacheGeneration = OID::gen(); +} + void AuthorizationManagerImpl::_pinnedUsersThreadRoutine() noexcept try { Client::initThread("PinnedUsersTracker"); std::list pinnedUsers; @@ -561,19 +567,21 @@ void AuthorizationManagerImpl::_pinnedUsersThreadRoutine() noexcept try { void AuthorizationManagerImpl::invalidateUserByName(OperationContext* opCtx, const UserName& userName) { LOGV2_DEBUG(20235, 2, "Invalidating user {userName}", "userName"_attr = userName); + _updateCacheGeneration(); _authSchemaVersionCache.invalidateAll(); _userCache.invalidate(userName); } void AuthorizationManagerImpl::invalidateUsersFromDB(OperationContext* opCtx, StringData dbname) { LOGV2_DEBUG(20236, 2, "Invalidating all users from database {dbname}", "dbname"_attr = dbname); + _updateCacheGeneration(); _authSchemaVersionCache.invalidateAll(); - _userCache.invalidateIf( - [&](const UserName& user, const User*) { return user.getDB() == dbname; }); + _userCache.invalidateIf([&](const UserName& user) { return user.getDB() == dbname; }); } void AuthorizationManagerImpl::invalidateUserCache(OperationContext* opCtx) { LOGV2_DEBUG(20237, 2, "Invalidating user cache"); + _updateCacheGeneration(); _authSchemaVersionCache.invalidateAll(); _userCache.invalidateAll(); } diff --git a/src/mongo/db/auth/authorization_manager_impl.h b/src/mongo/db/auth/authorization_manager_impl.h index 72f7e8f6969..88a62210097 100644 --- a/src/mongo/db/auth/authorization_manager_impl.h +++ b/src/mongo/db/auth/authorization_manager_impl.h @@ -121,16 +121,7 @@ public: std::vector getUserCacheInfo() const override; private: - /** - * Given the objects describing an oplog entry that affects authorization data, invalidates - * the portion of the user cache that is affected by that operation. Should only be called - * with oplog entries that have been pre-verified to actually affect authorization data. - */ - void _invalidateRelevantCacheData(OperationContext* opCtx, - const char* op, - const NamespaceString& ns, - const BSONObj& o, - const BSONObj* o2); + void _updateCacheGeneration(); void _pinnedUsersThreadRoutine() noexcept; @@ -151,6 +142,12 @@ private: // storage ThreadPool _threadPool; + // Serves as a source for the return value of getCacheGeneration(). Refer to this method for + // more details. + Mutex _cacheGenerationMutex = + MONGO_MAKE_LATCH("AuthorizationManagerImpl::_cacheGenerationMutex"); + OID _cacheGeneration{OID::gen()}; + /** * Cache which contains at most a single entry (which has key 0), whose value is the version of * the auth schema. diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp index e6eaa321fff..23681e211e1 100644 --- a/src/mongo/db/commands/user_management_commands.cpp +++ b/src/mongo/db/commands/user_management_commands.cpp @@ -31,8 +31,6 @@ #include "mongo/platform/basic.h" -#include "mongo/db/commands/user_management_commands.h" - #include #include #include @@ -50,7 +48,6 @@ #include "mongo/db/auth/address_restriction.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_session.h" -#include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege_parser.h" #include "mongo/db/auth/resource_pattern.h" #include "mongo/db/auth/sasl_options.h" @@ -60,6 +57,7 @@ #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/commands/run_aggregate.h" +#include "mongo/db/commands/user_management_commands_common.h" #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/jsobj.h" @@ -81,12 +79,6 @@ #include "mongo/util/uuid.h" namespace mongo { - -using std::endl; -using std::string; -using std::stringstream; -using std::vector; - namespace { Status useDefaultCode(const Status& status, ErrorCodes::Error defaultCode) { @@ -766,9 +758,6 @@ Status trimCredentials(OperationContext* opCtx, return Status::OK(); } -} // namespace - - class CmdCreateUser : public BasicCommand { public: CmdCreateUser() : BasicCommand("createUser") {} @@ -777,7 +766,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -785,16 +774,16 @@ public: return "Adds a user to the system"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForCreateUserCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { auth::CreateOrUpdateUserArgs args; Status status = auth::parseCreateOrUpdateUserCommands(cmdObj, "createUser", dbname, &args); uassertStatusOK(status); @@ -899,7 +888,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -907,16 +896,16 @@ public: return "Used to update a user, for example to change its password"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForUpdateUserCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { auth::CreateOrUpdateUserArgs args; Status status = auth::parseCreateOrUpdateUserCommands(cmdObj, "updateUser", dbname, &args); uassertStatusOK(status); @@ -1012,6 +1001,7 @@ public: StringData sensitiveFieldName() const final { return "pwd"_sd; } + } cmdUpdateUser; class CmdDropUser : public BasicCommand { @@ -1022,7 +1012,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1030,16 +1020,16 @@ public: return "Drops a single user."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForDropUserCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { UserName userName; Status status = auth::parseAndValidateDropUserCommand(cmdObj, dbname, &userName); uassertStatusOK(status); @@ -1080,7 +1070,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1088,16 +1078,16 @@ public: return "Drops all users for a single database."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForDropAllUsersFromDatabaseCommand(client, dbname); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { Status status = auth::parseAndValidateDropAllUsersFromDatabaseCommand(cmdObj, dbname); uassertStatusOK(status); ServiceContext* serviceContext = opCtx->getClient()->getServiceContext(); @@ -1128,7 +1118,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1136,16 +1126,16 @@ public: return "Grants roles to a user."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForGrantRolesToUserCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { std::string userNameString; std::vector roles; Status status = auth::parseRolePossessionManipulationCommands( @@ -1162,7 +1152,7 @@ public: status = getCurrentUserRoles(opCtx, authzManager, userName, &userRoles); uassertStatusOK(status); - for (vector::iterator it = roles.begin(); it != roles.end(); ++it) { + for (std::vector::iterator it = roles.begin(); it != roles.end(); ++it) { RoleName& roleName = *it; BSONObj roleDoc; status = authzManager->getRoleDescription(opCtx, roleName, &roleDoc); @@ -1191,7 +1181,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1199,16 +1189,16 @@ public: return "Revokes roles from a user."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForRevokeRolesFromUserCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { std::string userNameString; std::vector roles; Status status = auth::parseRolePossessionManipulationCommands( @@ -1225,7 +1215,7 @@ public: status = getCurrentUserRoles(opCtx, authzManager, userName, &userRoles); uassertStatusOK(status); - for (vector::iterator it = roles.begin(); it != roles.end(); ++it) { + for (std::vector::iterator it = roles.begin(); it != roles.end(); ++it) { RoleName& roleName = *it; BSONObj roleDoc; status = authzManager->getRoleDescription(opCtx, roleName, &roleDoc); @@ -1248,30 +1238,30 @@ public: class CmdUsersInfo : public BasicCommand { public: + CmdUsersInfo() : BasicCommand("usersInfo") {} + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { return AllowedOnSecondary::kOptIn; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return false; } - CmdUsersInfo() : BasicCommand("usersInfo") {} - std::string help() const override { return "Returns information about users."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForUsersInfoCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { auth::UsersInfoArgs args; Status status = auth::parseUsersInfoCommand(cmdObj, dbname, &args); uassertStatusOK(status); @@ -1410,7 +1400,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1418,16 +1408,16 @@ public: return "Adds a role to the system"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForCreateRoleCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { auth::CreateOrUpdateRoleArgs args; Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "createRole", dbname, &args); uassertStatusOK(status); @@ -1510,7 +1500,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1518,16 +1508,16 @@ public: return "Used to update a role"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForUpdateRoleCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { auth::CreateOrUpdateRoleArgs args; Status status = auth::parseCreateOrUpdateRoleCommands(cmdObj, "updateRole", dbname, &args); uassertStatusOK(status); @@ -1602,6 +1592,7 @@ public: uassertStatusOK(status); return true; } + } cmdUpdateRole; class CmdGrantPrivilegesToRole : public BasicCommand { @@ -1612,7 +1603,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1620,17 +1611,16 @@ public: return "Grants privileges to a role"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForGrantPrivilegesToRoleCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { - + BSONObjBuilder& result) override { RoleName roleName; PrivilegeVector privilegesToAdd; Status status = auth::parseAndValidateRolePrivilegeManipulationCommands( @@ -1703,7 +1693,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1711,16 +1701,16 @@ public: return "Revokes privileges from a role"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForRevokePrivilegesFromRoleCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { RoleName roleName; PrivilegeVector privilegesToRemove; Status status = auth::parseAndValidateRolePrivilegeManipulationCommands( @@ -1797,7 +1787,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1805,16 +1795,16 @@ public: return "Grants roles to another role."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForGrantRolesToRoleCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { std::string roleNameString; std::vector rolesToAdd; Status status = auth::parseRolePossessionManipulationCommands( @@ -1847,7 +1837,7 @@ public: status = auth::parseRoleNamesFromBSONArray( BSONArray(roleDoc["roles"].Obj()), roleName.getDB(), &directRoles); uassertStatusOK(status); - for (vector::iterator it = rolesToAdd.begin(); it != rolesToAdd.end(); ++it) { + for (auto it = rolesToAdd.begin(); it != rolesToAdd.end(); ++it) { const RoleName& roleToAdd = *it; if (!sequenceContains(directRoles, roleToAdd)) // Don't double-add role directRoles.push_back(*it); @@ -1873,7 +1863,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1881,16 +1871,16 @@ public: return "Revokes roles from another role."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForRevokeRolesFromRoleCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { std::string roleNameString; std::vector rolesToRemove; Status status = auth::parseRolePossessionManipulationCommands( @@ -1918,9 +1908,10 @@ public: BSONArray(roleDoc["roles"].Obj()), roleName.getDB(), &roles); uassertStatusOK(status); - for (vector::const_iterator it = rolesToRemove.begin(); it != rolesToRemove.end(); + for (std::vector::const_iterator it = rolesToRemove.begin(); + it != rolesToRemove.end(); ++it) { - vector::iterator itToRm = std::find(roles.begin(), roles.end(), *it); + std::vector::iterator itToRm = std::find(roles.begin(), roles.end(), *it); if (itToRm != roles.end()) { roles.erase(itToRm); } @@ -1946,7 +1937,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -1957,16 +1948,16 @@ public: "removed from some user/roles but otherwise still exists."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForDropRoleCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { RoleName roleName; Status status = auth::parseDropRoleCommand(cmdObj, dbname, &roleName); uassertStatusOK(status); @@ -2078,7 +2069,7 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } @@ -2090,16 +2081,16 @@ public: "exist."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForDropAllRolesFromDatabaseCommand(client, dbname); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { Status status = auth::parseDropAllRolesFromDatabaseCommand(cmdObj, dbname); uassertStatusOK(status); @@ -2195,33 +2186,32 @@ public: * these roles. This format may change over time with changes to the auth * schema. */ - class CmdRolesInfo : public BasicCommand { public: + CmdRolesInfo() : BasicCommand("rolesInfo") {} + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { return AllowedOnSecondary::kOptIn; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return false; } - CmdRolesInfo() : BasicCommand("rolesInfo") {} - std::string help() const override { return "Returns information about roles."; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForRolesInfoCommand(client, dbname, cmdObj); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { auth::RolesInfoArgs args; Status status = auth::parseRolesInfoCommand(cmdObj, dbname, &args); uassertStatusOK(status); @@ -2271,34 +2261,34 @@ public: class CmdInvalidateUserCache : public BasicCommand { public: + CmdInvalidateUserCache() : BasicCommand("invalidateUserCache") {} + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { return AllowedOnSecondary::kAlways; } - virtual bool adminOnly() const { + bool adminOnly() const override { return true; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return false; } - CmdInvalidateUserCache() : BasicCommand("invalidateUserCache") {} - std::string help() const override { return "Invalidates the in-memory cache of user information"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForInvalidateUserCacheCommand(client); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { AuthorizationManager* authzManager = AuthorizationManager::get(opCtx->getServiceContext()); auto lk = requireReadableAuthSchema26Upgrade(opCtx, authzManager); authzManager->invalidateUserCache(opCtx); @@ -2309,40 +2299,40 @@ public: class CmdGetCacheGeneration : public BasicCommand { public: + CmdGetCacheGeneration() : BasicCommand("_getUserCacheGeneration") {} + AllowedOnSecondary secondaryAllowed(ServiceContext*) const override { return AllowedOnSecondary::kAlways; } - virtual bool adminOnly() const { + bool adminOnly() const override { return true; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return false; } - CmdGetCacheGeneration() : BasicCommand("_getUserCacheGeneration") {} - std::string help() const override { return "internal"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForGetUserCacheGenerationCommand(client); } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { AuthorizationManager* authzManager = AuthorizationManager::get(opCtx->getServiceContext()); result.append("cacheGeneration", authzManager->getCacheGeneration()); return true; } -} CmdGetCacheGeneration; +} cmdGetCacheGeneration; /** * This command is used only by mongorestore to handle restoring users/roles. We do this so @@ -2362,11 +2352,11 @@ public: return AllowedOnSecondary::kNever; } - virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + bool supportsWriteConcern(const BSONObj& cmd) const override { return true; } - virtual bool adminOnly() const { + bool adminOnly() const { return true; } @@ -2374,9 +2364,9 @@ public: return "Internal command used by mongorestore for updating user/role data"; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) const { + Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) const override { return auth::checkAuthForMergeAuthzCollectionsCommand(client, cmdObj); } @@ -2563,11 +2553,11 @@ public: * Moves all user objects from usersCollName into admin.system.users. If drop is true, * removes any users that were in admin.system.users but not in usersCollName. */ - Status processUsers(OperationContext* opCtx, - AuthorizationManager* authzManager, - StringData usersCollName, - StringData db, - bool drop) { + static Status processUsers(OperationContext* opCtx, + AuthorizationManager* authzManager, + StringData usersCollName, + StringData db, + bool drop) { // When the "drop" argument has been provided, we use this set to store the users // that are currently in the system, and remove from it as we encounter // same-named users in the collection we are restoring from. Once we've fully @@ -2635,11 +2625,11 @@ public: * Moves all user objects from usersCollName into admin.system.users. If drop is true, * removes any users that were in admin.system.users but not in usersCollName. */ - Status processRoles(OperationContext* opCtx, - AuthorizationManager* authzManager, - StringData rolesCollName, - StringData db, - bool drop) { + static Status processRoles(OperationContext* opCtx, + AuthorizationManager* authzManager, + StringData rolesCollName, + StringData db, + bool drop) { // When the "drop" argument has been provided, we use this set to store the roles // that are currently in the system, and remove from it as we encounter // same-named roles in the collection we are restoring from. Once we've fully @@ -2706,9 +2696,9 @@ public: } bool run(OperationContext* opCtx, - const string& dbname, + const std::string& dbname, const BSONObj& cmdObj, - BSONObjBuilder& result) { + BSONObjBuilder& result) override { auth::MergeAuthzCollectionsArgs args; Status status = auth::parseMergeAuthzCollectionsCommand(cmdObj, &args); uassertStatusOK(status); @@ -2752,4 +2742,5 @@ public: } cmdMergeAuthzCollections; +} // namespace } // namespace mongo diff --git a/src/mongo/db/commands/user_management_commands.h b/src/mongo/db/commands/user_management_commands.h deleted file mode 100644 index 41f4203b492..00000000000 --- a/src/mongo/db/commands/user_management_commands.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * . - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include -#include - -#include "mongo/bson/mutable/element.h" -#include "mongo/db/auth/privilege.h" -#include "mongo/db/auth/role_name.h" -#include "mongo/db/auth/user_name.h" - -namespace mongo { - -class AuthorizationManager; -class AuthorizationSession; -struct BSONArray; -class BSONObj; -class Client; -class OperationContext; - -namespace auth { - -// -// checkAuthorizedTo* methods -// - -Status checkAuthorizedToGrantRoles(AuthorizationSession* authzSession, - const std::vector& roles); - -Status checkAuthorizedToGrantPrivileges(AuthorizationSession* authzSession, - const PrivilegeVector& privileges); - -Status checkAuthorizedToRevokeRoles(AuthorizationSession* authzSession, - const std::vector& roles); - -Status checkAuthorizedToRevokePrivileges(AuthorizationSession* authzSession, - const PrivilegeVector& privileges); - -// -// checkAuthFor*Command methods -// - -Status checkAuthForCreateUserCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForUpdateUserCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForGrantRolesToUserCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForCreateRoleCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForUpdateRoleCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForGrantRolesToRoleCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForGrantPrivilegesToRoleCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForDropAllUsersFromDatabaseCommand(Client* client, const std::string& dbname); - -Status checkAuthForRevokeRolesFromUserCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForRevokeRolesFromRoleCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForDropUserCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForDropRoleCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - - -Status checkAuthForUsersInfoCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForRevokePrivilegesFromRoleCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForDropAllRolesFromDatabaseCommand(Client* client, const std::string& dbname); - -Status checkAuthForRolesInfoCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj); - -Status checkAuthForInvalidateUserCacheCommand(Client* client); - -Status checkAuthForGetUserCacheGenerationCommand(Client* client); - -Status checkAuthForMergeAuthzCollectionsCommand(Client* client, const BSONObj& cmdObj); - -} // namespace auth -} // namespace mongo diff --git a/src/mongo/db/commands/user_management_commands_common.cpp b/src/mongo/db/commands/user_management_commands_common.cpp index 36d6963074f..0b0a38f1390 100644 --- a/src/mongo/db/commands/user_management_commands_common.cpp +++ b/src/mongo/db/commands/user_management_commands_common.cpp @@ -31,7 +31,7 @@ #include "mongo/platform/basic.h" -#include "mongo/db/commands/user_management_commands.h" +#include "mongo/db/commands/user_management_commands_common.h" #include #include diff --git a/src/mongo/db/commands/user_management_commands_common.h b/src/mongo/db/commands/user_management_commands_common.h new file mode 100644 index 00000000000..4ddeec5be1c --- /dev/null +++ b/src/mongo/db/commands/user_management_commands_common.h @@ -0,0 +1,138 @@ +/** + * Copyright (C) 2018-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include +#include + +#include "mongo/bson/mutable/element.h" +#include "mongo/db/auth/privilege.h" +#include "mongo/db/auth/role_name.h" +#include "mongo/db/auth/user_name.h" + +namespace mongo { + +class AuthorizationSession; +struct BSONArray; +class BSONObj; +class Client; +class OperationContext; + +namespace auth { + +// +// checkAuthorizedTo* methods +// + +Status checkAuthorizedToGrantRoles(AuthorizationSession* authzSession, + const std::vector& roles); + +Status checkAuthorizedToGrantPrivileges(AuthorizationSession* authzSession, + const PrivilegeVector& privileges); + +Status checkAuthorizedToRevokeRoles(AuthorizationSession* authzSession, + const std::vector& roles); + +Status checkAuthorizedToRevokePrivileges(AuthorizationSession* authzSession, + const PrivilegeVector& privileges); + +// +// checkAuthFor*Command methods +// + +Status checkAuthForCreateUserCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForUpdateUserCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForGrantRolesToUserCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForCreateRoleCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForUpdateRoleCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForGrantRolesToRoleCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForGrantPrivilegesToRoleCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForDropAllUsersFromDatabaseCommand(Client* client, const std::string& dbname); + +Status checkAuthForRevokeRolesFromUserCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForRevokeRolesFromRoleCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForDropUserCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForDropRoleCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + + +Status checkAuthForUsersInfoCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForRevokePrivilegesFromRoleCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForDropAllRolesFromDatabaseCommand(Client* client, const std::string& dbname); + +Status checkAuthForRolesInfoCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + +Status checkAuthForInvalidateUserCacheCommand(Client* client); + +Status checkAuthForGetUserCacheGenerationCommand(Client* client); + +Status checkAuthForMergeAuthzCollectionsCommand(Client* client, const BSONObj& cmdObj); + +} // namespace auth +} // namespace mongo diff --git a/src/mongo/s/commands/cluster_user_management_commands.cpp b/src/mongo/s/commands/cluster_user_management_commands.cpp index 58384e84755..664c6d4de11 100644 --- a/src/mongo/s/commands/cluster_user_management_commands.cpp +++ b/src/mongo/s/commands/cluster_user_management_commands.cpp @@ -37,7 +37,7 @@ #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/user_management_commands_parser.h" #include "mongo/db/commands.h" -#include "mongo/db/commands/user_management_commands.h" +#include "mongo/db/commands/user_management_commands_common.h" #include "mongo/db/jsobj.h" #include "mongo/rpc/write_concern_error_detail.h" #include "mongo/s/catalog/type_shard.h" diff --git a/src/mongo/util/read_through_cache.cpp b/src/mongo/util/read_through_cache.cpp index 877421fac9e..d2bee26d104 100644 --- a/src/mongo/util/read_through_cache.cpp +++ b/src/mongo/util/read_through_cache.cpp @@ -42,11 +42,6 @@ ReadThroughCacheBase::ReadThroughCacheBase(Mutex& mutex, ReadThroughCacheBase::~ReadThroughCacheBase() = default; -OID ReadThroughCacheBase::getCacheGeneration() const { - stdx::lock_guard lk(_cacheWriteMutex); - return _fetchGeneration; -} - void ReadThroughCacheBase::_asyncWork(WorkWithOpContext work) { _threadPool.schedule([this, work = std::move(work)](Status status) { ThreadClient tc(_serviceContext); diff --git a/src/mongo/util/read_through_cache.h b/src/mongo/util/read_through_cache.h index 54e5d4bfc45..bf8b377f6ec 100644 --- a/src/mongo/util/read_through_cache.h +++ b/src/mongo/util/read_through_cache.h @@ -48,12 +48,6 @@ class ReadThroughCacheBase { ReadThroughCacheBase(const ReadThroughCacheBase&) = delete; ReadThroughCacheBase& operator=(const ReadThroughCacheBase&) = delete; -public: - /** - * Returns the cache generation identifier. - */ - OID getCacheGeneration() const; - protected: ReadThroughCacheBase(Mutex& mutex, ServiceContext* service, ThreadPoolInterface& threadPool); @@ -380,13 +374,11 @@ public: void invalidateIf(const Pred& predicate) { CacheGuard guard(this); _updateCacheGeneration(guard); - _cache.invalidateIf([&](const Key& key, const StoredValue* storedValue) { - return predicate(key, &storedValue->value); - }); + _cache.invalidateIf([&](const Key& key, const StoredValue*) { return predicate(key); }); } void invalidateAll() { - invalidateIf([](const Key&, const Value*) { return true; }); + invalidateIf([](const Key&) { return true; }); } /** -- cgit v1.2.1