Ejemplo n.º 1
0
    def init_keys(self):
        from cmdb.security.key.generator import KeyGenerator
        kg = KeyGenerator()
        LOGGER.info('KEY ROUTINE: Generate RSA keypair')
        kg.generate_rsa_keypair()
        LOGGER.info('KEY ROUTINE: Generate aes key')
        kg.generate_symmetric_aes_key()

        self.__check_database()

        from cmdb.user_management.managers.user_manager import UserManager, UserModel
        from cmdb.security.security import SecurityManager
        scm = SecurityManager(self.setup_database_manager)
        usm = UserManager(self.setup_database_manager)

        try:
            admin_user: UserModel = usm.get(1)
            LOGGER.warning('KEY ROUTINE: Admin user detected')
            LOGGER.info(
                f'KEY ROUTINE: Enter new password for user: {admin_user.user_name}'
            )
            admin_pass = str(input('New admin password: '******'KEY ROUTINE: Password was updated for user: {admin_user.user_name}'
            )
        except Exception as ex:
            LOGGER.info(
                f'KEY ROUTINE: Password was updated for user failed: {ex}')
        LOGGER.info('KEY ROUTINE: FINISHED')
Ejemplo n.º 2
0
    def __create_user_management(self):
        from cmdb.user_management.models.user import UserModel

        from cmdb.user_management.managers.user_manager import UserManager
        from cmdb.user_management.managers.group_manager import GroupManager
        from cmdb.user_management import __FIXED_GROUPS__
        from cmdb.security.security import SecurityManager
        scm = SecurityManager(self.setup_database_manager)
        group_manager = GroupManager(self.setup_database_manager)
        user_manager = UserManager(self.setup_database_manager)

        for group in __FIXED_GROUPS__:
            group_manager.insert(group)

        # setting the initial user to admin/admin as default
        admin_name = 'admin'
        admin_pass = '******'

        import datetime
        admin_user = UserModel(
            public_id=1,
            user_name=admin_name,
            active=True,
            group_id=__FIXED_GROUPS__[0].get_public_id(),
            registration_time=datetime.datetime.now(),
            password=scm.generate_hmac(admin_pass),
        )
        user_manager.insert(admin_user)
        return True
Ejemplo n.º 3
0
    def authenticate(self, user_name: str, password: str, **kwargs) -> UserModel:
        __dbm = DatabaseManagerMongo(
            **SystemConfigReader().get_all_values_from_section('Database')
        )
        __user_manager = UserManager(__dbm)
        try:
            ldap_connection_status = self.connect()
            LOGGER.debug(f'[LdapAuthenticationProvider] Connection status: {ldap_connection_status}')
        except Exception as e:
            LOGGER.error(f'[LdapAuthenticationProvider] Failed to connect to LDAP server - error: {e}')
            raise AuthenticationError(LdapAuthenticationProvider.get_name(), e)
        ldap_search_filter = self.config.search['searchfilter'].replace("%username%", user_name)
        LOGGER.debug(f'[LdapAuthenticationProvider] Search Filter: {ldap_search_filter}')
        search_result = self.__ldap_connection.search(self.config.search['basedn'], ldap_search_filter)
        LOGGER.debug(f'[LdapAuthenticationProvider] Search result: {search_result}')

        if not search_result or len(self.__ldap_connection.entries) == 0:
            raise AuthenticationError(LdapAuthenticationProvider.get_name(), 'No matching entry')

        for entry in self.__ldap_connection.entries:
            LOGGER.debug(f'[LdapAuthenticationProvider] Entry: {entry}')
            entry_dn = entry.entry_dn
            try:
                entry_connection_result = LdapAuthenticationProvider.Connection(self.__ldap_server, entry_dn, password,
                                                                                auto_bind=True)
                LOGGER.debug(f'[LdapAuthenticationProvider] UserModel connection result: {entry_connection_result}')
            except Exception as e:
                LOGGER.error(f'[LdapAuthenticationProvider] UserModel auth result: {e}')
                raise AuthenticationError(LdapAuthenticationProvider.get_name(), e)

        # Check if user exists
        try:
            user_instance: UserModel = __user_manager.get_by({'user_name': user_name})
        except ManagerGetError as umge:
            LOGGER.warning(f'[LdapAuthenticationProvider] UserModel exists on LDAP but not in database: {umge}')
            LOGGER.debug(f'[LdapAuthenticationProvider] Try creating user: {user_name}')
            try:
                new_user_data = dict()
                new_user_data['user_name'] = user_name
                new_user_data['active'] = True
                new_user_data['group_id'] = self.config.default_group
                new_user_data['registration_time'] = datetime.now()
                new_user_data['authenticator'] = LdapAuthenticationProvider.get_name()

            except Exception as e:
                LOGGER.debug(f'[LdapAuthenticationProvider] {e}')
                raise AuthenticationError(LdapAuthenticationProvider.get_name(), e)
            LOGGER.debug(f'[LdapAuthenticationProvider] New user was init')
            try:
                user_id = __user_manager.insert(new_user_data)
            except ManagerInsertError as umie:
                LOGGER.debug(f'[LdapAuthenticationProvider] {umie}')
                raise AuthenticationError(LdapAuthenticationProvider.get_name(), umie)
            try:
                user_instance: UserModel = __user_manager.get(public_id=user_id)
            except ManagerGetError as umge:
                LOGGER.debug(f'[LdapAuthenticationProvider] {umge}')
                raise AuthenticationError(LdapAuthenticationProvider.get_name(), umge)
        return user_instance
Ejemplo n.º 4
0
            def _decorate(*args, **kwargs):

                if auth:
                    if not auth_is_valid():
                        return abort(401)

                if auth and right:
                    if not user_has_right(right):
                        if excepted:
                            with current_app.app_context():
                                user_manager = UserManager(
                                    current_app.database_manager)

                            token = parse_authorization_header(
                                request.headers['Authorization'])
                            try:
                                decrypted_token = TokenValidator(
                                    current_app.database_manager).decode_token(
                                        token)
                            except ValidationError as err:
                                return abort(401)
                            try:
                                user_id = decrypted_token['DATAGERRY'][
                                    'value']['user']['public_id']
                                user_dict: dict = UserModel.to_dict(
                                    user_manager.get(user_id))

                                if excepted:
                                    for exe_key, exe_value in excepted.items():
                                        try:
                                            route_parameter = kwargs[exe_value]
                                        except KeyError:
                                            return abort(
                                                403,
                                                f'User has not the required right {right}'
                                            )

                                        if exe_key not in user_dict.keys():
                                            return abort(
                                                403,
                                                f'User has not the required right {right}'
                                            )

                                        if user_dict[
                                                exe_key] == route_parameter:
                                            return f(*args, **kwargs)
                            except ManagerGetError:
                                return abort(404)
                        return abort(
                            403, f'User has not the required right {right}')

                return f(*args, **kwargs)
Ejemplo n.º 5
0
 def authenticate(self, user_name: str, password: str, **kwargs) -> UserModel:
     __dbm = DatabaseManagerMongo(
         **SystemConfigReader().get_all_values_from_section('Database')
     )
     __scm = SecurityManager(__dbm)
     __user_manager = UserManager(__dbm)
     LOGGER.info(f'[LocalAuthenticationProvider] Try login for user {user_name}')
     try:
         user: UserModel = __user_manager.get_by({'user_name': user_name})
     except ManagerGetError as umge:
         raise AuthenticationError(LocalAuthenticationProvider.get_name(), umge.message)
     login_pass = __scm.generate_hmac(password)
     if login_pass == user.password:
         return user
     raise AuthenticationError(LocalAuthenticationProvider.get_name(), 'UserModel not exists')
Ejemplo n.º 6
0
def change_user_password(public_id: int):
    """
    HTTP `PATCH` route for updating a single user password.

    Args:
        public_id (int): Public ID of the user.

    Raises:
        ManagerGetError: When the user with the `public_id` was not found.
        ManagerUpdateError: When something went wrong during the updated.

    Returns:
        UpdateSingleResponse: User with new password
    """
    user_manager: UserManager = UserManager(
        database_manager=current_app.database_manager)
    security_manager: SecurityManager = SecurityManager(
        database_manager=current_app.database_manager)
    try:
        user = user_manager.get(public_id=public_id)
        password = security_manager.generate_hmac(request.json.get('password'))
        user.password = password
        user_manager.update(public_id=PublicID(public_id), user=user)
        api_response = UpdateSingleResponse(result=UserModel.to_dict(user),
                                            url=request.url,
                                            model=UserModel.MODEL)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerUpdateError as err:
        return abort(400, err.message)

    return api_response.make_response()
Ejemplo n.º 7
0
def delete_user(public_id: int):
    """
    HTTP `DELETE` route for delete a single user resource.

    Args:
        public_id (int): Public ID of the user.

    Raises:
        ManagerGetError: When the user with the `public_id` was not found.
        ManagerDeleteError: When something went wrong during the deletion.

    Returns:
        DeleteSingleResponse: Delete result with the deleted user as data.
    """
    user_manager: UserManager = UserManager(
        database_manager=current_app.database_manager)
    try:
        deleted_group = user_manager.delete(public_id=PublicID(public_id))
        api_response = DeleteSingleResponse(
            raw=UserModel.to_dict(deleted_group), model=UserModel.MODEL)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerDeleteError as err:
        return abort(404, err.message)
    return api_response.make_response()
Ejemplo n.º 8
0
def update_user(public_id: int, data: dict):
    """
    HTTP `PUT`/`PATCH` route for update a single user resource.

    Args:
        public_id (int): Public ID of the updatable user.
        data (UserModel.SCHEMA): New user data to update.

    Raises:
        ManagerGetError: When the user with the `public_id` was not found.
        ManagerUpdateError: When something went wrong during the update.

    Returns:
        UpdateSingleResponse: With update result of the new updated user.
    """
    user_manager: UserManager = UserManager(
        database_manager=current_app.database_manager)
    try:
        user = UserModel.from_data(data=data)
        user_manager.update(public_id=PublicID(public_id), user=user)
        api_response = UpdateSingleResponse(result=UserModel.to_dict(user),
                                            url=request.url,
                                            model=UserModel.MODEL)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerUpdateError as err:
        return abort(400, err.message)
    return api_response.make_response()
Ejemplo n.º 9
0
def insert_user(data: dict):
    """
    HTTP `POST` route for insert a single user resource.

    Args:
        data (UserModel.SCHEMA): Insert data of a new user.

    Raises:
        ManagerGetError: If the inserted user could not be found after inserting.
        ManagerInsertError: If something went wrong during insertion.

    Returns:
        InsertSingleResponse: Insert response with the new user and its public_id.
    """
    user_manager: UserManager = UserManager(
        database_manager=current_app.database_manager)
    security_manager: SecurityManager = SecurityManager(
        database_manager=current_app.database_manager)
    try:
        data['password'] = security_manager.generate_hmac(data['password'])
        result_id: PublicID = user_manager.insert(data)
        user = user_manager.get(public_id=result_id)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerInsertError as err:
        return abort(400, err.message)
    api_response = InsertSingleResponse(result_id=result_id,
                                        raw=UserModel.to_dict(user),
                                        url=request.url,
                                        model=UserModel.MODEL)
    return api_response.make_response(prefix='users')
Ejemplo n.º 10
0
def get_user(public_id: int):
    """
    HTTP `GET`/`HEAD` route for a single user resource.

    Args:
        public_id (int): Public ID user.

    Raises:
        ManagerGetError: When the selected user does not exists.

    Notes:
        Calling the route over HTTP HEAD method will result in an empty body.

    Returns:
        GetSingleResponse: Which includes the json data of a UserModel.
    """
    user_manager: UserManager = UserManager(
        database_manager=current_app.database_manager)

    try:
        user: UserModel = user_manager.get(public_id)
    except ManagerGetError as err:
        return abort(404, err.message)
    api_response = GetSingleResponse(UserModel.to_dict(user),
                                     url=request.url,
                                     model=UserModel.MODEL,
                                     body=request.method == 'HEAD')
    return api_response.make_response()
Ejemplo n.º 11
0
    def __init__(self,
                 object_instance: CmdbObject,
                 type_instance: TypeModel,
                 render_user: UserModel,
                 object_manager: CmdbObjectManager = None,
                 ref_render=False):
        self.object_instance: CmdbObject = object_instance
        self.type_instance: TypeModel = type_instance
        self.render_user: UserModel = render_user

        self.object_manager = object_manager
        if self.object_manager:  # TODO: Refactor to pass database-manager in init
            self.type_manager = TypeManager(self.object_manager.dbm)
            self.user_manager = UserManager(self.object_manager.dbm)

        self.ref_render = ref_render
Ejemplo n.º 12
0
def parse_authorization_header(header):
    """
    Parses the HTTP Auth Header to a JWT Token
    Args:
        header: Authorization header of the HTTP Request
    Examples:
        request.headers['Authorization'] or something same
    Returns:
        Valid JWT token
    """
    if not header:
        return None
    value = wsgi_to_bytes(header)
    try:
        auth_type, auth_info = value.split(None, 1)
        auth_type = auth_type.lower()
    except ValueError:
        # Fallback for old versions
        auth_type = b"bearer"
        auth_info = value

    if auth_type == b"basic":
        try:
            username, password = base64.b64decode(auth_info).split(b":", 1)

            with current_app.app_context():
                username = to_unicode(username, "utf-8")
                password = to_unicode(password, "utf-8")

                user_manager: UserManager = UserManager(
                    current_app.database_manager)
                auth_module = AuthModule(
                    SystemSettingsReader(current_app.database_manager))

                try:
                    user_instance = auth_module.login(user_manager, username,
                                                      password)
                except Exception as e:
                    return None
                if user_instance:
                    tg = TokenGenerator(current_app.database_manager)
                    return tg.generate_token(payload={
                        'user': {
                            'public_id': user_instance.get_public_id()
                        }
                    })
                else:
                    return None
        except Exception:
            return None

    if auth_type == b"bearer":
        try:
            tv = TokenValidator()
            decoded_token = tv.decode_token(auth_info)
            tv.validate_token(decoded_token)
            return auth_info
        except Exception:
            return None
    return None
Ejemplo n.º 13
0
    def __init__(self, event, state=False):
        super(ExportdThread, self).__init__()
        self.job = None
        self.job_id = event.get_param("id")
        self.type_id = event.get_param("type_id")
        self.user_id = event.get_param("user_id")
        self.event = event
        self.is_active = state
        self.exception_handling = None

        scr = SystemConfigReader()
        database_options = scr.get_all_values_from_section('Database')
        self.__dbm = DatabaseManagerMongo(**database_options)
        self.log_manager = ExportdLogManager(database_manager=self.__dbm)
        self.exportd_job_manager = ExportdJobManagement(
            database_manager=self.__dbm)
        self.user_manager = UserManager(database_manager=self.__dbm)
Ejemplo n.º 14
0
    def get_request_user(*args, **kwargs):
        from flask import request, current_app
        with current_app.app_context():
            user_manager = UserManager(current_app.database_manager)

        token = parse_authorization_header(request.headers['Authorization'])
        try:
            decrypted_token = TokenValidator().decode_token(token)
        except ValidationError as err:
            return abort(401)
        try:
            user_id = decrypted_token['DATAGERRY']['value']['user'][
                'public_id']
        except ValueError:
            return abort(401)
        user = user_manager.get(user_id)
        kwargs.update({'request_user': user})
        return func(*args, **kwargs)
Ejemplo n.º 15
0
 def __init__(self,
              object_list: List[CmdbObject],
              request_user: UserModel,
              database_manager: DatabaseManagerMongo,
              ref_render=False,
              object_manager: CmdbObjectManager = None):
     self.object_list: List[CmdbObject] = object_list
     self.request_user = request_user
     self.ref_render = ref_render
     self.object_manager = object_manager
     self.type_manager = TypeManager(database_manager=database_manager)
     self.user_manager = UserManager(database_manager=database_manager)
Ejemplo n.º 16
0
    def __init__(self, event: Event, state: bool = False):

        scr = SystemConfigReader()
        database_options = scr.get_all_values_from_section('Database')
        database = DatabaseManagerMongo(**database_options)

        super(ExportdThread, self).__init__()
        self.job = None
        self.job_id = int(event.get_param("id"))
        self.type_id = int(
            event.get_param("type_id")) if event.get_param("type_id") else None
        self.user_id = int(event.get_param("user_id"))
        self.event = event
        self.is_active = state
        self.exception_handling = None

        self.object_manager = CmdbObjectManager(database_manager=database)
        self.log_manager = ExportdLogManager(database_manager=database)
        self.exportd_job_manager = ExportdJobManagement(
            database_manager=database)
        self.user_manager = UserManager(database_manager=database)
Ejemplo n.º 17
0
def delete_group(public_id: int, params: GroupDeletionParameters):
    """
    HTTP `DELETE` route for delete a single group resource.

    Args:
        public_id (int): Public ID of the user.
        params (GroupDeletionParameters): Optional action parameters for handling users when the group \
                                          is going to be deleted.

    Notes:
        Based on the params attribute. Users can be moved or deleted.

    Raises:
        ManagerGetError: When the group with the `public_id` was not found.
        ManagerDeleteError: When something went wrong during the deletion.

    Returns:
        DeleteSingleResponse: Delete result with the deleted group as data.
    """
    group_manager: GroupManager = GroupManager(database_manager=current_app.database_manager,
                                               right_manager=RightManager(rights))
    user_manager: UserManager = UserManager(database_manager=current_app.database_manager)

    # Check of action is set
    if params.action:
        users_in_group: List[UserModel] = user_manager.get_many(Query({'group_id': public_id}))
        if len(users_in_group) > 0:
            if params.action == GroupDeleteMode.MOVE.value:
                if params.group_id:
                    for user in users_in_group:
                        user.group_id = int(params.group_id)
                        try:
                            user_manager.update(user.public_id, user)
                        except ManagerUpdateError as err:
                            return abort(400,
                                         f'Could not move user: {user.public_id} to group: {params.group_id} | '
                                         f'Error: {err.message}')

            if params.action == GroupDeleteMode.DELETE.value:
                for user in users_in_group:
                    try:
                        user_manager.delete(user.public_id)
                    except ManagerDeleteError as err:
                        return abort(400, f'Could not delete user: {user.public_id} | Error: {err.message}')

    try:
        deleted_group = group_manager.delete(public_id=PublicID(public_id))
        api_response = DeleteSingleResponse(raw=UserGroupModel.to_dict(deleted_group), model=UserGroupModel.MODEL)
    except ManagerGetError as err:
        return abort(404, err.message)
    except ManagerDeleteError as err:
        return abort(404, err.message)
    return api_response.make_response()
Ejemplo n.º 18
0
def user_has_right(required_right: str) -> bool:
    """Check if a user has a specific right"""
    from flask import request, current_app
    with current_app.app_context():
        user_manager = UserManager(current_app.database_manager)
        group_manager = GroupManager(current_app.database_manager, RightManager(rights))

    token = parse_authorization_header(request.headers['Authorization'])
    try:
        decrypted_token = TokenValidator(database_manager=current_app.database_manager).decode_token(token)
    except ValidationError as err:
        return abort(401)
    try:
        user_id = decrypted_token['DATAGERRY']['value']['user']['public_id']
        user = user_manager.get(user_id)
        group = group_manager.get(user.group_id)
        right_status = group.has_right(right_name=required_right)
        if not right_status:
            right_status = group.has_extended_right(right_name=required_right)
        return right_status
    except ManagerGetError:
        return False
Ejemplo n.º 19
0
def preset_database(database_manager, database_name):
    from cmdb.database.errors.database_errors import DatabaseNotExists
    from cmdb.security.key.generator import KeyGenerator
    from cmdb.security.security import SecurityManager
    from cmdb.user_management.managers.group_manager import GroupManager
    from cmdb.user_management.managers.user_manager import UserManager
    try:
        database_manager.drop_database(database_name)
    except DatabaseNotExists:
        pass
    from cmdb.user_management import __FIXED_GROUPS__
    from datetime import datetime

    kg = KeyGenerator(database_manager=database_manager)
    kg.generate_rsa_keypair()
    kg.generate_symmetric_aes_key()

    group_manager = GroupManager(database_manager=database_manager)
    user_manager = UserManager(database_manager=database_manager)
    security_manager = SecurityManager(database_manager=database_manager)

    for group in __FIXED_GROUPS__:
        group_manager.insert(group)

    admin_name = 'admin'
    admin_pass = '******'
    from cmdb.user_management import UserModel
    admin_user = UserModel(
        public_id=1,
        user_name=admin_name,
        active=True,
        group_id=__FIXED_GROUPS__[0].public_id,
        registration_time=datetime.now(),
        password=security_manager.generate_hmac(admin_pass),
    )
    user_manager.insert(admin_user)
Ejemplo n.º 20
0
def post_login():
    user_manager: UserManager = UserManager(current_app.database_manager)
    group_manager: GroupManager = GroupManager(
        current_app.database_manager, right_manager=RightManager(rights))
    security_manager: SecurityManager = SecurityManager(
        current_app.database_manager)
    login_data = request.json
    if not request.json:
        return abort(400, 'No valid JSON data was provided')

    request_user_name = login_data['user_name']
    request_password = login_data['password']

    auth_module = AuthModule(
        system_settings_reader.get_all_values_from_section(
            'auth', default=AuthModule.__DEFAULT_SETTINGS__),
        user_manager=user_manager,
        group_manager=group_manager,
        security_manager=security_manager)
    user_instance = None
    try:
        user_instance = auth_module.login(request_user_name, request_password)
    except (AuthenticationProviderNotExistsError,
            AuthenticationProviderNotActivated) as err:
        return abort(503, err.message)
    except Exception as e:
        return abort(401)
    finally:
        # If login success generate user instance with token
        if user_instance:
            tg = TokenGenerator()
            token: bytes = tg.generate_token(
                payload={'user': {
                    'public_id': user_instance.get_public_id()
                }})
            token_issued_at = int(datetime.now().timestamp())
            token_expire = int(tg.get_expire_time().timestamp())

            login_response = LoginResponse(user_instance, token,
                                           token_issued_at, token_expire)

            return login_response.make_response()

        # Login not success
        else:
            return abort(401, 'Could not login')
Ejemplo n.º 21
0
def get_users(params: CollectionParameters):
    """
    HTTP `GET`/`HEAD` route for getting a iterable collection of resources.

    Args:
        params (CollectionParameters): Passed parameters over the http query string

    Returns:
        GetMultiResponse: Which includes a IterationResult of the UserModel.

    Notes:
        Calling the route over HTTP HEAD method will result in an empty body.

    Raises:
        ManagerIterationError: If the collection could not be iterated.
        ManagerGetError: If the collection/resources could not be found.
    """
    user_manager: UserManager = UserManager(
        database_manager=current_app.database_manager)

    try:
        iteration_result: IterationResult[UserModel] = user_manager.iterate(
            filter=params.filter,
            limit=params.limit,
            skip=params.skip,
            sort=params.sort,
            order=params.order)
        users = [UserModel.to_dict(user) for user in iteration_result.results]
        api_response = GetMultiResponse(users,
                                        total=iteration_result.total,
                                        params=params,
                                        url=request.url,
                                        model=UserModel.MODEL,
                                        body=request.method == 'HEAD')
    except ManagerIterationError as err:
        return abort(400, err.message)
    except ManagerGetError as err:
        return abort(404, err.message)
    return api_response.make_response()
Ejemplo n.º 22
0
from cmdb.security.token.generator import TokenGenerator
from cmdb.user_management import UserModel
from cmdb.user_management.managers.user_manager import UserManager
from cmdb.utils.system_reader import SystemSettingsReader
from cmdb.utils.system_writer import SystemSettingsWriter

try:
    from cmdb.utils.error import CMDBError
except ImportError:
    CMDBError = Exception

auth_blueprint = RootBlueprint('auth_rest', __name__, url_prefix='/auth')
LOGGER = logging.getLogger(__name__)

with current_app.app_context():
    user_manager: UserManager = UserManager(current_app.database_manager)
    system_settings_reader: SystemSettingsReader = SystemSettingsReader(
        current_app.database_manager)
    system_setting_writer: SystemSettingsWriter = SystemSettingsWriter(
        current_app.database_manager)


@auth_blueprint.route('/settings/', methods=['GET'])
@auth_blueprint.route('/settings', methods=['GET'])
@login_required
@insert_request_user
@right_required('base.system.view')
def get_auth_settings(request_user: UserModel):
    auth_module = AuthModule(system_settings_reader)
    return make_response(auth_module.settings)
Ejemplo n.º 23
0
    def login(self, user_manager: UserManager, user_name: str,
              password: str) -> Union[UserModel, None]:
        """
        Performs a login try with given username and password
        If the user is not found, iterate over all installed and activated providers
        Args:
            user_manager: Usermanager instance
            user_name: Name of the user
            password: Password

        Returns:
            UserModel: instance if user was found and password was correct
            None: if something went wrong
        """
        user_name = user_name.lower()
        user_instance = None
        try:
            founded_user = user_manager.get_by({'user_name': user_name})
            provider_class_name = founded_user.authenticator
            LOGGER.debug(
                f'[AUTH] Founded user: {founded_user} with provider: {provider_class_name}'
            )
            if not self.provider_exists(provider_class_name):
                raise AuthenticationProviderNotExistsError(provider_class_name)

            provider: ClassVar[
                AuthenticationProvider] = self.get_provider_class(
                    provider_class_name)
            provider_config_class: ClassVar[
                str] = provider.PROVIDER_CONFIG_CLASS
            provider_config_settings = self.settings.get_provider_settings(
                provider.get_name())

            provider_config_instance = provider_config_class(
                **provider_config_settings)
            provider_instance = provider(config=provider_config_instance)
            if not provider_instance.is_active():
                raise AuthenticationProviderNotActivated(
                    f'Provider {provider_class_name} is deactivated')
            if provider_instance.EXTERNAL_PROVIDER and not self.settings.enable_external:
                raise AuthenticationProviderNotActivated(
                    f'External providers are deactivated')
            try:
                user_instance = provider_instance.authenticate(
                    user_name, password)
            except AuthenticationError as ae:
                LOGGER.error(f'[LOGIN] UserModel could not login: {ae}')

        except ManagerGetError as umge:
            LOGGER.error(f'[AUTH] {user_name} not in database: {umge}')
            LOGGER.info(
                f'[AUTH] Check for other providers - request_user: {user_name}'
            )
            # get installed providers
            provider_list = self.providers
            LOGGER.debug(f'[AUTH] Provider list: {provider_list}')
            external_enabled = self.settings.enable_external
            for provider in provider_list:
                LOGGER.debug(f'[AUTH] using provider: {provider}')
                provider_config_class = provider.PROVIDER_CONFIG_CLASS
                provider_settings = self.settings.get_provider_settings(
                    provider.get_name())
                provider_config_instance = provider_config_class(
                    **provider_settings)

                if not provider_config_instance.is_active():
                    continue
                if provider.EXTERNAL_PROVIDER and not self.settings.enable_external:
                    continue
                provider_instance = provider(config=provider_config_instance)
                try:
                    user_instance = provider_instance.authenticate(
                        user_name, password)
                    if user_instance:
                        break
                except AuthenticationError as ae:
                    LOGGER.error(
                        f'[AUTH] UserModel {user_name} could not validate with provider {provider}: {ae}'
                    )
                LOGGER.info(f'[AUTH] Provider instance: {provider_instance}')
        except Exception as e:
            import traceback
            traceback.print_exc()
            LOGGER.error(f'[AUTH] Error while login: {e}')
            return None
        finally:
            return user_instance
Ejemplo n.º 24
0
class ExportdThread(Thread):
    def __init__(self, event, state=False):
        super(ExportdThread, self).__init__()
        self.job = None
        self.job_id = event.get_param("id")
        self.type_id = event.get_param("type_id")
        self.user_id = event.get_param("user_id")
        self.event = event
        self.is_active = state
        self.exception_handling = None

        scr = SystemConfigReader()
        database_options = scr.get_all_values_from_section('Database')
        self.__dbm = DatabaseManagerMongo(**database_options)
        self.log_manager = ExportdLogManager(database_manager=self.__dbm)
        self.exportd_job_manager = ExportdJobManagement(
            database_manager=self.__dbm)
        self.user_manager = UserManager(database_manager=self.__dbm)

    def run(self):
        try:
            if self.type_id:
                for obj in self.exportd_job_manager.get_job_by_event_based(
                        True):
                    if next((item for item in obj.get_sources()
                             if item["type_id"] == self.type_id), None):
                        if obj.get_active(
                        ) and obj.scheduling["event"]["active"]:
                            self.job = obj
                            self.worker()
            elif self.is_active:
                self.job = self.exportd_job_manager.get_job(self.job_id)
                self.worker()
        except Exception as ex:
            LOGGER.error(ex)
            return ex

    def worker(self):
        cur_user = None
        try:
            # update job for UI
            self.job.state = ExecuteState.RUNNING.name
            self.job.last_execute_date = datetime.utcnow()

            # get current user
            cur_user = self.user_manager.get(self.user_id)

            self.exportd_job_manager.update_job(self.job,
                                                self.user_manager.get(
                                                    self.user_id),
                                                event_start=False)
            # execute Exportd job
            job = cmdb.exportd.exporter_base.ExportdManagerBase(self.job)
            job.execute(self.event, cur_user.get_public_id(),
                        cur_user.get_display_name())

        except Exception as err:
            LOGGER.error(err)
            self.exception_handling = err
            # Generate Error log
            try:
                log_params = {
                    'job_id': self.job.get_public_id(),
                    'state': False,
                    'user_id': cur_user.get_public_id(),
                    'user_name': cur_user.get_display_name(),
                    'event': self.event.get_type(),
                    'message': ['Successful'] if not err else err.args,
                }
                self.log_manager.insert_log(action=LogAction.EXECUTE,
                                            log_type=ExportdJobLog.__name__,
                                            **log_params)
            except LogManagerInsertError as err:
                LOGGER.error(err)
        finally:
            # update job for UI
            self.job.state = ExecuteState.SUCCESSFUL.name if not self.exception_handling else ExecuteState.FAILED.name
            self.exportd_job_manager.update_job(self.job,
                                                self.user_manager.get(
                                                    self.user_id),
                                                event_start=False)
Ejemplo n.º 25
0
class CmdbRender:
    AUTHOR_ANONYMOUS_NAME = 'unknown'

    def __init__(self,
                 object_instance: CmdbObject,
                 type_instance: TypeModel,
                 render_user: UserModel,
                 object_manager: CmdbObjectManager = None,
                 ref_render=False):
        self.object_instance: CmdbObject = object_instance
        self.type_instance: TypeModel = type_instance
        self.render_user: UserModel = render_user

        self.object_manager = object_manager
        if self.object_manager:  # TODO: Refactor to pass database-manager in init
            self.type_manager = TypeManager(self.object_manager.dbm)
            self.user_manager = UserManager(self.object_manager.dbm)

        self.ref_render = ref_render

    @property
    def object_instance(self) -> CmdbObject:
        """
        Object of the class CmdbObject that has already been instantiated.
        The data should come from the database and already be validated.
        This already happens when the object is instantiated.
        """
        return self._object_instance

    @object_instance.setter
    def object_instance(self, object_instance: CmdbObject):
        """
        Property setter for object_instance. The render only checks whether the passed object
        belongs to the correct class, not whether it is valid.
        """
        if not isinstance(object_instance, CmdbObject):
            raise ObjectInstanceError()
        else:
            self._object_instance = object_instance

    @property
    def type_instance(self) -> TypeModel:
        """
        Object of the class TypeModel that has already been instantiated.
        The data should come from the database and already be validated.
        This already happens when the object is instantiated.
        """
        return self._type_instance

    @type_instance.setter
    def type_instance(self, type_instance: TypeModel):
        """
        Property setter for type_instance. The render only checks whether the passed object
        belongs to the correct class, not whether it is valid.
        """
        if not isinstance(type_instance, TypeModel):
            raise TypeInstanceError()
        self._type_instance = type_instance

    def result(self) -> RenderResult:
        return self._generate_result()

    def _generate_result(self) -> RenderResult:
        render_result = RenderResult()
        try:
            render_result = self.__generate_object_information(render_result)
            render_result = self.__generate_type_information(render_result)
            render_result = self.__set_fields(render_result)
            render_result = self.__set_sections(render_result)
            render_result = self.__set_summaries(render_result)
            render_result = self.__set_external(render_result)
        except CMDBError as err:
            import traceback
            traceback.print_exc()
            raise RenderError(
                f'Error while generating a CMDBResult: {str(err)}')
        return render_result

    def __generate_object_information(
            self, render_result: RenderResult) -> RenderResult:
        try:
            author_name = self.user_manager.get(
                self.object_instance.author_id).get_display_name()
        except CMDBError:
            author_name = CmdbRender.AUTHOR_ANONYMOUS_NAME

        if self.object_instance.editor_id:
            try:
                editor_name = self.user_manager.get(
                    self.object_instance.editor_id).get_display_name()
            except CMDBError:
                editor_name = None
        else:
            editor_name = None

        render_result.object_information = {
            'object_id': self.object_instance.public_id,
            'creation_time': self.object_instance.creation_time,
            'last_edit_time': self.object_instance.last_edit_time,
            'author_id': self.object_instance.author_id,
            'author_name': author_name,
            'editor_id': self.object_instance.editor_id,
            'editor_name': editor_name,
            'active': self.object_instance.active,
            'version': self.object_instance.version
        }
        return render_result

    def __generate_type_information(
            self, render_result: RenderResult) -> RenderResult:
        try:
            author_name = self.user_manager.get(
                self.type_instance.author_id).get_display_name()
        except CMDBError as err:
            author_name = CmdbRender.AUTHOR_ANONYMOUS_NAME
        try:
            self.type_instance.render_meta.icon
        except KeyError:
            self.type_instance.render_meta.icon = ''
        render_result.type_information = {
            'type_id': self.type_instance.public_id,
            'type_name': self.type_instance.name,
            'type_label': self.type_instance.label,
            'creation_time': self.type_instance.creation_time,
            'author_id': self.type_instance.author_id,
            'author_name': author_name,
            'icon': self.type_instance.render_meta.icon,
            'active': self.type_instance.active,
            'version': self.type_instance.version,
            'acl': self.type_instance.acl.to_json(self.type_instance.acl)
        }
        return render_result

    def __set_fields(self, render_result: RenderResult) -> RenderResult:
        render_result.fields = self.__merge_fields_value()
        return render_result

    def __set_sections(self, render_result: RenderResult) -> RenderResult:
        try:
            render_result.sections = [
                section.to_json(section)
                for section in self.type_instance.render_meta.sections
            ]
        except (IndexError, ValueError):
            render_result.sections = []
        return render_result

    def __merge_field_content_section(self, field: dict, object_: CmdbObject):
        curr_field = [x for x in object_.fields
                      if x['name'] == field['name']][0]
        if curr_field['name'] == field['name'] and field.get('value'):
            field['default'] = field['value']
        field['value'] = curr_field['value']
        # handle dates that are stored as strings
        if field['type'] == 'date' and isinstance(field['value'],
                                                  str) and field['value']:
            field['value'] = parse(field['value'], fuzzy=True)

        if self.ref_render and field['type'] == 'ref' and field['value']:
            field['reference'] = self.__merge_references(field)
        return field

    def __merge_fields_value(self) -> List[dict]:
        """
        Checks all fields for references.
        Fields with references are extended by the property 'references'.
        All reference values are stored in the new property.
        """
        field_map = []
        for idx, section in enumerate(self.type_instance.render_meta.sections):
            if type(section) is TypeFieldSection and isinstance(
                    section, TypeFieldSection):
                for section_field in section.fields:
                    field = {}
                    try:
                        field = self.type_instance.get_field(section_field)
                        field = self.__merge_field_content_section(
                            field, self.object_instance)

                        if field['type'] == 'ref' and (not self.ref_render
                                                       or 'summaries'
                                                       not in field):
                            ref_field_name: str = field['name']
                            field = self.type_instance.get_field(
                                ref_field_name)
                            reference_id: int = self.object_instance.get_value(
                                ref_field_name)
                            field['value'] = reference_id
                            reference_object: CmdbObject = self.object_manager.get_object(
                                public_id=reference_id)
                            ref_type: TypeModel = self.type_manager.get(
                                reference_object.get_type_id())
                            field['reference'] = {
                                'type_id': ref_type.public_id,
                                'type_name': ref_type.name,
                                'type_label': ref_type.label,
                                'object_id': reference_id,
                                'summaries': []
                            }
                            for ref_section_field_name in ref_type.get_fields(
                            ):
                                ref_section_field = ref_type.get_field(
                                    ref_section_field_name['name'])
                                try:
                                    ref_field = self.__merge_field_content_section(
                                        ref_section_field, reference_object)
                                except (FileNotFoundError, ValueError,
                                        IndexError):
                                    continue
                                field['reference']['summaries'].append(
                                    ref_field)

                    except (ValueError, IndexError, FileNotFoundError,
                            ObjectManagerGetError):
                        field['value'] = None

                    field_map.append(field)

            elif type(section) is TypeReferenceSection and isinstance(
                    section, TypeReferenceSection):
                ref_field_name: str = f'{section.name}-field'
                ref_field = self.type_instance.get_field(ref_field_name)
                reference_id: int = self.object_instance.get_value(
                    ref_field_name)
                ref_field['value'] = reference_id
                try:
                    reference_object: CmdbObject = self.object_manager.get_object(
                        public_id=reference_id)
                except ObjectManagerGetError:
                    reference_object = None
                ref_type: TypeModel = self.type_manager.get(
                    section.reference.type_id)
                ref_section = ref_type.get_section(
                    section.reference.section_name)
                ref_field['references'] = {
                    'type_id': ref_type.public_id,
                    'type_name': ref_type.name,
                    'type_label': ref_type.label,
                    'fields': []
                }
                if not ref_section:
                    continue
                if not section.reference.selected_fields or len(
                        section.reference.selected_fields) == 0:
                    selected_ref_fields = ref_section.fields
                    section.reference.selected_fields = selected_ref_fields
                    self.type_instance.render_meta.sections[idx] = section
                else:
                    selected_ref_fields = [
                        f for f in ref_section.fields
                        if f in section.reference.selected_fields
                    ]
                for ref_section_field_name in selected_ref_fields:
                    ref_section_field = ref_type.get_field(
                        ref_section_field_name)
                    if reference_object:
                        try:
                            ref_section_field = self.__merge_field_content_section(
                                ref_section_field, reference_object)
                        except (FileNotFoundError, ValueError, IndexError,
                                ObjectManagerGetError):
                            continue
                    ref_field['references']['fields'].append(ref_section_field)
                field_map.append(ref_field)
        return field_map

    def __merge_references(self, current_field):

        # Initialise TypeReference
        reference = TypeReference(type_id=0,
                                  object_id=0,
                                  type_label='',
                                  line='')

        if current_field['value']:

            try:
                ref_object = self.object_manager.get_object(
                    int(current_field['value']),
                    user=self.render_user,
                    permission=AccessControlPermission.READ)
            except AccessDeniedError as err:
                return err.message
            except ObjectManagerGetError:
                return TypeReference.to_json(reference)

            try:
                ref_type = self.object_manager.get_type(
                    ref_object.get_type_id())

                _summary_fields = []
                _nested_summaries = self.type_instance.get_nested_summaries()
                _nested_summary_fields = ref_type.get_nested_summary_fields(
                    _nested_summaries)
                _nested_summary_line = ref_type.get_nested_summary_line(
                    _nested_summaries)

                reference.type_id = ref_type.get_public_id()
                reference.object_id = int(current_field['value'])
                reference.type_label = ref_type.label
                reference.icon = ref_type.get_icon()
                reference.prefix = ref_type.has_nested_prefix(
                    _nested_summaries)

                _summary_fields = _nested_summary_fields \
                    if (_nested_summary_line or _nested_summary_fields) else ref_type.get_summary().fields

                summaries = []
                summary_values = []
                for field in _summary_fields:
                    summary_value = str([
                        x for x in ref_object.fields
                        if x['name'] == field['name']
                    ][0]['value'])
                    summaries.append({
                        "value": summary_value,
                        "type": field.get('type')
                    })
                    summary_values.append(summary_value)
                reference.summaries = summaries

                try:
                    # fill the summary line with summaries value data
                    reference.line = _nested_summary_line
                    if not reference.line_requires_fields():
                        reference.summaries = []
                    if _nested_summary_line:
                        reference.fill_line(summary_values)
                except (TypeReferenceLineFillError, Exception):
                    pass

            except ObjectManagerGetError:
                return TypeReference.to_json(reference)

        return TypeReference.to_json(reference)

    def __set_summaries(self, render_result: RenderResult) -> RenderResult:
        # global summary list
        summary_list = []
        summary_line = ''
        default_line = f'{self.type_instance.label} #{self.object_instance.public_id}'
        if not self.type_instance.has_summaries():
            render_result.summaries = summary_list
            render_result.summary_line = default_line
            return render_result
        try:
            summary_list = self.type_instance.get_summary().fields
            render_result.summaries = summary_list
            first = True

            for line in summary_list:
                if first:
                    summary_line += f'{line["value"]}'
                    first = False
                else:
                    summary_line += f' | {line["value"]}'

            render_result.summary_line = summary_line
        except Exception:
            summary_line = default_line
        finally:
            render_result.summary_line = summary_line
        return render_result

    def __set_external(self, render_result: RenderResult) -> RenderResult:
        """
        get filled external links
        Returns:
            list of filled external links (TypeExternalLink)
        """
        # global external list
        external_list = []
        # checks if type has externals defined
        if not self.type_instance.has_externals():
            render_result.externals = []
        # loop over all externals
        for ext_link in self.type_instance.get_externals():
            # append all values for required field in this list
            field_list = []
            # if data are missing or empty append here
            missing_list = []
            try:
                # get TypeExternalLink definitions from type
                ext_link_instance = self.type_instance.get_external(
                    ext_link.name)
                # check if link requires data - regex check for {}
                if ext_link_instance.link_requires_fields():
                    # check if has fields
                    if not ext_link_instance.has_fields():
                        raise ValueError(field_list)
                    # for every field get the value data from object_instance
                    for ext_link_field in ext_link_instance.fields:
                        try:
                            if ext_link_field == 'object_id':
                                field_value = self.object_instance.public_id
                            else:
                                field_value = self.object_instance.get_value(
                                    ext_link_field)
                            if field_value is None or field_value == '':
                                # if value is empty or does not exists
                                raise ValueError(ext_link_field)
                            field_list.append(field_value)
                        except CMDBError:
                            # if error append missing data
                            missing_list.append(ext_link_instance)
                if len(missing_list) > 0:
                    raise RuntimeError(missing_list)
                try:
                    # fill the href with field value data
                    ext_link_instance.fill_href(field_list)
                except ValueError:
                    continue
            except (CMDBError, Exception):
                continue
            external_list.append(TypeExternalLink.to_json(ext_link_instance))
            render_result.externals = external_list
        return render_result