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')
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
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)
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)
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
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)
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