| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- # IRIS Source Code
- # Copyright (C) 2024 - DFIR-IRIS
- # contact@dfir-iris.org
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU Lesser General Public
- # License as published by the Free Software Foundation; either
- # version 3 of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # Lesser General Public License for more details.
- #
- # You should have received a copy of the GNU Lesser General Public License
- # along with this program; if not, write to the Free Software Foundation,
- # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- import itertools
- from datetime import datetime
- from flask_login import current_user
- from flask import Blueprint
- from app.datamgmt.case.case_events_db import get_case_events_assets_graph
- from app.datamgmt.case.case_events_db import get_case_events_ioc_graph
- from app.models.authorization import CaseAccessLevel
- from app.blueprints.access_controls import ac_requires_case_identifier
- from app.blueprints.access_controls import ac_api_requires
- from app.blueprints.responses import response_success
- case_graph_rest_blueprint = Blueprint('case_graph_rest', __name__)
- @case_graph_rest_blueprint.route('/case/graph/getdata', methods=['GET'])
- @ac_requires_case_identifier(CaseAccessLevel.read_only, CaseAccessLevel.full_access)
- @ac_api_requires()
- def case_graph_get_data(caseid):
- events = get_case_events_assets_graph(caseid)
- events.extend(get_case_events_ioc_graph(caseid))
- nodes = []
- edges = []
- dates = {
- "human": [],
- "machine": []
- }
- tmp = {}
- for event in events:
- if hasattr(event, 'asset_compromise_status_id'):
- if event.asset_compromise_status_id == 1:
- img = event.asset_icon_compromised
- else:
- img = event.asset_icon_not_compromised
- if event.asset_ip:
- title = "{} -{}".format(event.asset_ip, event.asset_description)
- else:
- title = "{}".format(event.asset_description)
- label = event.asset_name
- idx = f'a{event.asset_id}'
- node_type = 'asset'
- else:
- img = 'virus-covid-solid.png'
- label = event.ioc_value
- title = event.ioc_description
- idx = f'b{event.ioc_id}'
- node_type = 'ioc'
- try:
- date = "{}-{}-{}".format(event.event_date.day, event.event_date.month, event.event_date.year)
- except:
- date = '15-05-2021'
- if date not in dates:
- dates['human'].append(date)
- dates['machine'].append(datetime.timestamp(event.event_date))
- new_node = {
- 'id': idx,
- 'label': label,
- 'image': '/static/assets/img/graph/' + img,
- 'shape': 'image',
- 'title': title,
- 'value': 1
- }
- if current_user.in_dark_mode:
- new_node['font'] = "12px verdana white"
- if not any(node['id'] == idx for node in nodes):
- nodes.append(new_node)
- ak = {
- 'node_id': idx,
- 'node_title': "{} - {}".format(event.event_date, event.event_title),
- 'node_name': label,
- 'node_type': node_type
- }
- if tmp.get(event.event_id):
- tmp[event.event_id]['list'].append(ak)
- else:
- tmp[event.event_id] = {
- 'master_node': [],
- 'list': [ak]
- }
- for event_id in tmp:
- for subset in itertools.combinations(tmp[event_id]['list'], 2):
- if subset[0]['node_type'] == 'ioc' and subset[1]['node_type'] == 'ioc' and len(tmp[event_id]['list']) != 2:
- continue
- edge = {
- 'from': subset[0]['node_id'],
- 'to': subset[1]['node_id'],
- 'title': subset[0]['node_title'],
- 'dashes': subset[0]['node_type'] == 'ioc' or subset[1]['node_type'] == 'ioc'
- }
- edges.append(edge)
- resp = {
- 'nodes': nodes,
- 'edges': edges,
- 'dates': dates
- }
- return response_success("", data=resp)
|