Ejemplo n.º 1
0
    def create(self, validated_data, **kwargs):
        """Create the new object."""
        attributes = validated_data.get('attributes', {})
        if not isinstance(attributes, dict):
            raise APIException(
                _('Attributes must be a dictionary of (string, string) pairs.')
            )

        if any(not isinstance(key, str) or not isinstance(aval, str)
               for key, aval in list(attributes.items())):
            raise APIException(_('Attributes must be a dictionary (str, str)'))

        workflow_obj = None
        try:
            workflow_obj = Workflow(
                user=self.context['request'].user,
                name=validated_data['name'],
                description_text=validated_data.get('description_text', ''),
                nrows=0,
                ncols=0,
                attributes=attributes,
            )

            workflow_obj.save()
        except Exception:
            if workflow_obj and workflow_obj.id:
                workflow_obj.delete()
            raise APIException(_('Workflow could not be created.'))

        return workflow_obj
Ejemplo n.º 2
0
def _do_clone_workflow(workflow: Workflow) -> Workflow:
    """Clone the workflow.

    :param workflow: source workflow

    :return: Clone object
    """
    new_workflow = Workflow(
        user=workflow.user,
        name=create_new_name(
            workflow.name,
            Workflow.objects.filter(
                Q(user=workflow.user) | Q(shared=workflow.user)),
        ),
        description_text=workflow.description_text,
        nrows=workflow.nrows,
        ncols=workflow.ncols,
        attributes=copy.deepcopy(workflow.attributes),
        query_builder_ops=copy.deepcopy(workflow.query_builder_ops),
        luser_email_column_md5=workflow.luser_email_column_md5,
        lusers_is_outdated=workflow.lusers_is_outdated)
    new_workflow.save()

    try:
        new_workflow.shared.set(list(workflow.shared.all()))
        new_workflow.lusers.set(list(workflow.lusers.all()))

        # Clone the columns
        for item_obj in workflow.columns.all():
            do_clone_column_only(item_obj, new_workflow=new_workflow)

        # Update the luser_email_column if needed:
        if workflow.luser_email_column:
            new_workflow.luser_email_column = new_workflow.columns.get(
                name=workflow.luser_email_column.name, )

        # Clone the DB table
        clone_table(workflow.get_data_frame_table_name(),
                    new_workflow.get_data_frame_table_name())

        # Clone actions
        for item_obj in workflow.actions.all():
            do_clone_action(item_obj, new_workflow)

        for item_obj in workflow.views.all():
            do_clone_view(item_obj, new_workflow)

        # Done!
        new_workflow.save()
    except Exception as exc:
        new_workflow.delete()
        raise exc

    return new_workflow
Ejemplo n.º 3
0
    def create(self, validated_data, **kwargs):
        """Create the new workflow."""
        wflow_name = self.context.get('name')
        if not wflow_name:
            wflow_name = self.validated_data.get('name')
            if not wflow_name:
                raise Exception(_('Unexpected empty workflow name.'))

            if Workflow.objects.filter(name=wflow_name,
                                       user=self.context['user']).exists():
                raise Exception(
                    _('There is a workflow with this name. ' +
                      'Please provide a workflow name in the import page.'))

        # Initial values
        workflow_obj = None
        try:
            workflow_obj = Workflow(
                user=self.context['user'],
                name=wflow_name,
                description_text=validated_data['description_text'],
                nrows=0,
                ncols=0,
                attributes=validated_data['attributes'],
                query_builder_ops=validated_data.get('query_builder_ops', {}),
            )
            workflow_obj.save()

            # Create the columns
            column_data = ColumnSerializer(data=validated_data.get(
                'columns', []),
                                           many=True,
                                           context={'workflow': workflow_obj})
            # And save its content
            if column_data.is_valid():
                columns = column_data.save()
            else:
                raise Exception(_('Unable to save column information'))

            # If there is any column with position = 0, recompute (this is to
            # guarantee backward compatibility.
            if any(col.position == 0 for col in columns):
                for idx, col in enumerate(columns):
                    col.position = idx + 1
                    col.save()

            # Load the data frame
            data_frame = validated_data.get('data_frame')
            if data_frame is not None:
                # Store the table in the DB
                store_table(
                    data_frame,
                    workflow_obj.get_data_frame_table_name(),
                    dtype={
                        col.name: col.data_type
                        for col in workflow_obj.columns.all()
                    },
                )

                # Reconcile now the information in workflow and columns with
                # the one loaded
                workflow_obj.ncols = validated_data['ncols']
                workflow_obj.nrows = validated_data['nrows']

                workflow_obj.save()

            # Create the actions pointing to the workflow
            action_data = ActionSerializer(data=validated_data.get(
                'actions', []),
                                           many=True,
                                           context={
                                               'workflow': workflow_obj,
                                               'columns': columns
                                           })

            if action_data.is_valid():
                action_data.save()
            else:
                raise Exception(_('Unable to save column information'))

            # Create the views pointing to the workflow
            view_data = ViewSerializer(data=validated_data.get('views', []),
                                       many=True,
                                       context={
                                           'workflow': workflow_obj,
                                           'columns': columns
                                       })

            if view_data.is_valid():
                view_data.save()
            else:
                raise Exception(_('Unable to save column information'))
        except Exception:
            # Get rid of the objects created
            if workflow_obj:
                if workflow_obj.id:
                    workflow_obj.delete()
            raise

        return workflow_obj
