Example #1
0
def verify_import_access(user: UserModel, _type: TypeModel, _manager: TypeManager):
    """Validate if a user has access to objects of this type."""

    location = 'acl.groups.includes.' + str(user.group_id)
    query = {'$and': [{'$or': [
        {'$or': [
            {'acl': {'$exists': False}}, {'acl.activated': False}]
        },
        {'$and': [
            {'acl.activated': True},
            {'$and': [
                {location: {'$exists': True}},
                {location: {'$all': [
                    AccessControlPermission.READ.value,
                    AccessControlPermission.CREATE.value,
                    AccessControlPermission.UPDATE.value]
                    }
                }
            ]
            }
        ]
        }]
    }, {'public_id': _type.public_id}]}
    types_ = _manager.iterate(filter=query, limit=1, skip=0, sort='public_id', order=1)
    if len([TypeModel.to_json(_) for _ in types_.results]) == 0:
        raise AccessDeniedError(f'The objects of the type `{_type.name}` are protected by ACL permission!')
Example #2
0
 def delete_object(self,
                   public_id: int,
                   user: UserModel,
                   permission: AccessControlPermission = None):
     type_id = self.get_object(public_id=public_id).type_id
     type_ = self._type_manager.get(type_id)
     if not type_.active:
         raise AccessDeniedError(
             f'Objects cannot be removed because type `{type_.name}` is deactivated.'
         )
     verify_access(type_, user, permission)
     try:
         if self._event_queue:
             event = Event(
                 "cmdb.core.object.deleted", {
                     "id": public_id,
                     "type_id": self.get_object(public_id).get_type_id(),
                     "user_id": user.get_public_id(),
                     "event": 'delete'
                 })
             self._event_queue.put(event)
         ack = self._delete(CmdbObject.COLLECTION, public_id)
         return ack
     except (CMDBError, Exception):
         raise ObjectDeleteError(msg=public_id)
def verify_access(model: TypeModel, user: UserModel = None, permission: AccessControlPermission = None):
    """Validate if a user has access to objects of this type."""
    if not user or not permission:
        return

    verify = has_access_control(model, user, permission)
    if not verify:
        raise AccessDeniedError('Protected by ACL permission!')
Example #4
0
    def insert_object(self,
                      data: (CmdbObject, dict),
                      user: UserModel = None,
                      permission: AccessControlPermission = None) -> int:
        """
        Insert new CMDB Object
        Args:
            data: init data
            user: current user, to detect who triggered event
            permission: extended user acl rights
        Returns:
            Public ID of the new object in database
        """
        new_object = None
        if isinstance(data, dict):
            try:
                new_object = CmdbObject(**data)
            except CMDBError as e:
                LOGGER.debug(
                    f'Error while inserting object - error: {e.message}')
                raise ObjectManagerInsertError(e)
        elif isinstance(data, CmdbObject):
            new_object = data

        type_ = self._type_manager.get(new_object.type_id)
        if not type_.active:
            raise AccessDeniedError(
                f'Objects cannot be created because type `{type_.name}` is deactivated.'
            )

        verify_access(type_, user, permission)

        try:
            ack = self.dbm.insert(collection=CmdbObject.COLLECTION,
                                  data=new_object.__dict__)
            if self._event_queue:
                event = Event(
                    "cmdb.core.object.added", {
                        "id": new_object.get_public_id(),
                        "type_id": new_object.get_type_id(),
                        "user_id": new_object.author_id,
                        "event": 'insert'
                    })
                self._event_queue.put(event)
        except (CMDBError, PublicIDAlreadyExists) as e:
            raise ObjectInsertError(e)
        return ack
