diff options
author | Spencer T Brody <spencer@10gen.com> | 2013-09-30 18:40:39 -0400 |
---|---|---|
committer | Spencer T Brody <spencer@10gen.com> | 2013-10-04 17:17:51 -0400 |
commit | d09e608691aae000f3176b27cc67a7900229cd1e (patch) | |
tree | 8740c59feef65ab28b7b8dc55fc85996a71acaed /src/mongo/db/auth | |
parent | e0f70cdb67a36c831a23b452e7b9fba41f512ae0 (diff) | |
download | mongo-d09e608691aae000f3176b27cc67a7900229cd1e.tar.gz |
SERVER-9515 Implement several remaining role manipulation commands
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r-- | src/mongo/db/auth/authorization_manager.cpp | 42 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager.h | 28 | ||||
-rw-r--r-- | src/mongo/db/auth/role_graph.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/auth/role_graph.h | 16 | ||||
-rw-r--r-- | src/mongo/db/auth/role_graph_test.cpp | 134 | ||||
-rw-r--r-- | src/mongo/db/auth/user_management_commands_parser.cpp | 133 | ||||
-rw-r--r-- | src/mongo/db/auth/user_management_commands_parser.h | 30 |
7 files changed, 212 insertions, 187 deletions
diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp index a1f60eaf956..9b0b07c9086 100644 --- a/src/mongo/db/auth/authorization_manager.cpp +++ b/src/mongo/db/auth/authorization_manager.cpp @@ -163,6 +163,19 @@ namespace mongo { return _externalState->removePrivilegeDocuments(query, writeConcern, numRemoved); } + Status AuthorizationManager::removeRoleDocuments(const BSONObj& query, + const BSONObj& writeConcern, + int* numRemoved) const { + Status status = _externalState->remove(NamespaceString("admin.system.roles"), + query, + writeConcern, + numRemoved); + if (status.code() == ErrorCodes::UnknownError) { + return Status(ErrorCodes::RoleModificationFailed, status.reason()); + } + return status; + } + Status AuthorizationManager::insertRoleDocument(const BSONObj& roleObj, const BSONObj& writeConcern) const { Status status = _externalState->insert(NamespaceString("admin.system.roles"), @@ -215,6 +228,22 @@ namespace mongo { return _externalState->query(collectionName, query, resultProcessor); } + Status AuthorizationManager::updateAuthzDocuments(const NamespaceString& collectionName, + const BSONObj& query, + const BSONObj& updatePattern, + bool upsert, + bool multi, + const BSONObj& writeConcern, + int* numUpdated) const { + return _externalState->update(collectionName, + query, + updatePattern, + upsert, + multi, + writeConcern, + numUpdated); + } + bool AuthorizationManager::roleExists(const RoleName& role) { boost::lock_guard<boost::mutex> lk(_lock); return _roleGraph.roleExists(role); @@ -230,6 +259,12 @@ namespace mongo { return _roleGraph.getDirectPrivileges(role); } + std::vector<RoleName> AuthorizationManager::getSubordinateRolesForRole( + const RoleName& role) { + boost::lock_guard<boost::mutex> lk(_lock); + return _roleGraph.getDirectSubordinates(role); + } + Status AuthorizationManager::getBSONForPrivileges(const PrivilegeVector& privileges, mutablebson::Element resultArray) { for (PrivilegeVector::const_iterator it = privileges.begin(); @@ -270,9 +305,10 @@ namespace mongo { // Build roles array mutablebson::Element rolesArrayElement = result.getDocument().makeElementArray("roles"); result.pushBack(rolesArrayElement); - RoleNameIterator nameIt = graph->getDirectSubordinates(roleName); - while (nameIt.more()) { - const RoleName& subRole = nameIt.next(); + const std::vector<RoleName> roles = graph->getDirectSubordinates(roleName); + for (std::vector<RoleName>::const_iterator it = roles.begin(); + it != roles.end(); ++it) { + const RoleName& subRole = *it; mutablebson::Element roleObj = result.getDocument().makeElementObject(""); roleObj.appendString("name", subRole.getRole()); roleObj.appendString("source", subRole.getDB()); diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h index 5220ee11a45..1f9a7ef2200 100644 --- a/src/mongo/db/auth/authorization_manager.h +++ b/src/mongo/db/auth/authorization_manager.h @@ -183,6 +183,29 @@ namespace mongo { const BSONObj& writeConcern) const; /** + * Updates documents matching "query" according to "updatePattern" in "collectionName". + * Should only be called on collections with authorization documents in them + * (ie admin.system.users and admin.system.roles). + */ + Status updateAuthzDocuments(const NamespaceString& collectionName, + const BSONObj& query, + const BSONObj& updatePattern, + bool upsert, + bool multi, + const BSONObj& writeConcern, + int* numUpdated) const; + + /* + * Removes roles matching the given query. + * Writes into *numRemoved the number of role documents that were modified. + * 'writeConcern' contains the arguments to be passed to getLastError to block for + * successful completion of the write. + */ + Status removeRoleDocuments(const BSONObj& query, + const BSONObj& writeConcern, + int* numRemoved) const; + + /** * Finds all documents matching "query" in "collectionName". For each document returned, * calls the function resultProcessor on it. * Should only be called on collections with authorization documents in them @@ -257,6 +280,11 @@ namespace mongo { PrivilegeVector getDirectPrivilegesForRole(const RoleName& role); /** + * Returns the direct subordinate roles of the given role. + */ + std::vector<RoleName> getSubordinateRolesForRole(const RoleName& role); + + /** * Initializes the authorization manager. Depending on what version the authorization * system is at, this may involve building up the user cache and/or the roles graph. * This function should be called once at startup and never again after that. diff --git a/src/mongo/db/auth/role_graph.cpp b/src/mongo/db/auth/role_graph.cpp index d42354aa577..a010326f57c 100644 --- a/src/mongo/db/auth/role_graph.cpp +++ b/src/mongo/db/auth/role_graph.cpp @@ -40,6 +40,7 @@ namespace mongo { namespace { PrivilegeVector emptyPrivilegeVector; + std::vector<RoleName> emptyRoleVector; // RoleNameIterator for iterating over an unordered_set of RoleNames. class RoleNameSetIterator : public RoleNameIterator::Impl { @@ -75,6 +76,7 @@ namespace { unordered_set<RoleName>::const_iterator _begin; unordered_set<RoleName>::const_iterator _end; }; + } // namespace RoleGraph::RoleGraph() {}; @@ -180,11 +182,10 @@ namespace { return Status::OK(); } - RoleNameIterator RoleGraph::getDirectSubordinates(const RoleName& role) { + const std::vector<RoleName>& RoleGraph::getDirectSubordinates(const RoleName& role) { if (!roleExists(role)) - return RoleNameIterator(NULL); - const std::vector<RoleName>& edges = _roleToSubordinates.find(role)->second; - return RoleNameIterator(new RoleNameVectorIterator(edges.begin(), edges.end())); + return emptyRoleVector; + return _roleToSubordinates.find(role)->second; } RoleNameIterator RoleGraph::getIndirectSubordinates(const RoleName& role) { @@ -194,11 +195,10 @@ namespace { return RoleNameIterator(new RoleNameSetIterator(subs.begin(), subs.end())); } - RoleNameIterator RoleGraph::getDirectMembers(const RoleName& role) { + const std::vector<RoleName>& RoleGraph::getDirectMembers(const RoleName& role) { if (!roleExists(role)) - return RoleNameIterator(NULL); - const std::vector<RoleName>& edges = _roleToMembers.find(role)->second; - return RoleNameIterator(new RoleNameVectorIterator(edges.begin(), edges.end())); + return emptyRoleVector; + return _roleToMembers.find(role)->second; } const PrivilegeVector& RoleGraph::getDirectPrivileges(const RoleName& role) { diff --git a/src/mongo/db/auth/role_graph.h b/src/mongo/db/auth/role_graph.h index b7dcbbaa80f..f30f62a104d 100644 --- a/src/mongo/db/auth/role_graph.h +++ b/src/mongo/db/auth/role_graph.h @@ -71,22 +71,20 @@ namespace mongo { static void generateUniversalPrivileges(PrivilegeVector* privileges); /** - * Returns an iterator that can be used to get a list of the members of the given role. + * Returns a vector of the RoleNames of the "members" of the given role. * Members of a role are roles that have been granted this role directly (roles that are * members transitively through another role are not included). These are the "parents" of - * this node in the graph. The iterator is valid until the next call to addRole or - * removeRole. + * this node in the graph. */ - RoleNameIterator getDirectMembers(const RoleName& role); + const std::vector<RoleName>& getDirectMembers(const RoleName& role); /** - * Returns an iterator that can be used to get a list of "subordinate" roles of the given - * role. Subordinate roles are the roles that this role has been granted directly (roles + * Returns a vector of the RoleNames of the "subordninates" of the given role. + * Subordinate roles are the roles that this role has been granted directly (roles * that have been granted transitively through another role are not included). These are - * the "children" of this node in the graph. The iterator is valid until the next call to - * addRole or removeRole. + * the "children" of this node in the graph. */ - RoleNameIterator getDirectSubordinates(const RoleName& role); + const std::vector<RoleName>& getDirectSubordinates(const RoleName& role); /** * Returns an iterator that can be used to get a full list of roles that this role inherits diff --git a/src/mongo/db/auth/role_graph_test.cpp b/src/mongo/db/auth/role_graph_test.cpp index e4e34f302c2..42d933fc76e 100644 --- a/src/mongo/db/auth/role_graph_test.cpp +++ b/src/mongo/db/auth/role_graph_test.cpp @@ -52,32 +52,27 @@ namespace { ASSERT_OK(graph.createRole(roleB)); ASSERT_OK(graph.createRole(roleC)); - RoleNameIterator it; - it = graph.getDirectSubordinates(roleA); - ASSERT_FALSE(it.more()); - it = graph.getDirectMembers(roleA); - ASSERT_FALSE(it.more()); + std::vector<RoleName> roles = graph.getDirectSubordinates(roleA); + ASSERT_EQUALS(0U, roles.size()); + roles = graph.getDirectMembers(roleA); + ASSERT_EQUALS(0U, roles.size()); ASSERT_OK(graph.addRoleToRole(roleA, roleB)); // A -> B - it = graph.getDirectSubordinates(roleA); - ASSERT_TRUE(it.more()); - // should not advance the iterator - ASSERT_EQUALS(it.get().getFullName(), roleB.getFullName()); - ASSERT_EQUALS(it.get().getFullName(), roleB.getFullName()); - ASSERT_EQUALS(it.next().getFullName(), roleB.getFullName()); - ASSERT_FALSE(it.more()); + roles = graph.getDirectSubordinates(roleA); + ASSERT_EQUALS(1U, roles.size()); + ASSERT_EQUALS(roles[0].getFullName(), roleB.getFullName()); - it = graph.getDirectMembers(roleA); - ASSERT_FALSE(it.more()); + roles = graph.getDirectMembers(roleA); + ASSERT_EQUALS(0U, roles.size()); - it = graph.getDirectMembers(roleB); - ASSERT_EQUALS(it.next().getFullName(), roleA.getFullName()); - ASSERT_FALSE(it.more()); + roles = graph.getDirectMembers(roleB); + ASSERT_EQUALS(1U, roles.size()); + ASSERT_EQUALS(roles[0].getFullName(), roleA.getFullName()); - it = graph.getDirectSubordinates(roleB); - ASSERT_FALSE(it.more()); + roles= graph.getDirectSubordinates(roleB); + ASSERT_EQUALS(0U, roles.size()); ASSERT_OK(graph.addRoleToRole(roleA, roleC)); ASSERT_OK(graph.addRoleToRole(roleB, roleC)); @@ -96,20 +91,9 @@ namespace { * D */ - - it = graph.getDirectSubordinates(roleA); // should be roleB and roleC, order doesn't matter - RoleName cur = it.next(); - if (cur == roleB) { - ASSERT_EQUALS(it.next().getFullName(), roleC.getFullName()); - } else if (cur == roleC) { - ASSERT_EQUALS(it.next().getFullName(), roleB.getFullName()); - } else { - FAIL(mongoutils::str::stream() << "unexpected role returned: " << cur.getFullName()); - } - ASSERT_FALSE(it.more()); - + // Check indirect roles for roleA. should have roleB, roleC and roleD, order doesn't matter. ASSERT_OK(graph.recomputePrivilegeData()); - it = graph.getIndirectSubordinates(roleA); // should have roleB, roleC and roleD + RoleNameIterator it = graph.getIndirectSubordinates(roleA); bool hasB = false; bool hasC = false; bool hasD = false; @@ -133,39 +117,32 @@ namespace { ASSERT(hasC); ASSERT(hasD); - it = graph.getDirectSubordinates(roleB); // should be roleC and roleD, order doesn't matter - cur = it.next(); - if (cur == roleC) { - ASSERT_EQUALS(it.next().getFullName(), roleD.getFullName()); - } else if (cur == roleD) { - ASSERT_EQUALS(it.next().getFullName(), roleC.getFullName()); - } else { - FAIL(mongoutils::str::stream() << "unexpected role returned: " << cur.getFullName()); - } - ASSERT_FALSE(it.more()); - - it = graph.getDirectSubordinates(roleC); - ASSERT_FALSE(it.more()); - - it = graph.getDirectMembers(roleA); - ASSERT_FALSE(it.more()); - - it = graph.getDirectMembers(roleB); - ASSERT_EQUALS(it.next().getFullName(), roleA.getFullName()); - ASSERT_FALSE(it.more()); - - it = graph.getDirectMembers(roleC); // should be role A and role B, order doesn't matter - cur = it.next(); - if (cur == roleA) { - ASSERT_EQUALS(it.next().getFullName(), roleB.getFullName()); - } else if (cur == roleB) { - ASSERT_EQUALS(it.next().getFullName(), roleA.getFullName()); - } else { - FAIL(mongoutils::str::stream() << "unexpected role returned: " << cur.getFullName()); - } - ASSERT_FALSE(it.more()); + roles = graph.getDirectSubordinates(roleA); // should be roleB then roleC + ASSERT_EQUALS(2U, roles.size()); + ASSERT_EQUALS(roleB.getFullName(), roles[0].getFullName()); + ASSERT_EQUALS(roleC.getFullName(), roles[1].getFullName()); + + roles = graph.getDirectSubordinates(roleB); // should be roleC then roleD + ASSERT_EQUALS(2U, roles.size()); + ASSERT_EQUALS(roleC.getFullName(), roles[0].getFullName()); + ASSERT_EQUALS(roleD.getFullName(), roles[1].getFullName()); + + roles = graph.getDirectSubordinates(roleC); + ASSERT_EQUALS(0U, roles.size()); + + roles = graph.getDirectMembers(roleA); + ASSERT_EQUALS(0U, roles.size()); + + roles = graph.getDirectMembers(roleB); + ASSERT_EQUALS(1U, roles.size()); + ASSERT_EQUALS(roleA.getFullName(), roles[0].getFullName()); + + roles = graph.getDirectMembers(roleC); // should be role A then role B + ASSERT_EQUALS(2U, roles.size()); + ASSERT_EQUALS(roleA.getFullName(), roles[0].getFullName()); + ASSERT_EQUALS(roleB.getFullName(), roles[1].getFullName()); - // Now remove roleD from roleB and make sure graph is update correctly + // Now remove roleD from roleB and make sure graph is updated correctly ASSERT_OK(graph.removeRoleFromRole(roleB, roleD)); /* @@ -175,23 +152,23 @@ namespace { * v v * B -> C */ - it = graph.getDirectSubordinates(roleB); // should be just roleC - ASSERT_EQUALS(it.next().getFullName(), roleC.getFullName()); - ASSERT_FALSE(it.more()); + roles = graph.getDirectSubordinates(roleB); // should be just roleC + ASSERT_EQUALS(1U, roles.size()); + ASSERT_EQUALS(roleC.getFullName(), roles[0].getFullName()); - it = graph.getDirectSubordinates(roleD); // should be empty - ASSERT_FALSE(it.more()); + roles = graph.getDirectSubordinates(roleD); // should be empty + ASSERT_EQUALS(0U, roles.size()); // Now delete roleB entirely and make sure that the other roles are updated properly ASSERT_OK(graph.deleteRole(roleB)); ASSERT_NOT_OK(graph.deleteRole(roleB)); - it = graph.getDirectSubordinates(roleA); - ASSERT_EQUALS(it.next().getFullName(), roleC.getFullName()); - ASSERT_FALSE(it.more()); - it = graph.getDirectMembers(roleC); - ASSERT_EQUALS(it.next().getFullName(), roleA.getFullName()); - ASSERT_FALSE(it.more()); + roles = graph.getDirectSubordinates(roleA); + ASSERT_EQUALS(1U, roles.size()); + ASSERT_EQUALS(roleC.getFullName(), roles[0].getFullName()); + roles = graph.getDirectMembers(roleC); + ASSERT_EQUALS(1U, roles.size()); + ASSERT_EQUALS(roleA.getFullName(), roles[0].getFullName()); } const ResourcePattern collectionAFooResource(ResourcePattern::forExactNamespace( @@ -526,10 +503,9 @@ namespace { // properly. swap(tempGraph, graph); - RoleNameIterator it = graph.getDirectSubordinates(roleB); - ASSERT_TRUE(it.more()); - ASSERT_EQUALS(it.next().getFullName(), roleC.getFullName()); - ASSERT_FALSE(it.more()); + std::vector<RoleName> roles = graph.getDirectSubordinates(roleB); + ASSERT_EQUALS(1U, roles.size()); + ASSERT_EQUALS(roleC.getFullName(), roles[0].getFullName()); graph.getAllPrivileges(roleA); // should have privileges from roleB *and* role C PrivilegeVector privileges = graph.getAllPrivileges(roleA); diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp index 2678cbd9b0b..88b8c90bee6 100644 --- a/src/mongo/db/auth/user_management_commands_parser.cpp +++ b/src/mongo/db/auth/user_management_commands_parser.cpp @@ -35,7 +35,6 @@ #include "mongo/bson/util/bson_extract.h" #include "mongo/client/auth_helpers.h" #include "mongo/db/auth/action_type.h" -#include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege_parser.h" #include "mongo/db/auth/user_document_parser.h" @@ -176,7 +175,7 @@ namespace auth { BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert(cmdName.toString()); - validFieldNames.insert("roles"); + validFieldNames.insert(rolesFieldName.toString()); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); @@ -189,15 +188,13 @@ namespace auth { return status; } - std::string userNameStr; - status = bsonExtractStringField(cmdObj, cmdName, &userNameStr); + status = bsonExtractStringField(cmdObj, cmdName, parsedName); if (!status.isOK()) { return status; } - *parsedName = userNameStr; BSONElement rolesElement; - status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement); + status = bsonExtractTypedField(cmdObj, rolesFieldName, Array, &rolesElement); if (!status.isOK()) { return status; } @@ -212,85 +209,12 @@ namespace auth { if (!parsedRoleNames->size()) { return Status(ErrorCodes::BadValue, - mongoutils::str::stream() << cmdName << " command requires a non-empty" << - " roles array"); + mongoutils::str::stream() << cmdName << " command requires a non-empty \"" + << rolesFieldName << "\" array"); } return Status::OK(); } - /** - * Validates that the roles array described by rolesElement is valid. - * Also returns a new roles array (via the modifiedRolesArray output param) where any roles - * from the input array that were listed as strings have been expanded to a full role document. - * If includePossessionBools is true then the expanded roles documents will have "hasRole" - * and "canDelegate" boolean fields (in addition to the "name" and "source" fields which are - * there either way). - */ - Status _validateAndModifyRolesArray(const BSONElement& rolesElement, - const std::string& dbname, - AuthorizationManager* authzManager, - bool includePossessionBools, - BSONArray* modifiedRolesArray) { - BSONArrayBuilder rolesBuilder; - - for (BSONObjIterator it(rolesElement.Obj()); it.more(); it.next()) { - BSONElement element = *it; - if (element.type() == String) { - RoleName roleName(element.String(), dbname); - if (!authzManager->roleExists(roleName)) { - return Status(ErrorCodes::RoleNotFound, - mongoutils::str::stream() << roleName.toString() << - " does not name an existing role"); - } - - if (includePossessionBools) { - rolesBuilder.append(BSON("name" << element.String() << - "source" << dbname << - "hasRole" << true << - "canDelegate" << false)); - } else { - rolesBuilder.append(BSON("name" << element.String() << - "source" << dbname)); - } - } else if (element.type() == Object) { - // Check that the role object is valid - V2UserDocumentParser parser; - BSONObj roleObj = element.Obj(); - Status status = parser.checkValidRoleObject(roleObj, includePossessionBools); - if (!status.isOK()) { - return status; - } - - // Check that the role actually exists - std::string roleNameString; - std::string roleSource; - status = bsonExtractStringField(roleObj, "name", &roleNameString); - if (!status.isOK()) { - return status; - } - status = bsonExtractStringField(roleObj, "source", &roleSource); - if (!status.isOK()) { - return status; - } - - RoleName roleName(roleNameString, roleSource); - if (!authzManager->roleExists(roleName)) { - return Status(ErrorCodes::RoleNotFound, - mongoutils::str::stream() << roleName.toString() << - " does not name an existing role"); - } - - rolesBuilder.append(element); - } else { - return Status(ErrorCodes::UnsupportedFormat, - "Values in 'roles' array must be sub-documents or strings"); - } - } - - *modifiedRolesArray = rolesBuilder.arr(); - return Status::OK(); - } - Status parseCreateOrUpdateUserCommands(const BSONObj& cmdObj, const StringData& cmdName, const std::string& dbname, @@ -591,5 +515,52 @@ namespace auth { return Status::OK(); } + Status parseRemoveRoleCommand(const BSONObj& cmdObj, + const std::string& dbname, + RoleName* parsedRoleName, + BSONObj* parsedWriteConcern) { + unordered_set<std::string> validFieldNames; + validFieldNames.insert("removeRole"); + validFieldNames.insert("writeConcern"); + + Status status = _checkNoExtraFields(cmdObj, "removeRole", validFieldNames); + if (!status.isOK()) { + return status; + } + + std::string user; + status = bsonExtractStringField(cmdObj, "removeRole", &user); + if (!status.isOK()) { + return status; + } + + status = _extractWriteConcern(cmdObj, parsedWriteConcern); + if (!status.isOK()) { + return status; + } + + *parsedRoleName = RoleName(user, dbname); + return Status::OK(); + } + + Status parseRemoveRolesFromDatabaseCommand(const BSONObj& cmdObj, + const std::string& dbname, + BSONObj* parsedWriteConcern) { + unordered_set<std::string> validFieldNames; + validFieldNames.insert("removeRolesFromDatabase"); + validFieldNames.insert("writeConcern"); + + Status status = _checkNoExtraFields(cmdObj, "removeRolesFromDatabase", validFieldNames); + if (!status.isOK()) { + return status; + } + + status = _extractWriteConcern(cmdObj, parsedWriteConcern); + if (!status.isOK()) { + return status; + } + + return Status::OK(); + } } // namespace auth } // namespace mongo diff --git a/src/mongo/db/auth/user_management_commands_parser.h b/src/mongo/db/auth/user_management_commands_parser.h index d1bca97c5ad..4d49ebb77a3 100644 --- a/src/mongo/db/auth/user_management_commands_parser.h +++ b/src/mongo/db/auth/user_management_commands_parser.h @@ -39,9 +39,6 @@ #include "mongo/db/jsobj.h" namespace mongo { - - class AuthorizationManager; - namespace auth { struct CreateOrUpdateUserArgs { @@ -69,9 +66,11 @@ namespace auth { /** * Takes a command object describing an invocation of one of "grantRolesToUser", - * "revokeRolesFromUser", "grantDelegateRolesToUser", and "revokeDelegateRolesFromUser" (which - * command it is is specified in the "cmdName" argument), and parses out the user name of the - * user being modified, the roles being granted or revoked, and the write concern to use. + * "revokeRolesFromUser", "grantDelegateRolesToUser", "revokeDelegateRolesFromUser", + * "grantRolesToRole", and "revokeRolesFromRoles" (which command it is is specified in the + * "cmdName" argument), and parses out (into the parsedName out param) the user/role name of + * the user/roles being modified, the roles being granted or revoked, and the write concern to + * use. */ Status parseRolePossessionManipulationCommands(const BSONObj& cmdObj, const StringData& cmdName, @@ -83,7 +82,7 @@ namespace auth { /** * Takes a command object describing an invocation of the "removeUser" command and parses out - * the userName of the user to be removed and the writeConcern. + * the UserName of the user to be removed and the writeConcern. * Also validates the input and returns a non-ok Status if there is anything wrong. */ Status parseAndValidateRemoveUserCommand(const BSONObj& cmdObj, @@ -144,5 +143,22 @@ namespace auth { PrivilegeVector* parsedPrivileges, BSONObj* parsedWriteConcern); + /** + * Takes a command object describing an invocation of the "removeRole" command and parses out + * the RoleName of the role to be removed and the writeConcern. + */ + Status parseRemoveRoleCommand(const BSONObj& cmdObj, + const std::string& dbname, + RoleName* parsedRoleName, + BSONObj* parsedWriteConcern); + + /** + * Takes a command object describing an invocation of the "removeRolesFromDatabase" command and + * parses out the write concern. + */ + Status parseRemoveRolesFromDatabaseCommand(const BSONObj& cmdObj, + const std::string& dbname, + BSONObj* parsedWriteConcern); + } // namespace auth } // namespace mongo |