diff options
-rw-r--r-- | src/mongo/db/commands/user_management_commands.cpp | 282 |
1 files changed, 272 insertions, 10 deletions
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp index 710ac048fa2..7667ed9529d 100644 --- a/src/mongo/db/commands/user_management_commands.cpp +++ b/src/mongo/db/commands/user_management_commands.cpp @@ -95,6 +95,8 @@ namespace mongo { class CmdCreateUser : public Command { public: + CmdCreateUser() : Command("createUser") {} + virtual bool logTheOp() { return false; } @@ -107,8 +109,6 @@ namespace mongo { return NONE; } - CmdCreateUser() : Command("createUser") {} - virtual void help(stringstream& ss) const { ss << "Adds a user to the system" << endl; } @@ -163,6 +163,8 @@ namespace mongo { class CmdUpdateUser : public Command { public: + CmdUpdateUser() : Command("updateUser") {} + virtual bool logTheOp() { return false; } @@ -175,8 +177,6 @@ namespace mongo { return NONE; } - CmdUpdateUser() : Command("updateUser") {} - virtual void help(stringstream& ss) const { ss << "Used to update a user, for example to change its password" << endl; } @@ -235,6 +235,8 @@ namespace mongo { class CmdRemoveUser : public Command { public: + CmdRemoveUser() : Command("removeUser") {} + virtual bool logTheOp() { return false; } @@ -247,8 +249,6 @@ namespace mongo { return NONE; } - CmdRemoveUser() : Command("removeUser") {} - virtual void help(stringstream& ss) const { ss << "Removes a single user." << endl; } @@ -312,6 +312,8 @@ namespace mongo { class CmdRemoveUsersFromDatabase : public Command { public: + CmdRemoveUsersFromDatabase() : Command("removeUsersFromDatabase") {} + virtual bool logTheOp() { return false; } @@ -324,8 +326,6 @@ namespace mongo { return NONE; } - CmdRemoveUsersFromDatabase() : Command("removeUsersFromDatabase") {} - virtual void help(stringstream& ss) const { ss << "Removes all users for a single database." << endl; } @@ -374,6 +374,8 @@ namespace mongo { class CmdGrantRolesToUser: public Command { public: + CmdGrantRolesToUser() : Command("grantRolesToUser") {} + virtual bool logTheOp() { return false; } @@ -386,8 +388,6 @@ namespace mongo { return NONE; } - CmdGrantRolesToUser() : Command("grantRolesToUser") {} - virtual void help(stringstream& ss) const { ss << "Grants roles to a user." << endl; } @@ -452,4 +452,266 @@ namespace mongo { } } CmdGrantRolesToUser; + + class CmdRevokeRolesFromUser: public Command { + public: + + CmdRevokeRolesFromUser() : Command("revokeRolesFromUser") {} + + virtual bool logTheOp() { + return false; + } + + virtual bool slaveOk() const { + return false; + } + + virtual LockType locktype() const { + return NONE; + } + + virtual void help(stringstream& ss) const { + ss << "Revokes roles from a user." << endl; + } + + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + // TODO: update this with the new rules around user creation in 2.6. + ActionSet actions; + actions.addAction(ActionType::userAdmin); + out->push_back(Privilege(dbname, actions)); + } + + bool run(const string& dbname, + BSONObj& cmdObj, + int options, + string& errmsg, + BSONObjBuilder& result, + bool fromRepl) { + UserName userName; + std::vector<RoleName> roles; + BSONObj writeConcern; + AuthorizationManager* authzManager = getGlobalAuthorizationManager(); + Status status = auth::parseUserRoleManipulationCommand(cmdObj, + "revokeRolesFromUser", + dbname, + authzManager, + &userName, + &roles, + &writeConcern); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + User::RoleDataMap userRoles; + status = getCurrentUserRoles(authzManager, userName, &userRoles); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + for (vector<RoleName>::iterator it = roles.begin(); it != roles.end(); ++it) { + RoleName& roleName = *it; + User::RoleDataMap::iterator roleDataIt = userRoles.find(roleName); + if (roleDataIt == userRoles.end()) { + continue; // User already doesn't have the role, nothing to do + } + User::RoleData& role = roleDataIt->second; + if (role.canDelegate) { + // If the user can still delegate the role, need to leave it in the roles array + role.hasRole = false; + } else { + // If the user can't delegate the role, and now doesn't have it either, remove + // the role from that user's roles array entirely + userRoles.erase(roleDataIt); + } + } + + BSONArray newRolesBSONArray = rolesToBSONArray(userRoles); + status = authzManager->updatePrivilegeDocument( + userName, BSON("$set" << BSON("roles" << newRolesBSONArray)), writeConcern); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + authzManager->invalidateUserByName(userName); + return true; + } + + } CmdRevokeRolesFromUser; + + class CmdGrantDelegateRolesToUser: public Command { + public: + + CmdGrantDelegateRolesToUser() : Command("grantDelegateRolesToUser") {} + + virtual bool logTheOp() { + return false; + } + + virtual bool slaveOk() const { + return false; + } + + virtual LockType locktype() const { + return NONE; + } + + virtual void help(stringstream& ss) const { + ss << "Grants the right to delegate roles to a user." << endl; + } + + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + // TODO: update this with the new rules around user creation in 2.6. + ActionSet actions; + actions.addAction(ActionType::userAdmin); + out->push_back(Privilege(dbname, actions)); + } + + bool run(const string& dbname, + BSONObj& cmdObj, + int options, + string& errmsg, + BSONObjBuilder& result, + bool fromRepl) { + UserName userName; + std::vector<RoleName> roles; + BSONObj writeConcern; + AuthorizationManager* authzManager = getGlobalAuthorizationManager(); + Status status = auth::parseUserRoleManipulationCommand(cmdObj, + "grantDelegateRolesToUser", + dbname, + authzManager, + &userName, + &roles, + &writeConcern); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + User::RoleDataMap userRoles; + status = getCurrentUserRoles(authzManager, userName, &userRoles); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + for (vector<RoleName>::iterator it = roles.begin(); it != roles.end(); ++it) { + RoleName& roleName = *it; + User::RoleData& role = userRoles[roleName]; + if (role.name.empty()) { + role.name = roleName; + } + role.canDelegate = true; + } + + BSONArray newRolesBSONArray = rolesToBSONArray(userRoles); + status = authzManager->updatePrivilegeDocument( + userName, BSON("$set" << BSON("roles" << newRolesBSONArray)), writeConcern); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + authzManager->invalidateUserByName(userName); + return true; + } + + } CmdGrantDelegateRolesToUser; + + class CmdRevokeDelegateRolesFromUser: public Command { + public: + + CmdRevokeDelegateRolesFromUser() : Command("revokeDelegateRolesFromUser") {} + + virtual bool logTheOp() { + return false; + } + + virtual bool slaveOk() const { + return false; + } + + virtual LockType locktype() const { + return NONE; + } + + virtual void help(stringstream& ss) const { + ss << "Revokes the right to delegate roles from a user." << endl; + } + + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + // TODO: update this with the new rules around user creation in 2.6. + ActionSet actions; + actions.addAction(ActionType::userAdmin); + out->push_back(Privilege(dbname, actions)); + } + + bool run(const string& dbname, + BSONObj& cmdObj, + int options, + string& errmsg, + BSONObjBuilder& result, + bool fromRepl) { + UserName userName; + std::vector<RoleName> roles; + BSONObj writeConcern; + AuthorizationManager* authzManager = getGlobalAuthorizationManager(); + Status status = auth::parseUserRoleManipulationCommand(cmdObj, + "revokeDelegateRolesFromUser", + dbname, + authzManager, + &userName, + &roles, + &writeConcern); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + User::RoleDataMap userRoles; + status = getCurrentUserRoles(authzManager, userName, &userRoles); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + for (vector<RoleName>::iterator it = roles.begin(); it != roles.end(); ++it) { + RoleName& roleName = *it; + User::RoleDataMap::iterator roleDataIt = userRoles.find(roleName); + if (roleDataIt == userRoles.end()) { + continue; // User already doesn't have the role, nothing to do + } + User::RoleData& role = roleDataIt->second; + if (role.hasRole) { + // If the user still has the role, need to leave it in the roles array + role.canDelegate = false; + } else { + // If the user doesn't have the role, and now can't delegate it either, remove + // the role from that user's roles array entirely + userRoles.erase(roleDataIt); + } + } + + BSONArray newRolesBSONArray = rolesToBSONArray(userRoles); + status = authzManager->updatePrivilegeDocument( + userName, BSON("$set" << BSON("roles" << newRolesBSONArray)), writeConcern); + if (!status.isOK()) { + addStatus(status, result); + return false; + } + + authzManager->invalidateUserByName(userName); + return true; + } + + } CmdRevokeDelegateRolesFromUser; } |