import io import json import logging from django.forms import model_to_dict from django.http import HttpResponse from rest_framework import status from rest_framework.decorators import action from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin from rest_framework.response import Response from rest_framework.viewsets import GenericViewSet, ModelViewSet from core.mixins import ApiPermissionCheckMixin, ExportToJSONMixin from correlation.models import Group, Rule from correlation.serializers import (RuleSerializer, GroupSerializer, ImporRulesFileSerializer) from correlation.services.import_service import ImportRulesService from correlation.tasks import update_correlator_tasks from perms.models import Perm _log = logging.getLogger(__name__) class RuleViewSet(ApiPermissionCheckMixin, ExportToJSONMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet): serializer_class = RuleSerializer console_permissions = {"destroy": [Perm.can_delete_correlation_rules], "list": [Perm.can_view_correlation_rules_list], "create": [Perm.can_create_and_edit_correlation_rule], "retrieve": [Perm.can_view_correlation_rule_card], "update": [Perm.can_create_and_edit_correlation_rule], "partial_update": [Perm.can_create_and_edit_correlation_rule], "json_export": [Perm.can_create_and_edit_correlation_rule], "import_rules": [Perm.can_create_and_edit_correlation_rule], } def get_queryset(self): if self.action == 'json_export': return Rule.objects.exclude(actions_json__contains=[{'type': 'firewall'}]) return Rule.objects.order_by('-status', 'id') def create(self, request, *args, **kwargs): data_dict = request.data.copy() data_dict["kind"] = "JSON" rule = RuleSerializer(data=data_dict) if rule.is_valid(): rule.save() return Response(data=rule.data, status=status.HTTP_201_CREATED) else: _log.critical(f"\n\n\nError: {rule.errors}\n\nData: {rule.data}\n\n") return Response(data=rule.errors, status=status.HTTP_400_BAD_REQUEST) def get_object(self): # get the initial value of the model fields # in the signal (correlation/services/signals.py) we make a decision to increase rule.rev or not rule = super().get_object() rule._initial = model_to_dict(rule, fields=[field.name for field in rule._meta.fields]) return rule @action(methods=['POST'], detail=False) def import_rules(self, request, *args, **kwargs): serializer = ImporRulesFileSerializer(request.POST, request.FILES) serializer.is_valid(raise_exception=True) service = ImportRulesService(serializer.validated_data['uploaded_file']) result = service.run_import() # send all exists rules to correlator update_correlator_tasks(clear_store=True) # create report file file = io.BytesIO() file.write(json.dumps(result, ensure_ascii=False, indent=4).encode()) file.seek(0) response = HttpResponse(file, content_type="application/file") response['Content-Disposition'] = f'attachment; filename="Report.json"' return response class GroupViewSet(ApiPermissionCheckMixin, ModelViewSet): serializer_class = GroupSerializer console_permissions = {'list': [Perm.can_view_correlation_rule_card], 'create': [Perm.can_edit_correlation_groups], 'retrieve': [Perm.can_edit_correlation_groups], 'destroy': [Perm.can_edit_correlation_groups], 'update': [Perm.can_edit_correlation_groups], 'partial_update': [Perm.can_edit_correlation_groups]} queryset = Group.objects.all()