old_console/dashboard/api.py
2024-11-02 14:12:45 +03:00

266 lines
10 KiB
Python

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)