Brak opisu

case_events_db.py 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. # IRIS Source Code
  2. # Copyright (C) 2021 - Airbus CyberSecurity (SAS)
  3. # ir@cyberactionlab.net
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Lesser General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 3 of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. # Lesser General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Lesser General Public License
  16. # along with this program; if not, write to the Free Software Foundation,
  17. # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. from flask_login import current_user
  19. from sqlalchemy import and_
  20. from app import db
  21. from app.datamgmt.states import update_timeline_state
  22. from app.models.models import AssetsType
  23. from app.models.models import CaseAssets
  24. from app.models.models import CaseEventCategory
  25. from app.models.models import CaseEventsAssets
  26. from app.models.models import CaseEventsIoc
  27. from app.models.cases import CasesEvent
  28. from app.models.models import Comments
  29. from app.models.models import EventCategory
  30. from app.models.models import EventComments
  31. from app.models.models import Ioc
  32. from app.models.models import IocAssetLink
  33. from app.models.models import IocType
  34. from app.models.authorization import User
  35. def get_case_events_assets_graph(caseid):
  36. events = CaseEventsAssets.query.with_entities(
  37. CaseEventsAssets.event_id,
  38. CasesEvent.event_uuid,
  39. CasesEvent.event_title,
  40. CaseAssets.asset_name,
  41. CaseAssets.asset_id,
  42. AssetsType.asset_name.label('type_name'),
  43. AssetsType.asset_icon_not_compromised,
  44. AssetsType.asset_icon_compromised,
  45. CasesEvent.event_color,
  46. CaseAssets.asset_compromise_status_id,
  47. CaseAssets.asset_description,
  48. CaseAssets.asset_ip,
  49. CasesEvent.event_date,
  50. CasesEvent.event_tags
  51. ).filter(and_(
  52. CaseEventsAssets.case_id == caseid,
  53. CasesEvent.event_in_graph == True
  54. )).join(
  55. CaseEventsAssets.event
  56. ).join(
  57. CaseEventsAssets.asset
  58. ).join(
  59. CaseAssets.asset_type
  60. ).all()
  61. return events
  62. def get_case_events_ioc_graph(caseid):
  63. events = CaseEventsIoc.query.with_entities(
  64. CaseEventsIoc.event_id,
  65. CasesEvent.event_uuid,
  66. CasesEvent.event_title,
  67. CasesEvent.event_date,
  68. Ioc.ioc_id,
  69. Ioc.ioc_value,
  70. Ioc.ioc_description,
  71. IocType.type_name
  72. ).filter(and_(
  73. CaseEventsIoc.case_id == caseid,
  74. CasesEvent.event_in_graph == True
  75. )).join(
  76. CaseEventsIoc.event
  77. ).join(
  78. CaseEventsIoc.ioc
  79. ).join(
  80. Ioc.ioc_type
  81. ).all()
  82. return events
  83. def get_events_categories():
  84. return EventCategory.query.with_entities(
  85. EventCategory.id,
  86. EventCategory.name
  87. ).all()
  88. def get_default_cat():
  89. cat = EventCategory.query.with_entities(
  90. EventCategory.id,
  91. EventCategory.name
  92. ).filter(
  93. EventCategory.name == "Unspecified"
  94. ).first()
  95. return [cat._asdict()]
  96. def get_case_event(event_id, caseid):
  97. return CasesEvent.query.filter(
  98. CasesEvent.event_id == event_id,
  99. CasesEvent.case_id == caseid
  100. ).first()
  101. def get_case_event_comments(event_id, caseid):
  102. return Comments.query.filter(
  103. EventComments.comment_event_id == event_id
  104. ).join(
  105. EventComments,
  106. Comments.comment_id == EventComments.comment_id
  107. ).order_by(
  108. Comments.comment_date.asc()
  109. ).all()
  110. def get_case_events_comments_count(events_list):
  111. return EventComments.query.filter(
  112. EventComments.comment_event_id.in_(events_list)
  113. ).with_entities(
  114. EventComments.comment_event_id,
  115. EventComments.comment_id
  116. ).group_by(
  117. EventComments.comment_event_id,
  118. EventComments.comment_id
  119. ).all()
  120. def get_case_event_comment(event_id, comment_id, caseid):
  121. return EventComments.query.filter(
  122. EventComments.comment_event_id == event_id,
  123. EventComments.comment_id == comment_id
  124. ).with_entities(
  125. Comments.comment_id,
  126. Comments.comment_text,
  127. Comments.comment_date,
  128. Comments.comment_update_date,
  129. Comments.comment_uuid,
  130. User.name,
  131. User.user
  132. ).join(
  133. EventComments.comment
  134. ).join(
  135. Comments.user
  136. ).first()
  137. def delete_event_comment(event_id, comment_id):
  138. comment = Comments.query.filter(
  139. Comments.comment_id == comment_id,
  140. Comments.comment_user_id == current_user.id
  141. ).first()
  142. if not comment:
  143. return False, "You are not allowed to delete this comment"
  144. EventComments.query.filter(
  145. EventComments.comment_event_id == event_id,
  146. EventComments.comment_id == comment_id
  147. ).delete()
  148. db.session.delete(comment)
  149. db.session.commit()
  150. return True, "Comment deleted"
  151. def add_comment_to_event(event_id, comment_id):
  152. ec = EventComments()
  153. ec.comment_event_id = event_id
  154. ec.comment_id = comment_id
  155. db.session.add(ec)
  156. db.session.commit()
  157. def delete_event_category(event_id):
  158. CaseEventCategory.query.filter(
  159. CaseEventCategory.event_id == event_id
  160. ).delete()
  161. def get_event_category(event_id):
  162. cec = CaseEventCategory.query.filter(
  163. CaseEventCategory.event_id == event_id
  164. ).first()
  165. return cec
  166. def save_event_category(event_id, category_id):
  167. CaseEventCategory.query.filter(
  168. CaseEventCategory.event_id == event_id
  169. ).delete()
  170. cec = CaseEventCategory()
  171. cec.event_id = event_id
  172. cec.category_id = category_id
  173. db.session.add(cec)
  174. db.session.commit()
  175. def get_event_assets_ids(event_id, caseid):
  176. assets_list = CaseEventsAssets.query.with_entities(
  177. CaseEventsAssets.asset_id
  178. ).filter(
  179. CaseEventsAssets.event_id == event_id,
  180. CaseEventsAssets.case_id == caseid
  181. ).all()
  182. return [x[0] for x in assets_list]
  183. def get_event_iocs_ids(event_id, caseid):
  184. iocs_list = CaseEventsIoc.query.with_entities(
  185. CaseEventsIoc.ioc_id
  186. ).filter(
  187. CaseEventsIoc.event_id == event_id,
  188. CaseEventsIoc.case_id == caseid
  189. ).all()
  190. return [x[0] for x in iocs_list]
  191. def update_event_assets(event_id, caseid, assets_list, iocs_list, sync_iocs_assets):
  192. CaseEventsAssets.query.filter(
  193. CaseEventsAssets.event_id == event_id,
  194. CaseEventsAssets.case_id == caseid
  195. ).delete()
  196. valid_assets = CaseAssets.query.with_entities(
  197. CaseAssets.asset_id
  198. ).filter(
  199. CaseAssets.asset_id.in_(assets_list),
  200. CaseAssets.case_id == caseid
  201. ).all()
  202. for asset in valid_assets:
  203. try:
  204. cea = CaseEventsAssets()
  205. cea.asset_id = int(asset.asset_id)
  206. cea.event_id = event_id
  207. cea.case_id = caseid
  208. db.session.add(cea)
  209. if sync_iocs_assets:
  210. for ioc in iocs_list:
  211. link = IocAssetLink.query.filter(
  212. IocAssetLink.asset_id == int(asset.asset_id),
  213. IocAssetLink.ioc_id == int(ioc)
  214. ).first()
  215. if link is None:
  216. ial = IocAssetLink()
  217. ial.asset_id = int(asset.asset_id)
  218. ial.ioc_id = int(ioc)
  219. db.session.add(ial)
  220. except Exception as e:
  221. return False, str(e)
  222. db.session.commit()
  223. return True, ''
  224. def update_event_iocs(event_id, caseid, iocs_list):
  225. CaseEventsIoc.query.filter(
  226. CaseEventsIoc.event_id == event_id,
  227. CaseEventsIoc.case_id == caseid
  228. ).delete()
  229. valid_iocs = Ioc.query.filter(
  230. Ioc.ioc_id.in_(iocs_list),
  231. Ioc.case_id == caseid
  232. ).all()
  233. for ioc in valid_iocs:
  234. try:
  235. cea = CaseEventsIoc()
  236. cea.ioc_id = int(ioc.ioc_id)
  237. cea.event_id = event_id
  238. cea.case_id = caseid
  239. db.session.add(cea)
  240. except Exception as e:
  241. return False, str(e)
  242. db.session.commit()
  243. return True, ''
  244. def get_case_assets_for_tm(caseid):
  245. """
  246. Return a list of all assets linked to the current case
  247. :return: Tuple of assets
  248. """
  249. assets = [{'asset_name': '', 'asset_id': '0'}]
  250. assets_list = CaseAssets.query.with_entities(
  251. CaseAssets.asset_name,
  252. CaseAssets.asset_id,
  253. AssetsType.asset_name.label('type')
  254. ).filter(
  255. CaseAssets.case_id == caseid
  256. ).join(CaseAssets.asset_type).order_by(CaseAssets.asset_name).all()
  257. for asset in assets_list:
  258. assets.append({
  259. 'asset_name': "{} ({})".format(asset.asset_name, asset.type),
  260. 'asset_id': asset.asset_id
  261. })
  262. return assets
  263. def get_case_iocs_for_tm(caseid):
  264. iocs = [{'ioc_value': '', 'ioc_id': '0'}]
  265. iocs_list = Ioc.query.with_entities(
  266. Ioc.ioc_value,
  267. Ioc.ioc_id
  268. ).filter(
  269. Ioc.case_id == caseid
  270. ).order_by(
  271. Ioc.ioc_value
  272. ).all()
  273. for ioc in iocs_list:
  274. iocs.append({
  275. 'ioc_value': "{}".format(ioc.ioc_value),
  276. 'ioc_id': ioc.ioc_id
  277. })
  278. return iocs
  279. def delete_event(event, caseid):
  280. delete_event_category(event.event_id)
  281. CaseEventsAssets.query.filter(
  282. CaseEventsAssets.event_id == event.event_id,
  283. CaseEventsAssets.case_id == caseid
  284. ).delete()
  285. CaseEventsIoc.query.filter(
  286. CaseEventsIoc.event_id == event.event_id,
  287. CaseEventsIoc.case_id == caseid
  288. ).delete()
  289. com_ids = EventComments.query.with_entities(
  290. EventComments.comment_id
  291. ).filter(
  292. EventComments.comment_event_id == event.event_id
  293. ).all()
  294. com_ids = [c.comment_id for c in com_ids]
  295. EventComments.query.filter(EventComments.comment_id.in_(com_ids)).delete()
  296. Comments.query.filter(Comments.comment_id.in_(com_ids)).delete()
  297. db.session.commit()
  298. db.session.delete(event)
  299. update_timeline_state(caseid=caseid)
  300. db.session.commit()
  301. def get_category_by_name(cat_name):
  302. return EventCategory.query.filter(
  303. EventCategory.name == cat_name,
  304. ).first()
  305. def get_default_category():
  306. return EventCategory.query.with_entities(
  307. EventCategory.id,
  308. EventCategory.name
  309. ).filter(
  310. EventCategory.name == "Unspecified"
  311. ).first()