510 lines
25 KiB
Python
510 lines
25 KiB
Python
import json
|
|
import logging
|
|
import re
|
|
from datetime import datetime
|
|
from distutils.util import strtobool
|
|
from ipaddress import ip_address
|
|
|
|
from django.conf import settings
|
|
from django.contrib.auth.decorators import login_required, permission_required
|
|
from django.db.models import Q
|
|
from django.http import JsonResponse, HttpResponse
|
|
from django.template.context_processors import csrf
|
|
from elasticsearch import Elasticsearch
|
|
from rest_framework import status
|
|
from rest_framework.decorators import action, api_view
|
|
from rest_framework.mixins import ListModelMixin, UpdateModelMixin, RetrieveModelMixin
|
|
from rest_framework.viewsets import GenericViewSet
|
|
|
|
from assets.models.assets import Asset, AssetListGroup
|
|
from console.conslog import object_create_log
|
|
from console.models import Connection
|
|
from core.decorators import log_url
|
|
from core.mixins import ApiPermissionCheckMixin
|
|
from core.utils import dtnow
|
|
from networkmap.services import parse_endpoint_celery_done_events
|
|
from events.constants import ELK_HOST, ELK_PORT, ELK_LOGIN, ELK_PASS
|
|
from incident.models import Incident
|
|
from networkmap.models import NetworkMap, NetworkMapBackgroundImage
|
|
from networkmap.serializers import (UserMapSerializer, NetmapElementsSerializer, NetmapGroupSerializer,
|
|
AssetDangerSerializer, UserMapNamesSerializer, AutoNetmapElementsSerializer,
|
|
AutoNetmapConnectionsSerializer, NetworkMapBackgroundImagesSerializer)
|
|
from perms.models import Perm
|
|
|
|
_log = logging.getLogger(__name__)
|
|
|
|
ELK_SEARCH_INDEX = getattr(settings, 'ELK_AGGREGATED_INDEX', 'aggregated-*')
|
|
# TODO: rename "Firerwall" to "Firewall" when vector variable will be fixed
|
|
# Yes its a mistake and yes it is correct for now
|
|
ELK_FIREWALL_DEVICE_PRODUCT = getattr(settings, 'ELK_FIREWALL_PRODUCT_NAME', 'Industrial Firerwall')
|
|
ELK_ENDPOINT_DEVICE_PRODUCT = getattr(settings, 'ELK_ENDPOINT_PRODUCT_NAME', 'Industrial Endpoint')
|
|
|
|
DANGER_STATUSES = [
|
|
Incident.Status.NOT_ASSIGNED,
|
|
Incident.Status.ASSIGNED,
|
|
Incident.Status.DELAYED,
|
|
Incident.Status.FALSE_ALARM,
|
|
]
|
|
|
|
|
|
class UserMapViewSet(ApiPermissionCheckMixin,
|
|
ListModelMixin,
|
|
UpdateModelMixin,
|
|
RetrieveModelMixin,
|
|
GenericViewSet):
|
|
console_permissions = [Perm.can_view_network]
|
|
message = 'Cannot access user network map API. Permission denied'
|
|
|
|
serializer_class = UserMapSerializer
|
|
queryset = NetworkMap.objects.all()
|
|
|
|
|
|
class NetworkMapBackgroundImagesViewSet(ApiPermissionCheckMixin,
|
|
ListModelMixin,
|
|
UpdateModelMixin,
|
|
RetrieveModelMixin,
|
|
GenericViewSet):
|
|
""" ViewSet for handling the networkmap background image data manipulation """
|
|
console_permissions = [Perm.can_view_network]
|
|
message = 'Cannot access user network map API. Permission denied'
|
|
serializer_class = NetworkMapBackgroundImagesSerializer
|
|
|
|
def get_queryset(self):
|
|
""" This method override is used for including linked to background image network map data """
|
|
network_map_id = self.request.query_params.get('current_map_id')
|
|
queryset = NetworkMapBackgroundImage.objects.filter(network_map=network_map_id)
|
|
return queryset
|
|
|
|
def try_to_get_background_image(self, map_pk, image_data, full_image_data=True):
|
|
""" Helper method for trying to get an image from DB
|
|
:param map_pk: linked for current background image network map pk
|
|
:param image_data: image data, which is needed for request
|
|
:param full_image_data: flag to show if image data that are being provided for request is:
|
|
if True - image data provided in cytoscape module for handling background images format - support images
|
|
if False - provided data will not be checked in this helper function, thus needed to be validated in further
|
|
actions
|
|
:return: Two variables:
|
|
1. True if image exists ind DB, False otherwise
|
|
2. If first variable is True - requested image instance,
|
|
otherwise - JsonResponse with error status and message
|
|
"""
|
|
if map_pk is None or image_data is None:
|
|
return False, JsonResponse({'status': 'err', 'error_message': 'Some mandatory arguments are missing'})
|
|
# Check if provided image data is valid
|
|
if full_image_data:
|
|
try:
|
|
background_image_data = json.loads(image_data)
|
|
except json.JSONDecodeError:
|
|
_log.error(f"Failed to parse background image data for network map {map_pk}")
|
|
return False, JsonResponse({'status': 'err', 'error_message': 'Image data is not valid'})
|
|
else:
|
|
background_image_data = image_data
|
|
# Get requested image
|
|
try:
|
|
if full_image_data:
|
|
target_image = NetworkMapBackgroundImage.objects.get(network_map=map_pk,
|
|
name=background_image_data['name'])
|
|
else:
|
|
target_image = NetworkMapBackgroundImage.objects.get(pk=background_image_data)
|
|
except NetworkMapBackgroundImage.DoesNotExist:
|
|
return False, JsonResponse({'status': 'err', 'error_message': 'Image does not exists in database'})
|
|
|
|
return True, target_image
|
|
|
|
@action(detail=False, methods=["POST"], name="update_image_data")
|
|
def update_image_data(self, request):
|
|
""" Method for handling <router-url>-update-image-data request for updating background image data fields value
|
|
in Database. Request always should contain 'current_map_id' and 'image_data' fields.
|
|
:param request: request instance that must contains 'current_map_id' and 'image_data' fields. Image_data should
|
|
be in support images format (cytoscape framework that is used for managing network map background images)
|
|
:return: JsonResponse with 'ok' status if everything works as expected, or with error message and 'err' status
|
|
otherwise
|
|
"""
|
|
# Get necessary arguments for updating image data
|
|
try:
|
|
network_map_id = int(self.request.POST.get('current_map_id'))
|
|
background_image_data = self.request.POST.get('image_data')
|
|
except TypeError:
|
|
return JsonResponse(
|
|
{'status': 'err', 'error_message': 'Necessary data for request not provided or corrupted'})
|
|
success_get_status, image_or_error = self.try_to_get_background_image(network_map_id, background_image_data)
|
|
if success_get_status:
|
|
parsed_image_data = json.loads(background_image_data)
|
|
image_or_error.bounds = parsed_image_data['bounds']
|
|
image_or_error.locked = parsed_image_data['locked']
|
|
image_or_error.visible = parsed_image_data['visible']
|
|
image_or_error.save()
|
|
return JsonResponse({'status': 'ok'})
|
|
else:
|
|
return image_or_error
|
|
|
|
@action(detail=False, methods=["POST"], name="delete_background_image")
|
|
def delete_background_image(self, request):
|
|
""" Method for handling <router-url>-delete-background-image request for deleting existing background image
|
|
for current network map. Request always should contain 'current_map_id' and 'image_data' fields.
|
|
:param request: request instance that must contains 'current_map_id' and 'image_data' fields. Image_data must
|
|
contain background image ID
|
|
:return: JsonResponse with 'ok' status if everything works as expected, or with error message and 'err' status
|
|
otherwise
|
|
"""
|
|
# Get necessary arguments for updating image data
|
|
try:
|
|
network_map_id = int(self.request.POST.get('current_map_id'))
|
|
background_image_data = int(self.request.POST.get('image_data'))
|
|
except TypeError:
|
|
return JsonResponse(
|
|
{'status': 'err', 'error_message': 'Necessary data for request not provided or corrupted'})
|
|
success_get_status, image_or_error = self.try_to_get_background_image(network_map_id,
|
|
background_image_data,
|
|
False)
|
|
if success_get_status:
|
|
image_or_error.delete()
|
|
return JsonResponse({'status': 'ok'})
|
|
else:
|
|
return image_or_error
|
|
|
|
|
|
class NetmapElementsViewSet(ApiPermissionCheckMixin, ListModelMixin, GenericViewSet):
|
|
console_permissions = [Perm.can_view_network]
|
|
pagination_class = None
|
|
serializer_class = NetmapElementsSerializer
|
|
queryset = Asset.objects.all()
|
|
|
|
|
|
class AutoNetmapElementsViewSet(ApiPermissionCheckMixin, ListModelMixin, GenericViewSet):
|
|
pagination_class = None
|
|
serializer_class = AutoNetmapElementsSerializer
|
|
console_permissions = [Perm.can_view_network]
|
|
queryset = Asset.objects.all()
|
|
|
|
|
|
class AutoNetmapConnectionsViewSet(ApiPermissionCheckMixin, ListModelMixin, GenericViewSet):
|
|
pagination_class = None
|
|
serializer_class = AutoNetmapConnectionsSerializer
|
|
console_permissions = [Perm.can_view_network]
|
|
queryset = Connection.objects.all()
|
|
|
|
|
|
class NetmapGroupsViewSet(ApiPermissionCheckMixin, ListModelMixin, GenericViewSet):
|
|
console_permissions = [Perm.can_view_network]
|
|
pagination_class = None
|
|
serializer_class = NetmapGroupSerializer
|
|
queryset = AssetListGroup.objects.filter(asset__isnull=False).distinct()
|
|
|
|
|
|
class AssetDangerViewSet(ApiPermissionCheckMixin, ListModelMixin, GenericViewSet):
|
|
console_permissions = [Perm.can_view_network]
|
|
pagination_class = None
|
|
serializer_class = AssetDangerSerializer
|
|
|
|
def get_queryset(self):
|
|
queryset = Asset.objects.filter(incidents__status__in=DANGER_STATUSES).distinct()
|
|
return queryset
|
|
|
|
|
|
# def add_new_user_map(request):
|
|
# if request.method == 'POST':
|
|
# form = AddNewUserMapForm(request.POST, request.FILES, user=request.user)
|
|
# if form.is_valid():
|
|
# new_map = form.save()
|
|
# serializer = UserMapSerializer(new_map)
|
|
# return JsonResponse(serializer.data, safe=False)
|
|
# else:
|
|
# form = AddNewUserMapForm()
|
|
# ctx = {}
|
|
# ctx.update(csrf(request))
|
|
# form = render_crispy_form(form, context=ctx)
|
|
# return JsonResponse({'status': 'err', 'form_html': form})
|
|
|
|
|
|
# def add_new_background_image(request, current_netmap_id):
|
|
# """ API for managing the new network map background image form
|
|
# :param request: request instance
|
|
# :param current_netmap_id: current network map id, on which is performing the background image addition
|
|
# :return: JsonResponse with 'ok' status if everything performed as expected and new background image is being added,
|
|
# JsonResponse with 'err' status and HTML rendered form with errors otherwise
|
|
# """
|
|
# try:
|
|
# netmap = NetworkMap.objects.get(pk=current_netmap_id)
|
|
# except NetworkMap.DoesNotExist:
|
|
# return JsonResponse({'status': 'err', 'error_message': 'Unknown networkmap selected'})
|
|
# if request.method == 'POST':
|
|
# form = AddNewBackgroundImageForm(request.POST, request.FILES,
|
|
# networkmap=netmap)
|
|
# if form.is_valid():
|
|
# form.save()
|
|
# return JsonResponse({'status': 'ok'})
|
|
# else:
|
|
# _log.error(form.errors)
|
|
# else:
|
|
# form = AddNewBackgroundImageForm()
|
|
# ctx = {}
|
|
# ctx.update(csrf(request))
|
|
# form = render_crispy_form(form, context=ctx)
|
|
# return JsonResponse({'status': 'err', 'form_html': form})
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_required(Perm.perm_req(Perm.can_view_network), raise_exception=True)
|
|
def get_user_maps(request):
|
|
""" API for getting network maps for specific user
|
|
:param request: request object
|
|
:return: list of group names for current user
|
|
"""
|
|
all_maps = NetworkMap.objects.filter(Q(user=request.user) | Q(shared_map=True))
|
|
serializer = UserMapNamesSerializer(all_maps, many=True)
|
|
return JsonResponse(serializer.data, safe=False)
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_required(Perm.perm_req(Perm.can_view_network), raise_exception=True)
|
|
def get_map_background_image(request, background_pk):
|
|
try:
|
|
bimage = NetworkMapBackgroundImage.objects.get(pk=background_pk)
|
|
except NetworkMapBackgroundImage.DoesNotExist:
|
|
return JsonResponse({'status': 'err', 'error_message': 'Background image does not exists'})
|
|
if not bimage.url:
|
|
return JsonResponse({'status': 'err', 'error_message': 'No link for selected background image'})
|
|
else:
|
|
return HttpResponse(bimage.url, content_type='image/png')
|
|
|
|
|
|
@api_view(['DELETE'])
|
|
@permission_required(Perm.perm_req(Perm.can_view_network), raise_exception=True)
|
|
def delete_user_map(request, pk):
|
|
try:
|
|
target_netmap = NetworkMap.objects.get(pk=pk)
|
|
except NetworkMap.DoesNotExist:
|
|
return JsonResponse({'message': 'The networkmap does not exist'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
target_netmap.delete()
|
|
return JsonResponse({'message': 'Networkmap was deleted successfully!'}, status=status.HTTP_200_OK)
|
|
|
|
|
|
def auto_netmap_assets_filter(form_assets_data, include_neighbours, assets_queryset=None, connections_queryset=None):
|
|
""" Asset filtering function for auto network map. Function returns list of two querysets [Filtered_assets, Filtered_connections]
|
|
which can be used in further filtering or send to frontend for rendering the map
|
|
:param form_assets_data: data, provided by user
|
|
:param assets_queryset: assets queryset from previous filters, if exists
|
|
:param connections_queryset: connection queryset from previous filters, if exists
|
|
:param include_neighbours: argument to tell if assets, which have connections with selected assets, should be displayed
|
|
:return: list with assets and connections filtered querysets
|
|
"""
|
|
chosen_assets_queryset = Asset.objects.filter(pk__in=form_assets_data)
|
|
if not connections_queryset:
|
|
connections_queryset = Connection.objects.all()
|
|
# Get connections for selected assets
|
|
edge_assets = []
|
|
if include_neighbours:
|
|
filtered_connections_queryset = connections_queryset.filter(
|
|
Q(src_asset__in=chosen_assets_queryset) | Q(dst_asset__in=chosen_assets_queryset))
|
|
for asset in chosen_assets_queryset:
|
|
src_connections = filtered_connections_queryset.filter(src_asset=asset)
|
|
dst_connections = filtered_connections_queryset.filter(dst_asset=asset)
|
|
for connection in src_connections:
|
|
edge_assets.append(connection.dst_asset.pk)
|
|
for connection in dst_connections:
|
|
edge_assets.append(connection.src_asset.pk)
|
|
else:
|
|
filtered_connections_queryset = connections_queryset.filter(
|
|
Q(src_asset__in=chosen_assets_queryset) & Q(dst_asset__in=chosen_assets_queryset))
|
|
edged_assets = Asset.objects.filter(pk__in=edge_assets)
|
|
filtered_assets_queryset = chosen_assets_queryset.union(edged_assets)
|
|
return [filtered_assets_queryset, filtered_connections_queryset]
|
|
|
|
|
|
def auto_netmap_time_filter(form_time_data, connections_queryset='no_data'):
|
|
""" Time filtering function for auto network map. Function returns list of two querysets [Filtered_assets, Filtered_connections]
|
|
which can be used in further filtering or send to frontend for rendering the map
|
|
:param form_time_data: data, provided by user
|
|
:param connections_queryset: connection queryset from previous filters, if exists
|
|
:return: list with assets and connections filtered querysets
|
|
"""
|
|
splitted_range = form_time_data.split(' - ')
|
|
formatted_range = []
|
|
for timestamp in splitted_range:
|
|
if '.' in timestamp:
|
|
formatted_range.append(datetime.strptime(timestamp, '%d.%m.%Y %H:%M:%S'))
|
|
else:
|
|
formatted_range.append(datetime.fromisoformat(timestamp))
|
|
|
|
if connections_queryset == 'no_data':
|
|
connections_queryset = Connection.objects.all()
|
|
filtered_connections = connections_queryset.filter(updated__range=formatted_range)
|
|
assets_set = []
|
|
for connection in filtered_connections:
|
|
assets_set.append(connection.src_asset.pk)
|
|
assets_set.append(connection.dst_asset.pk)
|
|
filtered_assets = Asset.objects.filter(pk__in=list(assets_set))
|
|
return [filtered_assets, filtered_connections]
|
|
|
|
|
|
def auto_netmap_protocol_filter(form_protocol_data, connections_queryset='no_data'):
|
|
""" Protocol filtering function for auto network map. Function returns list of two querysets [Filtered_assets, Filtered_connections]
|
|
which can be used in further filtering or send to frontend for rendering the map
|
|
:param form_time_data: data, provided by user
|
|
:param connections_queryset: connection queryset from previous filters, if exists
|
|
:return: list with assets and connections filtered querysets
|
|
"""
|
|
if connections_queryset == 'no_data':
|
|
connections_queryset = Connection.objects.all()
|
|
|
|
pattern = re.compile(r'^\w+$') # allow any word character (equivalent to [a-zA-Z0-9_])
|
|
form_protocol_data = [protocol for protocol in form_protocol_data if pattern.match(protocol)]
|
|
|
|
filtered_connections = connections_queryset.filter(connection_protocol__in=form_protocol_data)
|
|
assets_set = []
|
|
for connection in filtered_connections:
|
|
assets_set.append(connection.src_asset.pk)
|
|
assets_set.append(connection.dst_asset.pk)
|
|
filtered_assets = Asset.objects.filter(pk__in=list(assets_set))
|
|
return [filtered_assets, filtered_connections]
|
|
|
|
|
|
def apply_auto_netmap_filters(parsed_filters):
|
|
# Next two 'if's are made for parsing JSON converting issues from ajax
|
|
if 'assets_filter[assets][]' in parsed_filters:
|
|
parsed_filters['assets_filter'] = {'assets': parsed_filters.pop('assets_filter[assets][]'),
|
|
'include_neighbours': bool(
|
|
strtobool(parsed_filters.pop('assets_filter[include_neighbours]')[0]))}
|
|
if 'protocol_filter[]' in parsed_filters:
|
|
parsed_filters['protocol_filter'] = parsed_filters.pop('protocol_filter[]')
|
|
filters_querydicts = [Asset.objects.all(), Connection.objects.all()]
|
|
if 'assets_filter' in parsed_filters:
|
|
chosen_assets = parsed_filters.get('assets_filter').get('assets')
|
|
include_neighbours = parsed_filters.get('assets_filter').get('include_neighbours')
|
|
filters_querydicts = auto_netmap_assets_filter(chosen_assets, include_neighbours)
|
|
if 'time_filter' in parsed_filters:
|
|
filters_querydicts = auto_netmap_time_filter(parsed_filters.get('time_filter'), filters_querydicts[1])
|
|
if 'protocol_filter' in parsed_filters:
|
|
filters_querydicts = auto_netmap_protocol_filter(parsed_filters.get('protocol_filter'), filters_querydicts[1])
|
|
serialized_assets = AutoNetmapElementsSerializer(filters_querydicts[0], many=True)
|
|
serialized_connections = AutoNetmapConnectionsSerializer(filters_querydicts[1], many=True)
|
|
context = {
|
|
'edges': serialized_connections.data,
|
|
'nodes': serialized_assets.data,
|
|
}
|
|
return context
|
|
|
|
|
|
# @log_url
|
|
# @login_required
|
|
# @permission_required(Perm.perm_req(Perm.can_view_network), raise_exception=True)
|
|
# def handle_filter_forms(request, form_type):
|
|
# if form_type == 'assets':
|
|
# filter_form = FilterByAssetForm
|
|
# elif form_type == 'time':
|
|
# filter_form = FilterByTimeForm
|
|
# elif form_type == 'protocol':
|
|
# filter_form = FilterByProtocolForm
|
|
# elif form_type == 'reset':
|
|
# return JsonResponse(apply_auto_netmap_filters(request.GET.copy()), safe=False)
|
|
# else:
|
|
# _log.error(f"Unknown filter type for auto network map: {form_type}")
|
|
#
|
|
# if request.method == 'POST':
|
|
# form = filter_form(request.POST)
|
|
# if form.is_valid():
|
|
# current_auto_netmap_filters = form.cleaned_data['current_filters']
|
|
# context = apply_auto_netmap_filters(current_auto_netmap_filters)
|
|
# return JsonResponse(context, safe=False)
|
|
# else:
|
|
# return JsonResponse({'status': 'err', 'error_message': 'no_entries_selected'})
|
|
# else:
|
|
# form = filter_form()
|
|
# ctx = {}
|
|
# ctx.update(csrf(request))
|
|
# form = render_crispy_form(form, context=ctx)
|
|
# return JsonResponse({'status': 'err', 'form_html': form})
|
|
|
|
|
|
def parse_firewall_celery_done_events(hit):
|
|
""" Algorithm for forming connections data for the auto network map """
|
|
if hit['_source']['source_ip'] and hit['_source']['destination_ip']:
|
|
source_ip = hit['_source']['source_ip']
|
|
destination_ip = hit['_source']['destination_ip']
|
|
log_type = hit['_source']['type']
|
|
connection_protocol = hit['_source']['event_protocol']
|
|
|
|
try:
|
|
ip_address(source_ip)
|
|
ip_address(destination_ip)
|
|
except ValueError:
|
|
_log.critical(
|
|
f"Error incorrect ip format [event id: {hit.get('_id')} by source_ip {source_ip} \
|
|
or dest_ip {destination_ip}]")
|
|
return
|
|
|
|
# Check if Assets with corresponding IP's presented in database. If not - add them
|
|
if not Asset.objects.filter(ip=source_ip, sensor=log_type).exists():
|
|
source_asset = Asset.objects.create(name=source_ip, ip=source_ip, sensor=log_type)
|
|
object_create_log(source_asset.name, Asset.Meta.__name__)
|
|
if not Asset.objects.filter(ip=destination_ip, sensor=log_type).exists():
|
|
dest_asset = Asset.objects.create(name=destination_ip, ip=destination_ip, sensor=log_type)
|
|
object_create_log(dest_asset.name, Asset.Meta.__name__)
|
|
# ip_list = [source_ip, destination_ip]
|
|
# # Checking if there is a connection in db with the same IP's as in the event
|
|
# if Connection.objects.filter(src_asset__ip__in=ip_list, dst_asset__ip__in=ip_list).exists():
|
|
# # If there is a match during filtering process - update field Connection.updated
|
|
# try:
|
|
# connection_from_db = Connection.objects.get(src_asset__ip=source_ip,
|
|
# src_asset__sensor=log_type,
|
|
# dst_asset__ip=destination_ip,
|
|
# dst_asset__sensor=log_type)
|
|
# # Add updated connection to the network map data
|
|
# connection_from_db.updated = dtnow()
|
|
# connection_from_db.save()
|
|
# except Connection.DoesNotExist:
|
|
# connection_from_db = Connection.objects.get(dst_asset__ip=source_ip,
|
|
# dst_asset__sensor=log_type,
|
|
# src_asset__ip=destination_ip,
|
|
# src_asset__sensor=log_type)
|
|
# # Add updated connection to the network map data
|
|
# connection_from_db.updated = dtnow()
|
|
# connection_from_db.save()
|
|
# else:
|
|
# # Creating a new connection if there is no in DB
|
|
# received_protocol = connection_protocol.upper()
|
|
# if received_protocol in Connection.ProtocolType:
|
|
# Connection.objects.create(src_asset=Asset.objects.get(ip=source_ip, sensor=log_type),
|
|
# dst_asset=Asset.objects.get(ip=destination_ip, sensor=log_type),
|
|
# connection_protocol=received_protocol)
|
|
# else:
|
|
# Connection.objects.create(src_asset=Asset.objects.get(ip=source_ip, sensor=log_type),
|
|
# dst_asset=Asset.objects.get(ip=destination_ip, sensor=log_type))
|
|
|
|
|
|
# TODO: rename to summary celery_done corresponding name
|
|
def update_connections_model_data():
|
|
""" Algorithm for forming connections data for the auto network map """
|
|
# Receiving data from Elasticsearch
|
|
es = Elasticsearch([{'host': ELK_HOST, 'port': ELK_PORT}], http_auth=(ELK_LOGIN, ELK_PASS))
|
|
search_body = {
|
|
"query": {
|
|
"match": {
|
|
"celery_done": "false"
|
|
}
|
|
}
|
|
}
|
|
es_search = es.search(index=ELK_SEARCH_INDEX, body=search_body, filter_path=['hits.hits._*'], size=1000)
|
|
if 'hits' in es_search:
|
|
for hit in es_search['hits']['hits']:
|
|
if hit['_source']['device_product'] == ELK_ENDPOINT_DEVICE_PRODUCT:
|
|
parse_endpoint_celery_done_events(hit)
|
|
elif hit['_source']['device_product'] == ELK_FIREWALL_DEVICE_PRODUCT:
|
|
parse_firewall_celery_done_events(hit)
|
|
# Updating 'celery_done field
|
|
hit_id = hit.get('_id')
|
|
update_body = {
|
|
"script": {
|
|
"source": "ctx._source.celery_done=true",
|
|
"lang": "painless"
|
|
},
|
|
"query": {
|
|
"match": {
|
|
"_id": hit_id
|
|
}
|
|
}
|
|
}
|
|
# Updating ELK event data
|
|
es.update_by_query(index=ELK_SEARCH_INDEX, body=update_body)
|