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();
    }
Beispiel #11
0
    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();
    }
Beispiel #12
0
 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));
        }
    }