266 lines
10 KiB
Python
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)
|