Status parseRoleNamesFromBSONArray(const BSONArray& rolesArray, const StringData& dbname, const StringData& rolesFieldName, std::vector<RoleName>* parsedRoleNames) { for (BSONObjIterator it(rolesArray); it.more(); it.next()) { BSONElement element = *it; if (element.type() == String) { parsedRoleNames->push_back(RoleName(element.String(), dbname)); } else if (element.type() == Object) { BSONObj roleObj = element.Obj(); std::string roleNameString; std::string roleSource; Status status = bsonExtractStringField(roleObj, "name", &roleNameString); if (!status.isOK()) { return status; } status = bsonExtractStringField(roleObj, "source", &roleSource); if (!status.isOK()) { return status; } parsedRoleNames->push_back(RoleName(roleNameString, roleSource)); } else { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << "Values in \"" << rolesFieldName << "\" array must be sub-documents or strings"); } } return Status::OK(); }
Status parseDropRoleCommand(const BSONObj& cmdObj, const std::string& dbname, RoleName* parsedRoleName, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert("dropRole"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, "dropRole", validFieldNames); if (!status.isOK()) { return status; } std::string user; status = bsonExtractStringField(cmdObj, "dropRole", &user); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } *parsedRoleName = RoleName(user, dbname); return Status::OK(); }
Status V2PrivilegeDocumentParser::initializeUserRolesFromPrivilegeDocument( User* user, const BSONObj& privDoc, const StringData&) const { BSONElement rolesElement = privDoc[ROLES_FIELD_NAME]; if (rolesElement.type() != Array) { return Status(ErrorCodes::UnsupportedFormat, "User document needs 'roles' field to be an array"); } for (BSONObjIterator it(rolesElement.Obj()); it.more(); it.next()) { if ((*it).type() != Object) { return Status(ErrorCodes::UnsupportedFormat, "User document needs values in 'roles' array to be a sub-documents"); } BSONObj roleObject = (*it).Obj(); BSONElement roleNameElement = roleObject[ROLE_NAME_FIELD_NAME]; BSONElement roleSourceElement = roleObject[ROLE_SOURCE_FIELD_NAME]; if (roleNameElement.type() != String || makeStringDataFromBSONElement(roleNameElement).empty()) { return Status(ErrorCodes::UnsupportedFormat, "Role names must be non-empty strings"); } if (roleSourceElement.type() != String || makeStringDataFromBSONElement(roleSourceElement).empty()) { return Status(ErrorCodes::UnsupportedFormat, "Role source must be non-empty strings"); } user->addRole(RoleName(roleNameElement.String(), roleSourceElement.String())); } return Status::OK(); }
Status parseCreateOrUpdateRoleCommands(const BSONObj& cmdObj, const StringData& cmdName, const std::string& dbname, CreateOrUpdateRoleArgs* parsedArgs) { unordered_set<std::string> validFieldNames; validFieldNames.insert(cmdName.toString()); validFieldNames.insert("privileges"); validFieldNames.insert("roles"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, &parsedArgs->writeConcern); if (!status.isOK()) { return status; } std::string roleName; status = bsonExtractStringField(cmdObj, "createRole", &roleName); if (!status.isOK()) { return status; } parsedArgs->roleName = RoleName(roleName, dbname); // Parse privileges if (cmdObj.hasField("privileges")) { BSONElement privilegesElement; status = bsonExtractTypedField(cmdObj, "privileges", Array, &privilegesElement); if (!status.isOK()) { return status; } status = parseAndValidatePrivilegeArray(BSONArray(privilegesElement.Obj()), &parsedArgs->privileges); if (!status.isOK()) { return status; } parsedArgs->hasPrivileges = true; } // Parse roles if (cmdObj.hasField("roles")) { BSONElement rolesElement; status = bsonExtractTypedField(cmdObj, "roles", Array, &rolesElement); if (!status.isOK()) { return status; } status = parseRoleNamesFromBSONArray(BSONArray(rolesElement.Obj()), dbname, "roles", &parsedArgs->roles); if (!status.isOK()) { return status; } parsedArgs->hasRoles = true; } return Status::OK(); }
static void _initializeUserRolesFromV0UserDocument( User* user, const BSONObj& privDoc, const StringData& dbname) { bool readOnly = privDoc["readOnly"].trueValue(); if (dbname == "admin") { if (readOnly) { user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_ADMIN_READ, "admin")); } else { user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_ADMIN_READ_WRITE, "admin")); } } else { if (readOnly) { user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_READ, dbname)); } else { user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_READ_WRITE, dbname)); } } }
Status V2UserDocumentParser::parseRoleName(const BSONObj& roleObject, RoleName* result) { BSONElement roleNameElement; BSONElement roleSourceElement; Status status = _extractRoleDocumentElements(roleObject, &roleNameElement, &roleSourceElement); if (!status.isOK()) return status; *result = RoleName(roleNameElement.str(), roleSourceElement.str()); return status; }
void _initializeUserRolesFromV0PrivilegeDocument( User* user, const BSONObj& privDoc, const StringData& dbname) { bool readOnly = privDoc["readOnly"].trueValue(); if (dbname == "admin") { if (readOnly) { user->addRole(RoleName(AuthorizationManager::SYSTEM_ROLE_V0_ADMIN_READ, "admin")); } else { user->addRole(RoleName(AuthorizationManager::SYSTEM_ROLE_V0_ADMIN_READ_WRITE, "admin")); } } else { if (readOnly) { user->addRole(RoleName(AuthorizationManager::SYSTEM_ROLE_V0_READ, dbname)); } else { user->addRole(RoleName(AuthorizationManager::SYSTEM_ROLE_V0_READ_WRITE, dbname)); } } }
void AuthorizationSession::_buildAuthenticatedRolesVector() { _authenticatedRoleNames.clear(); for (UserSet::iterator it = _authenticatedUsers.begin(); it != _authenticatedUsers.end(); ++it) { RoleNameIterator roles = (*it)->getIndirectRoles(); while (roles.more()) { RoleName roleName = roles.next(); _authenticatedRoleNames.push_back(RoleName(roleName.getRole(), roleName.getDB())); } } }
Status parseAndValidateRolePrivilegeManipulationCommands(const BSONObj& cmdObj, const StringData& cmdName, const std::string& dbname, RoleName* parsedRoleName, PrivilegeVector* parsedPrivileges, BSONObj* parsedWriteConcern) { unordered_set<std::string> validFieldNames; validFieldNames.insert(cmdName.toString()); validFieldNames.insert("privileges"); validFieldNames.insert("writeConcern"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { return status; } status = _extractWriteConcern(cmdObj, parsedWriteConcern); if (!status.isOK()) { return status; } BSONObjBuilder roleObjBuilder; // Parse role name std::string roleName; status = bsonExtractStringField(cmdObj, cmdName, &roleName); if (!status.isOK()) { return status; } *parsedRoleName = RoleName(roleName, dbname); // Parse privileges BSONElement privilegesElement; status = bsonExtractTypedField(cmdObj, "privileges", Array, &privilegesElement); if (!status.isOK()) { return status; } status = parseAndValidatePrivilegeArray(BSONArray(privilegesElement.Obj()), parsedPrivileges); if (!status.isOK()) { return status; } if (!parsedPrivileges->size()) { return Status(ErrorCodes::BadValue, mongoutils::str::stream() << cmdName << " command requires a non-empty " "\"privileges\" array"); } return Status::OK(); }
Status _extractRoleDataFromBSONArray(const BSONElement& rolesElement, const std::string& dbname, std::vector<User::RoleData> *parsedRoleData) { for (BSONObjIterator it(rolesElement.Obj()); it.more(); it.next()) { BSONElement element = *it; if (element.type() == String) { RoleName roleName(element.String(), dbname); parsedRoleData->push_back(User::RoleData(roleName, true, false)); } else if (element.type() == Object) { // Check that the role object is valid V2UserDocumentParser parser; BSONObj roleObj = element.Obj(); Status status = parser.checkValidRoleObject(roleObj, true); if (!status.isOK()) { return status; } std::string roleName; std::string roleSource; bool hasRole; bool canDelegate; status = bsonExtractStringField(roleObj, "name", &roleName); if (!status.isOK()) { return status; } status = bsonExtractStringField(roleObj, "source", &roleSource); if (!status.isOK()) { return status; } status = bsonExtractBooleanField(roleObj, "hasRole", &hasRole); if (!status.isOK()) { return status; } status = bsonExtractBooleanField(roleObj, "canDelegate", &canDelegate); if (!status.isOK()) { return status; } parsedRoleData->push_back(User::RoleData(RoleName(roleName, roleSource), hasRole, canDelegate)); } else { return Status(ErrorCodes::UnsupportedFormat, "Values in 'roles' array must be sub-documents or strings"); } } return Status::OK(); }
Status _initializeUserRolesFromV1RolesArray(User* user, const BSONElement& rolesElement, const StringData& dbname) { static const char privilegesTypeMismatchMessage[] = "Roles in V1 user documents must be enumerated in an array of strings."; if (rolesElement.type() != Array) return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage); for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) { BSONElement roleElement = *iter; if (roleElement.type() != String) return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage); user->addRole(RoleName(roleElement.String(), dbname)); } return Status::OK(); }
Status V2UserDocumentParser::parseRoleData(const BSONObj& roleObject, User::RoleData* result) { BSONElement roleNameElement; BSONElement roleSourceElement; BSONElement canDelegateElement; BSONElement hasRoleElement; Status status = _extractRoleDocumentElements( roleObject, &roleNameElement, &roleSourceElement, &canDelegateElement, &hasRoleElement); if (!status.isOK()) return status; result->name = RoleName(roleNameElement.str(), roleSourceElement.str()); result->canDelegate = canDelegateElement.eoo() ? false : canDelegateElement.trueValue(); result->hasRole = hasRoleElement.eoo() ? true : hasRoleElement.trueValue(); return status; }
Status _initializeUserRolesFromV1RolesArray(User* user, const BSONElement& rolesElement, const StringData& dbname) { static const char privilegesTypeMismatchMessage[] = "Roles in V1 user documents must be enumerated in an array of strings."; if (dbname == AuthorizationManager::WILDCARD_RESOURCE_NAME) { return Status(ErrorCodes::BadValue, AuthorizationManager::WILDCARD_RESOURCE_NAME + " is an invalid database name."); } if (rolesElement.type() != Array) return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage); for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) { BSONElement roleElement = *iter; if (roleElement.type() != String) return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage); user->addRole(RoleName(roleElement.String(), dbname)); } return Status::OK(); }
Status V2PrivilegeDocumentParser::initializeUserRolesFromPrivilegeDocument( User* user, const BSONObj& privDoc, const StringData&) const { BSONElement rolesElement = privDoc[ROLES_FIELD_NAME]; if (rolesElement.type() != Array) { return Status(ErrorCodes::UnsupportedFormat, "User document needs 'roles' field to be an array"); } for (BSONObjIterator it(rolesElement.Obj()); it.more(); it.next()) { if ((*it).type() != Object) { return Status(ErrorCodes::UnsupportedFormat, "User document needs values in 'roles' array to be a sub-documents"); } BSONObj roleObject = (*it).Obj(); Status status = checkValidRoleObject(roleObject); if (!status.isOK()) { return status; } BSONElement roleNameElement = roleObject[ROLE_NAME_FIELD_NAME]; BSONElement roleSourceElement = roleObject[ROLE_SOURCE_FIELD_NAME]; BSONElement canDelegateElement = roleObject[ROLE_CAN_DELEGATE_FIELD_NAME]; BSONElement hasRoleElement = roleObject[ROLE_HAS_ROLE_FIELD_NAME]; if (hasRoleElement.Bool()) { user->addRole(RoleName(roleNameElement.String(), roleSourceElement.String())); } if (canDelegateElement.Bool()) { // TODO(spencer): record the fact that this user can delegate this role } } return Status::OK(); }
void RoleGraph::_createBuiltinRolesForDBIfNeeded(const std::string& dbname) { _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_READ, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_READ_WRITE, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_USER_ADMIN, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_DB_ADMIN, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_DB_OWNER, dbname)); if (dbname == "admin") { _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_READ_ANY_DB, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_READ_WRITE_ANY_DB, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_USER_ADMIN_ANY_DB, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_DB_ADMIN_ANY_DB, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_CLUSTER_MONITOR, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_HOST_MANAGEMENT, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_CLUSTER_MANAGEMENT, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_CLUSTER_ADMIN, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_BACKUP, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_RESTORE, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_ROOT, dbname)); _createBuiltinRoleIfNeeded(RoleName(BUILTIN_ROLE_INTERNAL, dbname)); } }