Ejemplo n.º 4
0
    def post(self, request, object_id=None, action=None):
        try:
            if not action:
                # return workflow_edit(request, None, api=True)
                pass

            enabled = request.POST.get('enabled') is not False
            defender_policy = False
            fqdn = ""
            public_dir = "/"

            try:
                frontend = Frontend.objects.get(pk=request.POST['frontend'])

                if frontend.mode == "http":
                    try:
                        fqdn = request.POST['fqdn']
                        if not validators.domain(fqdn):
                            return JsonResponse({
                                'error': _('This FQDN is not valid')
                            })

                        public_dir = request.POST['public_dir']
                        if public_dir and len(public_dir):
                            if public_dir[0] != '/':
                                public_dir = '/' + public_dir
                            if public_dir[-1] != '/':
                                public_dir += '/'

                    except KeyError:
                        return JsonResponse({
                            'error': _('For a HTTP Frontend, you must define a FQDN & a public_dir')
                        })
            except Frontend.DoesNotExist:
                return JsonResponse({
                    'error': _('frontend with id {} does not exist'.format(request.POST['frontend']))
                }, status=401)
            except KeyError:
                return JsonResponse({
                    'error': _('You must define a frontend for a workflow')
                }, status=401)

            try:
                backend = Backend.objects.get(pk=request.POST['backend'])

                if frontend.mode != backend.mode:
                    return JsonResponse({
                        'error': _('Frontend and Backend must be in the same mode.')
                    })
            except Backend.DoesNotExist:
                return JsonResponse({
                    'error': _('Backend with id {} does not exist'.format(request.POST['backend']))
                }, status=401)
            except KeyError:
                return JsonResponse({
                    'error': _('You must define a backend for a workflow')
                }, status=401)

            if request.POST.get('defender_policy'):
                try:
                    defender_policy = DefenderPolicy.objects.get(pk=request.POST['defender_policy'])
                except DefenderPolicy.DoesNotExist:
                    return JsonResponse({
                        'error': _('Defender Policy with id {} does not exist'.format(request.POST['defender_policy']))
                    }, status=401)

            try:
                if object_id:
                    workflow = Workflow.objects.get(pk=object_id)
                else:
                    workflow = Workflow()

                workflow.enabled = enabled
                workflow.name = request.POST['name']
                workflow.fqdn = fqdn
                workflow.public_dir = public_dir
                workflow.frontend = frontend
                workflow.backend = backend
                workflow.save()

                workflow_acls = []

                if defender_policy:
                    workflow.defender_policy = defender_policy

                workflow.workflowacl_set.all().delete()
                for i, tmp_acl in enumerate(json.loads(request.POST.get('acl_frontend', "[]"))):
                    status, acl = format_acl_from_api(tmp_acl, i, before_policy=True)
                    if not status:
                        return acl

                    acl.workflow = workflow
                    workflow_acls.append(acl)
                    acl.save()

                for i, tmp_acl in enumerate(json.loads(request.POST.get('acl_backend', "[]"))):
                    status, acl = format_acl_from_api(tmp_acl, i, before_policy=False)
                    if not status:
                        return acl

                    acl.workflow = workflow
                    workflow_acls.append(acl)
                    acl.save()

                workflow.workflow_json = generate_workflow(workflow)
                workflow.save()

                nodes = workflow.frontend.reload_conf()
                workflow.backend.reload_conf()

                if workflow.defender_policy:
                    logger.info("Need to reload the Defender Policy SPOE configuration")
                    Cluster.api_request(
                        "darwin.defender_policy.policy.write_defender_backend_conf",
                        workflow.defender_policy.pk
                    )
                    Cluster.api_request(
                        "darwin.defender_policy.policy.write_defender_spoe_conf",
                        workflow.defender_policy.pk
                    )

                # Reload HAProxy on concerned nodes
                for node in nodes:
                    api_res = node.api_request("services.haproxy.haproxy.restart_service")
                    if not api_res.get('status'):
                        logger.error("Workflow::edit: API error while trying to "
                                     "restart HAProxy service : {}".format(api_res.get('message')))
                        for workflow_acl in workflow.workflowacl_set.all():
                            workflow_acl.delete()

                        try:
                            workflow.delete()
                        except Exception:
                            pass

                        return JsonResponse({
                            'error': api_res.get('message')
                        }, status=500)

                return JsonResponse({
                    'message': _('Workflow saved')
                })

            except KeyError:
                return JsonResponse({
                    'error': _('Partial data')
                }, status=401)

            if action and not object_id:
                return JsonResponse({
                    'error': _('You must specify an ID')
                }, status=401)

            if action not in list(COMMAND_LIST.keys()):
                return JsonResponse({
                    'error': _('Action not allowed')
                }, status=403)

            return COMMAND_LIST[action](request, object_id, api=True)

        except Exception as e:
            logger.critical(e, exc_info=1)
            if settings.DEV_MODE:
                error = str(e)
            else:
                error = _("An error has occurred")

        return JsonResponse({
            'error': error
        }, status=500)