import logging import redis import requests from django.conf import settings from django.contrib.auth.decorators import login_required, permission_required from django.http import JsonResponse from django.template.context_processors import csrf from django.utils.translation import gettext_lazy from rest_framework.decorators import api_view from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, ListModelMixin from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.viewsets import GenericViewSet from assets.models.assets import Asset from core.decorators import log_url from core.mixins import ApiPermissionCheckMixin from correlation.models import Rule from dashboard.models import DashboardLayout from dashboard.serializers import (AssetsByIncidentsSerializer, IncidentsByCategorySerializer, TopIdsEventsSerializer, SystemInfoSerializer, SerivcesWidgetSerializer, OpenedIncidentsSerializer, IncidentsByImportanceSerializer) from dashboard.serializers import DashboardSerializer from dashboard.utils import RedisInstances from dashboard.widgets.opened_incs_widget import get_opened_incidents_count from dashboard.widgets.services_widget import get_services_list from dashboard.widgets.sys_info_widget import (get_machine_name, get_operating_system, get_cpu_model, get_uptime, get_cpu_total, get_console_version, get_disk_usage, get_mem, get_server_time, get_description) from dashboard.widgets.top_ids_widget import get_top_ids_events from dashboard.widgets.widgets import get_widget_list_from_user from incident.models import Incident, IncidentCategory from perms.models import Perm CORRELATOR_URL = getattr(settings, 'CORRELATOR_URL', 'http://localhost:9200') redis_instance = redis.StrictRedis(host=getattr(settings, 'REDIS_HOST', 'redis'), port=getattr(settings, 'REDIS_PORT', 6379), db=0) _log = logging.getLogger(__name__) @login_required @log_url def add_widget_form(request): """ API for rendering the add widget form """ user = request.user available_widgets_for_user_count = len(get_widget_list_from_user(request.user)) form = AddWidgetForm(user) ctx = {} ctx.update(csrf(request)) form = render_crispy_form(form, context=ctx) return JsonResponse({'status': 'ok', 'form_html': form, 'available_widgets_count': available_widgets_for_user_count}) class DashboardLayoutViewSet(ApiPermissionCheckMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, CreateModelMixin, GenericViewSet): """ ViewSet for handling all operations with dashboard layout """ pagination_class = None serializer_class = DashboardSerializer queryset = DashboardLayout.objects.all() console_permissions = {'default': [Perm.can_add_widgets]} # Incidendts by time widget api @api_view(['GET']) @permission_required(Perm.perm_req(Perm.can_add_widgets), raise_exception=True) def get_current_incidents_by_time_widget_data(request): response = { 'day_stats': redis_instance.get(RedisInstances.WIDGET_INCS_BY_TIME_DAY), 'week_stats': redis_instance.get(RedisInstances.WIDGET_INCS_BY_TIME_WEEK), 'month_stats': redis_instance.get(RedisInstances.WIDGET_INCS_BY_TIME_MONTH), 'year_stats': redis_instance.get(RedisInstances.WIDGET_INCS_BY_TIME_YEAR), } return Response(response, status=200) # Events by time widget api @api_view(['GET']) @permission_required(Perm.perm_req(Perm.can_add_widgets), raise_exception=True) def get_current_events_by_time_widget_data(request): response = { 'day_stats': redis_instance.get(RedisInstances.WIDGET_EVENTS_BY_TIME_DAY), 'week_stats': redis_instance.get(RedisInstances.WIDGET_EVENTS_BY_TIME_WEEK), 'month_stats': redis_instance.get(RedisInstances.WIDGET_EVENTS_BY_TIME_MONTH), 'year_stats': redis_instance.get(RedisInstances.WIDGET_EVENTS_BY_TIME_YEAR), } return Response(response, status=200) class AssetsByIncidentsViewSet(ApiPermissionCheckMixin, ListModelMixin, GenericViewSet): pagination_class = None serializer_class = AssetsByIncidentsSerializer queryset = Asset.objects.filter(incidents__isnull=False).distinct() console_permissions = [Perm.can_add_widgets] class IncidentsByCategoryViewSet(ApiPermissionCheckMixin, ListModelMixin, GenericViewSet): pagination_class = None serializer_class = IncidentsByCategorySerializer queryset = IncidentCategory.objects.filter(incident__isnull=False).distinct() console_permissions = [Perm.can_view_incidents] class TopIdsEventsWidget(ApiPermissionCheckMixin, APIView): console_permissions = [Perm.can_view_events] def get(self, request): context = { 'top_ids_events': get_top_ids_events(), } serializer = TopIdsEventsSerializer(data=context) serializer.is_valid() return Response(serializer.data) class IncidentByImportanceApi(ApiPermissionCheckMixin, APIView): """ Data source for incidents by importance widget """ console_permissions = [Perm.can_view_incidents] def filter_incidents_by_importance_levels(self, min_importance, max_importance): return Incident.objects.filter(importance__range=(min_importance, max_importance)).count() def get(self, request): _log.info("Call for incident by importance stats") context = { 'importance_none': self.filter_incidents_by_importance_levels(0, 0), 'importance_info': self.filter_incidents_by_importance_levels(1, 9), 'importance_low': self.filter_incidents_by_importance_levels(10, 39), 'importance_medium': self.filter_incidents_by_importance_levels(40, 69), 'importance_high': self.filter_incidents_by_importance_levels(70, 89), 'importance_critical': self.filter_incidents_by_importance_levels(90, 101), } serializer = IncidentsByImportanceSerializer(data=context) serializer.is_valid() return Response(serializer.data) class SysTimeWidgetApi(APIView): def get(self, request): return Response({'server_time': get_server_time()}) class SysInfoWidgetApi(ApiPermissionCheckMixin, APIView): """ Data source for system information widget """ console_permissions = [Perm.can_view_sys_info] def get(self, request): context = { 'machine_name': get_machine_name(), 'operating_system': get_operating_system(), 'cpu_model': get_cpu_model(), 'machine_uptime': get_uptime(), 'total_cpu': get_cpu_total(), 'console_version': get_console_version(), 'server_time': get_server_time(), 'description': get_description(), } context.update(get_disk_usage()) context.update(get_mem()) serializer = SystemInfoSerializer(data=context) serializer.is_valid() return Response(serializer.data) class ServicesWidgetApi(ApiPermissionCheckMixin, APIView): """ Data source for services widget """ console_permissions = [Perm.can_view_sys_info] def get(self, request): serializer = SerivcesWidgetSerializer(data=get_services_list(), many=True) serializer.is_valid() return Response(serializer.data) class OpenedIncidentsWidgetApi(ApiPermissionCheckMixin, APIView): console_permissions = [Perm.can_view_incidents] @staticmethod def get(request): context = {'inc_count': get_opened_incidents_count()} serializer = OpenedIncidentsSerializer(data=context) serializer.is_valid() return Response(serializer.data) class CorrelatorStat(ApiPermissionCheckMixin, APIView): console_permissions = [Perm.can_view_correlation_rules_list] message = 'Cannot access correlator API. Permission denied' @staticmethod def get(request): # Need to call correlator api # Then, update it's json url = CORRELATOR_URL + '/stats/' headers = {'Accept': 'application/json', 'Content-Encoding': 'utf-8'} _log.info("Call correlator stat") try: response = requests.get(url, headers=headers) except requests.ConnectionError: _log.exception("Can't get correlator status") return JsonResponse({"status": False, "error": gettext_lazy("Correlator not responding")}) correlator = response.json() # { # "aggregator": { # "events_processed": 0, # "events_aggregated": 0, # "average_iteration": { # "value": "0s" # } # }, # "correlator": { # "rule_count": 3, # "average_time": { # "value": "15.487471ms" # }, # "average_rule_time": { # "1": { # "value": "5.338945ms" # }, # "2": { # "value": "4.323614ms" # }, # "35": { # "value": "3.4368ms" # } # }, # "incident_count": 0 # } # } correlator["status"] = "true" rules = Rule.objects.filter(status=True).all() try: for key in correlator["correlator"]["average_rule_time"]: for cur in rules: if cur.pk == int(key): correlator["correlator"]["average_rule_time"][key]["title"] = cur.name break except TypeError: correlator["status"] = "false" _log.error(f"Got bad json: {correlator}") return JsonResponse(correlator)