Some checks failed
Deployment Verification / deploy-and-test (push) Failing after 29s
403 lines
10 KiB
Python
403 lines
10 KiB
Python
#!/usr/bin/env python3
|
|
#
|
|
# IRIS Source Code
|
|
# Copyright (C) 2021 - Airbus CyberSecurity (SAS)
|
|
# ir@cyberactionlab.net
|
|
#
|
|
# 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.
|
|
from flask_login import current_user
|
|
from sqlalchemy import and_
|
|
|
|
from app import db
|
|
from app.datamgmt.states import update_timeline_state
|
|
from app.models import AssetsType
|
|
from app.models import CaseAssets
|
|
from app.models import CaseEventCategory
|
|
from app.models import CaseEventsAssets
|
|
from app.models import CaseEventsIoc
|
|
from app.models import CasesEvent
|
|
from app.models import Comments
|
|
from app.models import EventCategory
|
|
from app.models import EventComments
|
|
from app.models import Ioc
|
|
from app.models import IocAssetLink
|
|
from app.models import IocLink
|
|
from app.models import IocType
|
|
from app.models.authorization import User
|
|
|
|
|
|
def get_case_events_assets_graph(caseid):
|
|
events = CaseEventsAssets.query.with_entities(
|
|
CaseEventsAssets.event_id,
|
|
CasesEvent.event_uuid,
|
|
CasesEvent.event_title,
|
|
CaseAssets.asset_name,
|
|
CaseAssets.asset_id,
|
|
AssetsType.asset_name.label('type_name'),
|
|
AssetsType.asset_icon_not_compromised,
|
|
AssetsType.asset_icon_compromised,
|
|
CasesEvent.event_color,
|
|
CaseAssets.asset_compromise_status_id,
|
|
CaseAssets.asset_description,
|
|
CaseAssets.asset_ip,
|
|
CasesEvent.event_date,
|
|
CasesEvent.event_tags
|
|
).filter(and_(
|
|
CaseEventsAssets.case_id == caseid,
|
|
CasesEvent.event_in_graph == True
|
|
)).join(
|
|
CaseEventsAssets.event,
|
|
CaseEventsAssets.asset,
|
|
CaseAssets.asset_type,
|
|
).all()
|
|
|
|
return events
|
|
|
|
|
|
def get_case_events_ioc_graph(caseid):
|
|
events = CaseEventsIoc.query.with_entities(
|
|
CaseEventsIoc.event_id,
|
|
CasesEvent.event_uuid,
|
|
CasesEvent.event_title,
|
|
CasesEvent.event_date,
|
|
Ioc.ioc_id,
|
|
Ioc.ioc_value,
|
|
Ioc.ioc_description,
|
|
IocType.type_name
|
|
).filter(and_(
|
|
CaseEventsIoc.case_id == caseid,
|
|
CasesEvent.event_in_graph == True
|
|
)).join(
|
|
CaseEventsIoc.event,
|
|
CaseEventsIoc.ioc,
|
|
Ioc.ioc_type,
|
|
).all()
|
|
|
|
return events
|
|
|
|
|
|
def get_events_categories():
|
|
return EventCategory.query.with_entities(
|
|
EventCategory.id,
|
|
EventCategory.name
|
|
).all()
|
|
|
|
|
|
def get_default_cat():
|
|
cat = EventCategory.query.with_entities(
|
|
EventCategory.id,
|
|
EventCategory.name
|
|
).filter(
|
|
EventCategory.name == "Unspecified"
|
|
).first()
|
|
|
|
return [cat._asdict()]
|
|
|
|
|
|
def get_case_event(event_id, caseid):
|
|
return CasesEvent.query.filter(
|
|
CasesEvent.event_id == event_id,
|
|
CasesEvent.case_id == caseid
|
|
).first()
|
|
|
|
|
|
def get_case_event_comments(event_id, caseid):
|
|
return Comments.query.filter(
|
|
EventComments.comment_event_id == event_id
|
|
).join(
|
|
EventComments,
|
|
Comments.comment_id == EventComments.comment_id
|
|
).order_by(
|
|
Comments.comment_date.asc()
|
|
).all()
|
|
|
|
|
|
def get_case_events_comments_count(events_list):
|
|
return EventComments.query.filter(
|
|
EventComments.comment_event_id.in_(events_list)
|
|
).with_entities(
|
|
EventComments.comment_event_id,
|
|
EventComments.comment_id
|
|
).group_by(
|
|
EventComments.comment_event_id,
|
|
EventComments.comment_id
|
|
).all()
|
|
|
|
|
|
def get_case_event_comment(event_id, comment_id, caseid):
|
|
return EventComments.query.filter(
|
|
EventComments.comment_event_id == event_id,
|
|
EventComments.comment_id == comment_id
|
|
).with_entities(
|
|
Comments.comment_id,
|
|
Comments.comment_text,
|
|
Comments.comment_date,
|
|
Comments.comment_update_date,
|
|
Comments.comment_uuid,
|
|
User.name,
|
|
User.user
|
|
).join(
|
|
EventComments.comment,
|
|
Comments.user
|
|
).first()
|
|
|
|
|
|
def delete_event_comment(event_id, comment_id):
|
|
comment = Comments.query.filter(
|
|
Comments.comment_id == comment_id,
|
|
Comments.comment_user_id == current_user.id
|
|
).first()
|
|
if not comment:
|
|
return False, "You are not allowed to delete this comment"
|
|
|
|
EventComments.query.filter(
|
|
EventComments.comment_event_id == event_id,
|
|
EventComments.comment_id == comment_id
|
|
).delete()
|
|
|
|
db.session.delete(comment)
|
|
db.session.commit()
|
|
|
|
return True, "Comment deleted"
|
|
|
|
|
|
def add_comment_to_event(event_id, comment_id):
|
|
ec = EventComments()
|
|
ec.comment_event_id = event_id
|
|
ec.comment_id = comment_id
|
|
|
|
db.session.add(ec)
|
|
db.session.commit()
|
|
|
|
|
|
def delete_event_category(event_id):
|
|
CaseEventCategory.query.filter(
|
|
CaseEventCategory.event_id == event_id
|
|
).delete()
|
|
|
|
|
|
def get_event_category(event_id):
|
|
cec = CaseEventCategory.query.filter(
|
|
CaseEventCategory.event_id == event_id
|
|
).first()
|
|
return cec
|
|
|
|
|
|
def save_event_category(event_id, category_id):
|
|
CaseEventCategory.query.filter(
|
|
CaseEventCategory.event_id == event_id
|
|
).delete()
|
|
|
|
cec = CaseEventCategory()
|
|
cec.event_id = event_id
|
|
cec.category_id = category_id
|
|
|
|
db.session.add(cec)
|
|
db.session.commit()
|
|
|
|
|
|
def get_event_assets_ids(event_id, caseid):
|
|
assets_list = CaseEventsAssets.query.with_entities(
|
|
CaseEventsAssets.asset_id
|
|
).filter(
|
|
CaseEventsAssets.event_id == event_id,
|
|
CaseEventsAssets.case_id == caseid
|
|
).all()
|
|
|
|
return [x[0] for x in assets_list]
|
|
|
|
|
|
def get_event_iocs_ids(event_id, caseid):
|
|
iocs_list = CaseEventsIoc.query.with_entities(
|
|
CaseEventsIoc.ioc_id
|
|
).filter(
|
|
CaseEventsIoc.event_id == event_id,
|
|
CaseEventsIoc.case_id == caseid
|
|
).all()
|
|
|
|
return [x[0] for x in iocs_list]
|
|
|
|
|
|
def update_event_assets(event_id, caseid, assets_list, iocs_list, sync_iocs_assets):
|
|
|
|
CaseEventsAssets.query.filter(
|
|
CaseEventsAssets.event_id == event_id,
|
|
CaseEventsAssets.case_id == caseid
|
|
).delete()
|
|
|
|
valid_assets = CaseAssets.query.with_entities(
|
|
CaseAssets.asset_id
|
|
).filter(
|
|
CaseAssets.asset_id.in_(assets_list),
|
|
CaseAssets.case_id == caseid
|
|
).all()
|
|
|
|
for asset in valid_assets:
|
|
try:
|
|
|
|
cea = CaseEventsAssets()
|
|
cea.asset_id = int(asset.asset_id)
|
|
cea.event_id = event_id
|
|
cea.case_id = caseid
|
|
|
|
db.session.add(cea)
|
|
|
|
if sync_iocs_assets:
|
|
for ioc in iocs_list:
|
|
link = IocAssetLink.query.filter(
|
|
IocAssetLink.asset_id == int(asset.asset_id),
|
|
IocAssetLink.ioc_id == int(ioc)
|
|
).first()
|
|
|
|
if link is None:
|
|
|
|
ial = IocAssetLink()
|
|
ial.asset_id = int(asset.asset_id)
|
|
ial.ioc_id = int(ioc)
|
|
|
|
db.session.add(ial)
|
|
|
|
except Exception as e:
|
|
return False, str(e)
|
|
|
|
db.session.commit()
|
|
return True, ''
|
|
|
|
|
|
def update_event_iocs(event_id, caseid, iocs_list):
|
|
|
|
CaseEventsIoc.query.filter(
|
|
CaseEventsIoc.event_id == event_id,
|
|
CaseEventsIoc.case_id == caseid
|
|
).delete()
|
|
|
|
valid_iocs = IocLink.query.with_entities(
|
|
IocLink.ioc_id
|
|
).filter(
|
|
IocLink.ioc_id.in_(iocs_list),
|
|
IocLink.case_id == caseid
|
|
).all()
|
|
|
|
for ioc in valid_iocs:
|
|
try:
|
|
|
|
cea = CaseEventsIoc()
|
|
cea.ioc_id = int(ioc.ioc_id)
|
|
cea.event_id = event_id
|
|
cea.case_id = caseid
|
|
|
|
db.session.add(cea)
|
|
|
|
except Exception as e:
|
|
return False, str(e)
|
|
|
|
db.session.commit()
|
|
return True, ''
|
|
|
|
|
|
def get_case_assets_for_tm(caseid):
|
|
"""
|
|
Return a list of all assets linked to the current case
|
|
:return: Tuple of assets
|
|
"""
|
|
assets = [{'asset_name': '', 'asset_id': '0'}]
|
|
|
|
assets_list = CaseAssets.query.with_entities(
|
|
CaseAssets.asset_name,
|
|
CaseAssets.asset_id,
|
|
AssetsType.asset_name.label('type')
|
|
).filter(
|
|
CaseAssets.case_id == caseid
|
|
).join(CaseAssets.asset_type).order_by(CaseAssets.asset_name).all()
|
|
|
|
for asset in assets_list:
|
|
assets.append({
|
|
'asset_name': "{} ({})".format(asset.asset_name, asset.type),
|
|
'asset_id': asset.asset_id
|
|
})
|
|
|
|
return assets
|
|
|
|
|
|
def get_case_iocs_for_tm(caseid):
|
|
iocs = [{'ioc_value': '', 'ioc_id': '0'}]
|
|
|
|
iocs_list = Ioc.query.with_entities(
|
|
Ioc.ioc_value,
|
|
Ioc.ioc_id
|
|
).filter(
|
|
IocLink.case_id == caseid
|
|
).join(
|
|
IocLink.ioc
|
|
).order_by(
|
|
Ioc.ioc_value
|
|
).all()
|
|
|
|
for ioc in iocs_list:
|
|
iocs.append({
|
|
'ioc_value': "{}".format(ioc.ioc_value),
|
|
'ioc_id': ioc.ioc_id
|
|
})
|
|
|
|
return iocs
|
|
|
|
|
|
def delete_event(event, caseid):
|
|
delete_event_category(event.event_id)
|
|
|
|
CaseEventsAssets.query.filter(
|
|
CaseEventsAssets.event_id == event.event_id,
|
|
CaseEventsAssets.case_id == caseid
|
|
).delete()
|
|
|
|
CaseEventsIoc.query.filter(
|
|
CaseEventsIoc.event_id == event.event_id,
|
|
CaseEventsIoc.case_id == caseid
|
|
).delete()
|
|
|
|
com_ids = EventComments.query.with_entities(
|
|
EventComments.comment_id
|
|
).filter(
|
|
EventComments.comment_event_id == event.event_id
|
|
).all()
|
|
|
|
com_ids = [c.comment_id for c in com_ids]
|
|
EventComments.query.filter(EventComments.comment_id.in_(com_ids)).delete()
|
|
|
|
Comments.query.filter(Comments.comment_id.in_(com_ids)).delete()
|
|
|
|
db.session.commit()
|
|
|
|
db.session.delete(event)
|
|
update_timeline_state(caseid=caseid)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
def get_category_by_name(cat_name):
|
|
return EventCategory.query.filter(
|
|
EventCategory.name == cat_name,
|
|
).first()
|
|
|
|
|
|
def get_default_category():
|
|
return EventCategory.query.with_entities(
|
|
EventCategory.id,
|
|
EventCategory.name
|
|
).filter(
|
|
EventCategory.name == "Unspecified"
|
|
).first()
|
|
|