Beispiel #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')
Beispiel #2
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
Beispiel #3
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)
Beispiel #4
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)
Beispiel #5
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
Beispiel #6
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)
Beispiel #7
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