Example #5
0
    def update_object(self,
                      data: (dict, CmdbObject),
                      user: UserModel = None,
                      permission: AccessControlPermission = None) -> str:

        if isinstance(data, dict):
            update_object = CmdbObject(**data)
        elif isinstance(data, CmdbObject):
            update_object = data
        else:
            raise ObjectManagerUpdateError(
                'Wrong CmdbObject init format - expecting CmdbObject or dict')
        update_object.last_edit_time = datetime.now(timezone.utc)
        if user:
            update_object.editor_id = user.public_id

        type_ = self._type_manager.get(update_object.type_id)
        if not type_.active:
            raise AccessDeniedError(
                f'Objects cannot be updated because type `{type_.name}` is deactivated.'
            )
        verify_access(type_, user, permission)

        ack = self._update(collection=CmdbObject.COLLECTION,
                           public_id=update_object.get_public_id(),
                           data=update_object.__dict__)

        if self._event_queue and user:
            event = Event(
                "cmdb.core.object.updated", {
                    "id": update_object.get_public_id(),
                    "type_id": update_object.get_type_id(),
                    "user_id": user.get_public_id(),
                    'event': 'update'
                })
            self._event_queue.put(event)
        return ack.acknowledged
Example #6
0
def import_objects(request_user: UserModel):
    # Check if file exists
    if not request.files:
        return abort(400, 'No import file was provided')
    request_file: FileStorage = get_file_in_request('file', request.files)

    filename = secure_filename(request_file.filename)
    working_file = f'/tmp/{filename}'
    request_file.save(working_file)

    # Load file format
    file_format = request.form.get('file_format', None)

    # Load parser config
    parser_config: dict = get_element_from_data_request('parser_config', request) or {}
    if parser_config == {}:
        LOGGER.info('No parser config was provided - using default parser config')

    # Check for importer config
    importer_config_request: dict = get_element_from_data_request('importer_config', request) or None
    if not importer_config_request:
        return abort(400, 'No import config was provided')

    # Check if type exists
    try:
        type_manager = TypeManager(database_manager=current_app.database_manager)
        type_ = type_manager.get(importer_config_request.get('type_id'))
        if not type_.active:
            raise AccessDeniedError(f'Objects cannot be created because type `{type_.name}` is deactivated.')
        verify_import_access(user=request_user,
                             _type=type_,
                             _manager=type_manager)
    except ObjectManagerGetError as err:
        return abort(404, err.message)
    except AccessDeniedError as err:
        return abort(403, err.message)

    # Load parser
    try:
        parser_class = load_parser_class('object', file_format)
    except ParserLoadError as ple:
        return abort(406, ple.message)
    parser = parser_class(parser_config)

    LOGGER.info(f'Parser {parser_class} was loaded')

    # Load importer config
    try:
        importer_config_class = load_importer_config_class('object', file_format)
    except ImporterLoadError as ile:
        return abort(406, ile.message)
    importer_config = importer_config_class(**importer_config_request)
    LOGGER.debug(importer_config_request)
    # Load importer
    try:
        importer_class = load_importer_class('object', file_format)
    except ImporterLoadError as ile:
        return abort(406, ile.message)
    importer = importer_class(working_file, importer_config, parser, object_manager, request_user)
    LOGGER.info(f'Importer {importer_class} was loaded')

    try:
        import_response: ImporterObjectResponse = importer.start_import()
    except ImportRuntimeError as ire:
        LOGGER.error(f'Error while importing objects: {ire.message}')
        return abort(500, ire.message)
    except AccessDeniedError as err:
        return abort(403, err.message)

    # close request file
    request_file.close()

    # log all successful imports
    for message in import_response.success_imports:
        try:

            # get object state of every imported object
            current_type_instance = object_manager.get_type(importer_config_request.get('type_id'))
            current_object = object_manager.get_object(message.public_id)
            current_object_render_result = CmdbRender(object_instance=current_object,
                                                      type_instance=current_type_instance,
                                                      render_user=request_user,
                                                      object_manager=object_manager).result()

            # insert object create log
            log_params = {
                'object_id': message.public_id,
                'user_id': request_user.get_public_id(),
                'user_name': request_user.get_display_name(),
                'comment': 'Object was imported',
                'render_state': json.dumps(current_object_render_result, default=default).encode('UTF-8'),
                'version': current_object.version
            }
            log_manager.insert(action=LogAction.CREATE, log_type=CmdbObjectLog.__name__, **log_params)

        except ObjectManagerGetError as err:
            LOGGER.error(err)
            return abort(404)
        except RenderError as err:
            LOGGER.error(err)
            return abort(500)
        except LogManagerInsertError as err:
            LOGGER.error(err)

    return make_response(import_response)