This commit is contained in:
6
iris-web/source/app/models/__init__.py
Normal file
6
iris-web/source/app/models/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
from app.models.models import ObjectState
|
||||
from app.models.cases import Cases
|
||||
from app.models.cases import CasesEvent
|
||||
from app.models.cases import Client
|
||||
from app.models.models import *
|
||||
|
116
iris-web/source/app/models/alerts.py
Normal file
116
iris-web/source/app/models/alerts.py
Normal file
@ -0,0 +1,116 @@
|
||||
from datetime import datetime
|
||||
|
||||
import uuid
|
||||
from sqlalchemy.dialects.postgresql import JSON
|
||||
from sqlalchemy import BigInteger, Table, Boolean
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import DateTime
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
|
||||
from app import db
|
||||
from app.models import Base, alert_assets_association, alert_iocs_association
|
||||
from app.models.cases import Cases
|
||||
|
||||
|
||||
class AlertCaseAssociation(db.Model):
|
||||
__tablename__ = 'alert_case_association'
|
||||
|
||||
alert_id = Column(ForeignKey('alerts.alert_id'), primary_key=True, nullable=False)
|
||||
case_id = Column(ForeignKey('cases.case_id'), primary_key=True, nullable=False, index=True)
|
||||
|
||||
|
||||
class Alert(db.Model):
|
||||
__tablename__ = 'alerts'
|
||||
|
||||
alert_id = Column(BigInteger, primary_key=True)
|
||||
alert_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, nullable=False,
|
||||
server_default=text('gen_random_uuid()'), unique=True)
|
||||
alert_title = Column(Text, nullable=False)
|
||||
alert_description = Column(Text)
|
||||
alert_source = Column(Text)
|
||||
alert_source_ref = Column(Text)
|
||||
alert_source_link = Column(Text)
|
||||
alert_source_content = Column(JSON)
|
||||
alert_severity_id = Column(ForeignKey('severities.severity_id'), nullable=False)
|
||||
alert_status_id = Column(ForeignKey('alert_status.status_id'), nullable=False)
|
||||
alert_context = Column(JSON)
|
||||
alert_source_event_time = Column(DateTime, nullable=False, server_default=text("now()"))
|
||||
alert_creation_time = Column(DateTime, nullable=False, server_default=text("now()"))
|
||||
alert_note = Column(Text)
|
||||
alert_tags = Column(Text)
|
||||
alert_owner_id = Column(ForeignKey('user.id'))
|
||||
modification_history = Column(JSON)
|
||||
alert_customer_id = Column(ForeignKey('client.client_id'), nullable=False)
|
||||
alert_classification_id = Column(ForeignKey('case_classification.id'))
|
||||
alert_resolution_status_id = Column(ForeignKey('alert_resolution_status.resolution_status_id'), nullable=True)
|
||||
|
||||
owner = relationship('User', foreign_keys=[alert_owner_id])
|
||||
severity = relationship('Severity')
|
||||
status = relationship('AlertStatus')
|
||||
customer = relationship('Client')
|
||||
classification = relationship('CaseClassification')
|
||||
resolution_status = relationship('AlertResolutionStatus')
|
||||
|
||||
cases = relationship('Cases', secondary="alert_case_association", back_populates='alerts')
|
||||
comments = relationship('Comments', back_populates='alert', cascade='all, delete-orphan')
|
||||
|
||||
assets = relationship('CaseAssets', secondary=alert_assets_association, back_populates='alerts')
|
||||
iocs = relationship('Ioc', secondary=alert_iocs_association, back_populates='alerts')
|
||||
|
||||
|
||||
class Severity(db.Model):
|
||||
__tablename__ = 'severities'
|
||||
|
||||
severity_id = Column(Integer, primary_key=True)
|
||||
severity_name = Column(Text, nullable=False, unique=True)
|
||||
severity_description = Column(Text)
|
||||
|
||||
|
||||
class AlertStatus(db.Model):
|
||||
__tablename__ = 'alert_status'
|
||||
|
||||
status_id = Column(Integer, primary_key=True)
|
||||
status_name = Column(Text, nullable=False, unique=True)
|
||||
status_description = Column(Text)
|
||||
|
||||
|
||||
class AlertResolutionStatus(db.Model):
|
||||
__tablename__ = 'alert_resolution_status'
|
||||
|
||||
resolution_status_id = Column(Integer, primary_key=True)
|
||||
resolution_status_name = Column(Text, nullable=False, unique=True)
|
||||
resolution_status_description = Column(Text)
|
||||
|
||||
|
||||
class SimilarAlertsCache(db.Model):
|
||||
__tablename__ = 'similar_alerts_cache'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
customer_id = Column(BigInteger, ForeignKey('client.client_id'), nullable=False)
|
||||
asset_name = Column(Text, nullable=True)
|
||||
ioc_value = Column(Text, nullable=True)
|
||||
alert_id = Column(BigInteger, ForeignKey('alerts.alert_id'), nullable=False)
|
||||
created_at = Column(DateTime, nullable=False, server_default=text("now()"))
|
||||
|
||||
asset_type_id = Column(Integer, ForeignKey('assets_type.asset_id'), nullable=True)
|
||||
ioc_type_id = Column(Integer, ForeignKey('ioc_type.type_id'), nullable=True)
|
||||
|
||||
alert = relationship('Alert')
|
||||
customer = relationship('Client')
|
||||
asset_type = relationship('AssetsType')
|
||||
ioc_type = relationship('IocType')
|
||||
|
||||
def __init__(self, customer_id, alert_id, asset_name=None, ioc_value=None, asset_type_id=None, ioc_type_id=None,
|
||||
created_at=None):
|
||||
self.customer_id = customer_id
|
||||
self.asset_name = asset_name
|
||||
self.ioc_value = ioc_value
|
||||
self.alert_id = alert_id
|
||||
self.asset_type_id = asset_type_id
|
||||
self.ioc_type_id = ioc_type_id
|
||||
self.created_at = created_at if created_at else datetime.utcnow()
|
207
iris-web/source/app/models/authorization.py
Normal file
207
iris-web/source/app/models/authorization.py
Normal file
@ -0,0 +1,207 @@
|
||||
import enum
|
||||
import secrets
|
||||
import uuid
|
||||
from flask_login import UserMixin
|
||||
from sqlalchemy import BigInteger
|
||||
from sqlalchemy import Boolean
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy import UniqueConstraint
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app import db
|
||||
|
||||
|
||||
class CaseAccessLevel(enum.Enum):
|
||||
deny_all = 0x1
|
||||
read_only = 0x2
|
||||
full_access = 0x4
|
||||
|
||||
@classmethod
|
||||
def has_value(cls, value):
|
||||
return value in cls._value2member_map_
|
||||
|
||||
|
||||
class Permissions(enum.Enum):
|
||||
standard_user = 0x1
|
||||
server_administrator = 0x2
|
||||
|
||||
alerts_read = 0x4
|
||||
alerts_write = 0x8
|
||||
alerts_delete = 0x10
|
||||
|
||||
search_across_cases = 0x20
|
||||
|
||||
customers_read = 0x40
|
||||
customers_write = 0x80
|
||||
|
||||
case_templates_read = 0x100
|
||||
case_templates_write = 0x200
|
||||
|
||||
activities_read = 0x400
|
||||
all_activities_read = 0x800
|
||||
|
||||
|
||||
class Organisation(db.Model):
|
||||
__tablename__ = 'organisations'
|
||||
|
||||
org_id = Column(BigInteger, primary_key=True)
|
||||
org_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, nullable=False,
|
||||
server_default=text('gen_random_uuid()'), unique=True)
|
||||
org_name = Column(Text, nullable=False, unique=True)
|
||||
org_description = Column(Text)
|
||||
org_url = Column(Text)
|
||||
org_logo = Column(Text)
|
||||
org_email = Column(Text)
|
||||
org_nationality = Column(Text)
|
||||
org_sector = Column(Text)
|
||||
org_type = Column(Text)
|
||||
|
||||
UniqueConstraint('org_name')
|
||||
|
||||
|
||||
class OrganisationCaseAccess(db.Model):
|
||||
__tablename__ = "organisation_case_access"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
org_id = Column(BigInteger, ForeignKey('organisations.org_id'), nullable=False)
|
||||
case_id = Column(BigInteger, ForeignKey('cases.case_id'), nullable=False)
|
||||
access_level = Column(BigInteger, nullable=False)
|
||||
|
||||
org = relationship('Organisation')
|
||||
case = relationship('Cases')
|
||||
|
||||
UniqueConstraint('case_id', 'org_id')
|
||||
|
||||
|
||||
class Group(db.Model):
|
||||
__tablename__ = 'groups'
|
||||
|
||||
group_id = Column(BigInteger, primary_key=True)
|
||||
group_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, nullable=False,
|
||||
server_default=text('gen_random_uuid()'), unique=True)
|
||||
group_name = Column(Text, nullable=False, unique=True)
|
||||
group_description = Column(Text)
|
||||
group_permissions = Column(BigInteger, nullable=False)
|
||||
group_auto_follow = Column(Boolean, nullable=False, default=False)
|
||||
group_auto_follow_access_level = Column(BigInteger, nullable=False, default=0)
|
||||
|
||||
UniqueConstraint('group_name')
|
||||
|
||||
|
||||
class GroupCaseAccess(db.Model):
|
||||
__tablename__ = "group_case_access"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
group_id = Column(BigInteger, ForeignKey('groups.group_id'), nullable=False)
|
||||
case_id = Column(BigInteger, ForeignKey('cases.case_id'), nullable=False)
|
||||
access_level = Column(BigInteger, nullable=False)
|
||||
|
||||
group = relationship('Group')
|
||||
case = relationship('Cases')
|
||||
|
||||
UniqueConstraint('case_id', 'group_id')
|
||||
|
||||
|
||||
class UserCaseAccess(db.Model):
|
||||
__tablename__ = "user_case_access"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, nullable=False)
|
||||
user_id = Column(BigInteger, ForeignKey('user.id'), nullable=False)
|
||||
case_id = Column(BigInteger, ForeignKey('cases.case_id'), nullable=False)
|
||||
access_level = Column(BigInteger, nullable=False)
|
||||
|
||||
user = relationship('User')
|
||||
case = relationship('Cases')
|
||||
|
||||
UniqueConstraint('case_id', 'user_id')
|
||||
|
||||
|
||||
class UserCaseEffectiveAccess(db.Model):
|
||||
__tablename__ = "user_case_effective_access"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, nullable=False)
|
||||
user_id = Column(BigInteger, ForeignKey('user.id'), nullable=False)
|
||||
case_id = Column(BigInteger, ForeignKey('cases.case_id'), nullable=False)
|
||||
access_level = Column(BigInteger, nullable=False)
|
||||
|
||||
user = relationship('User')
|
||||
case = relationship('Cases')
|
||||
|
||||
UniqueConstraint('case_id', 'user_id')
|
||||
|
||||
|
||||
class UserOrganisation(db.Model):
|
||||
__tablename__ = "user_organisation"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, nullable=False)
|
||||
user_id = Column(BigInteger, ForeignKey('user.id'), nullable=False)
|
||||
org_id = Column(BigInteger, ForeignKey('organisations.org_id'), nullable=False)
|
||||
is_primary_org = Column(Boolean, nullable=False)
|
||||
|
||||
user = relationship('User')
|
||||
org = relationship('Organisation')
|
||||
|
||||
UniqueConstraint('user_id', 'org_id')
|
||||
|
||||
|
||||
class UserGroup(db.Model):
|
||||
__tablename__ = "user_group"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, nullable=False)
|
||||
user_id = Column(BigInteger, ForeignKey('user.id'), nullable=False)
|
||||
group_id = Column(BigInteger, ForeignKey('groups.group_id'), nullable=False)
|
||||
|
||||
user = relationship('User')
|
||||
group = relationship('Group')
|
||||
|
||||
UniqueConstraint('user_id', 'group_id')
|
||||
|
||||
|
||||
class User(UserMixin, db.Model):
|
||||
__tablename__ = 'user'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
user = Column(String(64), unique=True)
|
||||
name = Column(String(64), unique=False)
|
||||
email = Column(String(120), unique=True)
|
||||
uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, nullable=False,
|
||||
server_default=text('gen_random_uuid()'), unique=True)
|
||||
password = Column(String(500))
|
||||
ctx_case = Column(Integer)
|
||||
ctx_human_case = Column(String(256))
|
||||
active = Column(Boolean())
|
||||
api_key = Column(Text(), unique=True)
|
||||
external_id = Column(Text, unique=True)
|
||||
in_dark_mode = Column(Boolean())
|
||||
has_mini_sidebar = Column(Boolean(), default=False)
|
||||
has_deletion_confirmation = Column(Boolean(), default=False)
|
||||
is_service_account = Column(Boolean(), default=False)
|
||||
|
||||
def __init__(self, user: str, name: str, email: str, password: str, active: bool,
|
||||
external_id: str = None, is_service_account: bool = False):
|
||||
self.user = user
|
||||
self.name = name
|
||||
self.password = password
|
||||
self.email = email
|
||||
self.active = active
|
||||
self.external_id = external_id
|
||||
self.is_service_account = is_service_account
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.id) + ' - ' + str(self.user)
|
||||
|
||||
def save(self):
|
||||
|
||||
self.api_key = secrets.token_urlsafe(nbytes=64)
|
||||
|
||||
# inject self into db session
|
||||
db.session.add(self)
|
||||
db.session.commit()
|
||||
|
||||
return self
|
223
iris-web/source/app/models/cases.py
Normal file
223
iris-web/source/app/models/cases.py
Normal file
@ -0,0 +1,223 @@
|
||||
#!/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.
|
||||
import uuid
|
||||
|
||||
from datetime import datetime
|
||||
from flask_login import current_user
|
||||
# IMPORTS ------------------------------------------------
|
||||
from sqlalchemy import BigInteger, Table
|
||||
from sqlalchemy import Boolean
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import Date
|
||||
from sqlalchemy import DateTime
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy import UniqueConstraint
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.dialects.postgresql import JSON
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app import db
|
||||
from app.datamgmt.states import update_assets_state
|
||||
from app.datamgmt.states import update_evidences_state
|
||||
from app.datamgmt.states import update_ioc_state
|
||||
from app.datamgmt.states import update_notes_state
|
||||
from app.datamgmt.states import update_tasks_state
|
||||
from app.datamgmt.states import update_timeline_state
|
||||
from app.models.models import Client, Base
|
||||
|
||||
|
||||
class Cases(db.Model):
|
||||
__tablename__ = 'cases'
|
||||
|
||||
case_id = Column(BigInteger, primary_key=True)
|
||||
soc_id = Column(String(256))
|
||||
client_id = Column(ForeignKey('client.client_id'), nullable=False)
|
||||
name = Column(String(256))
|
||||
description = Column(Text)
|
||||
open_date = Column(Date)
|
||||
close_date = Column(Date)
|
||||
initial_date = Column(DateTime, nullable=False, server_default=text("now()"))
|
||||
closing_note = Column(Text)
|
||||
user_id = Column(ForeignKey('user.id'))
|
||||
owner_id = Column(ForeignKey('user.id'))
|
||||
status_id = Column(Integer, nullable=False, server_default=text("0"))
|
||||
state_id = Column(ForeignKey('case_state.state_id'), nullable=True)
|
||||
custom_attributes = Column(JSON)
|
||||
case_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"),
|
||||
nullable=False)
|
||||
classification_id = Column(ForeignKey('case_classification.id'))
|
||||
reviewer_id = Column(ForeignKey('user.id'), nullable=True)
|
||||
review_status_id = Column(ForeignKey('review_status.id'), nullable=True)
|
||||
|
||||
modification_history = Column(JSON)
|
||||
|
||||
client = relationship('Client')
|
||||
user = relationship('User', foreign_keys=[user_id])
|
||||
owner = relationship('User', foreign_keys=[owner_id])
|
||||
classification = relationship('CaseClassification')
|
||||
reviewer = relationship('User', foreign_keys=[reviewer_id])
|
||||
|
||||
alerts = relationship('Alert', secondary="alert_case_association", back_populates='cases', viewonly=True)
|
||||
|
||||
tags = relationship('Tags', secondary="case_tags", back_populates='cases')
|
||||
state = relationship('CaseState', back_populates='cases')
|
||||
|
||||
review_status = relationship('ReviewStatus')
|
||||
|
||||
def __init__(self,
|
||||
name=None,
|
||||
soc_id=None,
|
||||
client_id=None,
|
||||
description=None,
|
||||
user=None,
|
||||
custom_attributes=None,
|
||||
classification_id=None,
|
||||
state_id=None
|
||||
):
|
||||
self.name = name[:200] if name else None,
|
||||
self.soc_id = soc_id,
|
||||
self.client_id = client_id,
|
||||
self.description = description,
|
||||
self.user_id = current_user.id if current_user else user.id
|
||||
self.owner_id = self.user_id
|
||||
self.author = current_user.user if current_user else user.user
|
||||
self.description = description
|
||||
self.open_date = datetime.utcnow()
|
||||
self.close_date = None
|
||||
self.initial_date = datetime.utcnow()
|
||||
self.custom_attributes = custom_attributes
|
||||
self.case_uuid = uuid.uuid4()
|
||||
self.status_id = 0
|
||||
self.classification_id = classification_id
|
||||
self.state_id = state_id
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the current case in database
|
||||
:return:
|
||||
"""
|
||||
# Inject self into db
|
||||
db.session.add(self)
|
||||
|
||||
# Commit the changes
|
||||
db.session.commit()
|
||||
|
||||
# Rename case with the ID
|
||||
self.name = "#{id} - {name}".format(id=self.case_id, name=self.name)
|
||||
|
||||
# Create the states
|
||||
update_timeline_state(caseid=self.case_id, userid=self.user_id)
|
||||
update_tasks_state(caseid=self.case_id, userid=self.user_id)
|
||||
update_evidences_state(caseid=self.case_id, userid=self.user_id)
|
||||
update_ioc_state(caseid=self.case_id, userid=self.user_id)
|
||||
update_assets_state(caseid=self.case_id, userid=self.user_id)
|
||||
update_notes_state(caseid=self.case_id, userid=self.user_id)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
return self
|
||||
|
||||
def validate_on_build(self):
|
||||
"""
|
||||
Execute an autocheck of the case metadata and validate it
|
||||
:return: True if valid else false; Tuple with errors
|
||||
"""
|
||||
# TODO : Check if case name already exists
|
||||
|
||||
res = Client.query\
|
||||
.with_entities(Client.client_id)\
|
||||
.filter(Client.client_id == self.client_id)\
|
||||
.first()
|
||||
|
||||
self.client_id = res[0]
|
||||
|
||||
return True, []
|
||||
|
||||
|
||||
class CaseTags(db.Model):
|
||||
__tablename__ = 'case_tags'
|
||||
__table_args__ = (
|
||||
UniqueConstraint('case_id', 'tag_id', name='case_tags_case_id_tag_id_key'),
|
||||
)
|
||||
|
||||
case_id = Column(ForeignKey('cases.case_id'), primary_key=True, nullable=False)
|
||||
tag_id = Column(ForeignKey('tags.id'), primary_key=True, nullable=False, index=True)
|
||||
|
||||
|
||||
class CasesEvent(db.Model):
|
||||
__tablename__ = "cases_events"
|
||||
|
||||
event_id = Column(BigInteger, primary_key=True)
|
||||
event_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"),
|
||||
nullable=False)
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
event_title = Column(Text)
|
||||
event_source = Column(Text)
|
||||
event_content = Column(Text)
|
||||
event_raw = Column(Text)
|
||||
event_date = Column(DateTime)
|
||||
event_added = Column(DateTime)
|
||||
event_in_graph = Column(Boolean)
|
||||
event_in_summary = Column(Boolean)
|
||||
user_id = Column(ForeignKey('user.id'))
|
||||
modification_history = Column(JSONB)
|
||||
event_color = Column(Text)
|
||||
event_tags = Column(Text)
|
||||
event_tz = Column(Text)
|
||||
event_date_wtz = Column(DateTime)
|
||||
event_is_flagged = Column(Boolean, default=False)
|
||||
custom_attributes = Column(JSONB)
|
||||
|
||||
case = relationship('Cases')
|
||||
user = relationship('User')
|
||||
category = relationship('EventCategory', secondary="case_events_category",
|
||||
primaryjoin="CasesEvent.event_id==CaseEventCategory.event_id",
|
||||
secondaryjoin="CaseEventCategory.category_id==EventCategory.id",
|
||||
viewonly=True)
|
||||
|
||||
|
||||
class CaseState(db.Model):
|
||||
__tablename__ = 'case_state'
|
||||
|
||||
state_id = Column(Integer, primary_key=True)
|
||||
state_name = Column(Text, nullable=False)
|
||||
state_description = Column(Text)
|
||||
protected = Column(Boolean, default=False)
|
||||
|
||||
cases = relationship('Cases', back_populates='state')
|
||||
|
||||
|
||||
class CaseProtagonist(db.Model):
|
||||
__tablename__ = "case_protagonist"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
user_id = Column(ForeignKey('user.id'))
|
||||
name = Column(Text)
|
||||
contact = Column(Text)
|
||||
role = Column(Text)
|
||||
|
||||
case = relationship('Cases')
|
||||
user = relationship('User')
|
950
iris-web/source/app/models/models.py
Normal file
950
iris-web/source/app/models/models.py
Normal file
@ -0,0 +1,950 @@
|
||||
#!/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.
|
||||
import datetime
|
||||
|
||||
# IMPORTS ------------------------------------------------
|
||||
import enum
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import BigInteger, UniqueConstraint, Table
|
||||
from sqlalchemy import Boolean
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import DateTime
|
||||
from sqlalchemy import ForeignKey
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import LargeBinary
|
||||
from sqlalchemy import Sequence
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import TIMESTAMP
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy.dialects.postgresql import JSON, JSONB
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
from app import app
|
||||
from app import db
|
||||
|
||||
Base = declarative_base()
|
||||
metadata = Base.metadata
|
||||
|
||||
|
||||
class CaseStatus(enum.Enum):
|
||||
unknown = 0x0
|
||||
false_positive = 0x1
|
||||
true_positive_with_impact = 0x2
|
||||
not_applicable = 0x3
|
||||
true_positive_without_impact = 0x4
|
||||
|
||||
|
||||
class ReviewStatusList:
|
||||
no_review_required = "No review required"
|
||||
not_reviewed = "Not reviewed"
|
||||
pending_review = "Pending review"
|
||||
review_in_progress = "Review in progress"
|
||||
reviewed = "Reviewed"
|
||||
|
||||
|
||||
class CompromiseStatus(enum.Enum):
|
||||
to_be_determined = 0x0
|
||||
compromised = 0x1
|
||||
not_compromised = 0x2
|
||||
unknown = 0x3
|
||||
|
||||
@classmethod
|
||||
def has_value(cls, value):
|
||||
return value in cls._value2member_map_
|
||||
|
||||
|
||||
def create_safe(session, model, **kwargs):
|
||||
instance = session.query(model).filter_by(**kwargs).first()
|
||||
if instance:
|
||||
return False
|
||||
else:
|
||||
instance = model(**kwargs)
|
||||
session.add(instance)
|
||||
session.commit()
|
||||
return True
|
||||
|
||||
|
||||
def create_safe_limited(session, model, keywords_list, **kwargs):
|
||||
kwdup = kwargs.keys()
|
||||
for kw in list(kwdup):
|
||||
if kw not in keywords_list:
|
||||
kwargs.pop(kw)
|
||||
|
||||
instance = session.query(model).filter_by(**kwargs).first()
|
||||
if instance:
|
||||
return False
|
||||
else:
|
||||
instance = model(**kwargs)
|
||||
session.add(instance)
|
||||
session.commit()
|
||||
return True
|
||||
|
||||
|
||||
def get_by_value_or_create(session, model, fieldname, **kwargs):
|
||||
select_value = {fieldname: kwargs.get(fieldname)}
|
||||
instance = session.query(model).filter_by(**select_value).first()
|
||||
if instance:
|
||||
return instance
|
||||
else:
|
||||
instance = model(**kwargs)
|
||||
session.add(instance)
|
||||
session.commit()
|
||||
return instance
|
||||
|
||||
|
||||
def get_or_create(session, model, **kwargs):
|
||||
instance = session.query(model).filter_by(**kwargs).first()
|
||||
if instance:
|
||||
return instance
|
||||
else:
|
||||
instance = model(**kwargs)
|
||||
session.add(instance)
|
||||
session.commit()
|
||||
return instance
|
||||
|
||||
|
||||
# CONTENT ------------------------------------------------
|
||||
class Client(db.Model):
|
||||
__tablename__ = 'client'
|
||||
|
||||
client_id = Column(BigInteger, primary_key=True)
|
||||
client_uuid = Column(UUID(as_uuid=True), server_default=text("gen_random_uuid()"), nullable=False)
|
||||
name = Column(Text, unique=True)
|
||||
description = Column(Text)
|
||||
sla = Column(Text)
|
||||
creation_date = Column(DateTime, server_default=func.now(), nullable=True)
|
||||
created_by = Column(ForeignKey('user.id'), nullable=True)
|
||||
last_update_date = Column(DateTime, server_default=func.now(), nullable=True)
|
||||
|
||||
custom_attributes = Column(JSON)
|
||||
|
||||
|
||||
class AssetsType(db.Model):
|
||||
__tablename__ = 'assets_type'
|
||||
|
||||
asset_id = Column(Integer, primary_key=True)
|
||||
asset_name = Column(String(155))
|
||||
asset_description = Column(String(255))
|
||||
asset_icon_not_compromised = Column(String(255))
|
||||
asset_icon_compromised = Column(String(255))
|
||||
|
||||
|
||||
alert_assets_association = Table(
|
||||
'alert_assets_association',
|
||||
db.Model.metadata,
|
||||
Column('alert_id', ForeignKey('alerts.alert_id'), primary_key=True),
|
||||
Column('asset_id', ForeignKey('case_assets.asset_id'), primary_key=True)
|
||||
)
|
||||
|
||||
|
||||
alert_iocs_association = Table(
|
||||
'alert_iocs_association',
|
||||
db.Model.metadata,
|
||||
Column('alert_id', ForeignKey('alerts.alert_id'), primary_key=True),
|
||||
Column('ioc_id', ForeignKey('ioc.ioc_id'), primary_key=True)
|
||||
)
|
||||
|
||||
|
||||
class CaseAssets(db.Model):
|
||||
__tablename__ = 'case_assets'
|
||||
|
||||
asset_id = Column(BigInteger, primary_key=True)
|
||||
asset_uuid = Column(UUID(as_uuid=True), server_default=text("gen_random_uuid()"), nullable=False)
|
||||
asset_name = Column(Text)
|
||||
asset_description = Column(Text)
|
||||
asset_domain = Column(Text)
|
||||
asset_ip = Column(Text)
|
||||
asset_info = Column(Text)
|
||||
asset_compromise_status_id = Column(Integer, nullable=True)
|
||||
asset_type_id = Column(ForeignKey('assets_type.asset_id'))
|
||||
asset_tags = Column(Text)
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
date_added = Column(DateTime)
|
||||
date_update = Column(DateTime)
|
||||
user_id = Column(ForeignKey('user.id'))
|
||||
analysis_status_id = Column(ForeignKey('analysis_status.id'))
|
||||
custom_attributes = Column(JSON)
|
||||
asset_enrichment = Column(JSONB)
|
||||
|
||||
case = relationship('Cases')
|
||||
user = relationship('User')
|
||||
asset_type = relationship('AssetsType')
|
||||
analysis_status = relationship('AnalysisStatus')
|
||||
|
||||
alerts = relationship('Alert', secondary=alert_assets_association, back_populates='assets')
|
||||
|
||||
|
||||
class AnalysisStatus(db.Model):
|
||||
__tablename__ = 'analysis_status'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(Text)
|
||||
|
||||
|
||||
class CaseClassification(db.Model):
|
||||
__tablename__ = 'case_classification'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(Text)
|
||||
name_expanded = Column(Text)
|
||||
description = Column(Text)
|
||||
creation_date = Column(DateTime, server_default=func.now(), nullable=True)
|
||||
created_by_id = Column(ForeignKey('user.id'), nullable=True)
|
||||
|
||||
created_by = relationship('User')
|
||||
|
||||
|
||||
class CaseTemplate(db.Model):
|
||||
__tablename__ = 'case_template'
|
||||
|
||||
# Metadata
|
||||
id = Column(Integer, primary_key=True)
|
||||
created_by_user_id = Column(Integer, db.ForeignKey('user.id'))
|
||||
created_at = Column(DateTime, server_default=func.now())
|
||||
updated_at = Column(DateTime, onupdate=func.now())
|
||||
# Data
|
||||
name = Column(String, nullable=False)
|
||||
display_name = Column(String, nullable=True)
|
||||
description = Column(Text, nullable=True)
|
||||
author = Column(String, nullable=True)
|
||||
title_prefix = Column(String, nullable=True)
|
||||
summary = Column(String, nullable=True)
|
||||
tags = Column(JSON, nullable=True)
|
||||
tasks = Column(JSON, nullable=True)
|
||||
note_groups = Column(JSON, nullable=True)
|
||||
classification = Column(String, nullable=True)
|
||||
|
||||
created_by_user = relationship('User')
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def update_from_dict(self, data: dict):
|
||||
for field, value in data.items():
|
||||
setattr(self, field, value)
|
||||
|
||||
|
||||
class Contact(db.Model):
|
||||
__tablename__ = 'contact'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
contact_uuid = Column(UUID(as_uuid=True), server_default=text("gen_random_uuid()"), nullable=False)
|
||||
contact_name = Column(Text)
|
||||
contact_email = Column(Text)
|
||||
contact_role = Column(Text)
|
||||
contact_note = Column(Text)
|
||||
contact_work_phone = Column(Text)
|
||||
contact_mobile_phone = Column(Text)
|
||||
custom_attributes = Column(JSON)
|
||||
client_id = Column(ForeignKey('client.client_id'))
|
||||
|
||||
client = relationship('Client')
|
||||
|
||||
|
||||
class CaseEventsAssets(db.Model):
|
||||
__tablename__ = 'case_events_assets'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
event_id = Column(ForeignKey('cases_events.event_id'))
|
||||
asset_id = Column(ForeignKey('case_assets.asset_id'))
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
|
||||
event = relationship('CasesEvent')
|
||||
asset = relationship('CaseAssets')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class CaseEventsIoc(db.Model):
|
||||
__tablename__ = 'case_events_ioc'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
event_id = Column(ForeignKey('cases_events.event_id'))
|
||||
ioc_id = Column(ForeignKey('ioc.ioc_id'))
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
|
||||
event = relationship('CasesEvent')
|
||||
ioc = relationship('Ioc')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class ObjectState(db.Model):
|
||||
__tablename__ = 'object_state'
|
||||
|
||||
object_id = Column(BigInteger, primary_key=True)
|
||||
object_case_id = Column(ForeignKey('cases.case_id'))
|
||||
object_updated_by_id = db.Column(db.Integer(), db.ForeignKey('user.id'))
|
||||
object_name = Column(Text)
|
||||
object_state = Column(BigInteger)
|
||||
object_last_update = Column(TIMESTAMP)
|
||||
|
||||
case = relationship('Cases')
|
||||
updated_by = relationship('User')
|
||||
|
||||
|
||||
class EventCategory(db.Model):
|
||||
__tablename__ = 'event_category'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(Text)
|
||||
|
||||
|
||||
class CaseEventCategory(db.Model):
|
||||
__tablename__ = 'case_events_category'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
event_id = Column(ForeignKey('cases_events.event_id'), unique=True)
|
||||
category_id = Column(ForeignKey('event_category.id'))
|
||||
|
||||
event = relationship('CasesEvent', cascade="delete")
|
||||
category = relationship('EventCategory')
|
||||
|
||||
|
||||
class CaseGraphAssets(db.Model):
|
||||
__tablename__ = 'case_graph_assets'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
asset_id = Column(Integer)
|
||||
asset_type_id = Column(ForeignKey('assets_type.asset_id'))
|
||||
|
||||
case = relationship('Cases')
|
||||
asset_type = relationship('AssetsType')
|
||||
|
||||
|
||||
class CaseGraphLinks(db.Model):
|
||||
__tablename__ = 'case_graph_links'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
source_id = Column(ForeignKey('case_graph_assets.id'))
|
||||
dest_id = Column(ForeignKey('case_graph_assets.id'))
|
||||
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class Languages(db.Model):
|
||||
__tablename__ = 'languages'
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
name = db.Column(db.String(), unique=True)
|
||||
code = db.Column(db.String(), unique=True)
|
||||
|
||||
|
||||
class ReportType(db.Model):
|
||||
__tablename__ = 'report_type'
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
name = db.Column(db.Text(), unique=True)
|
||||
|
||||
|
||||
class CaseTemplateReport(db.Model):
|
||||
__tablename__ = 'case_template_report'
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
name = db.Column(db.String())
|
||||
description = db.Column(db.String())
|
||||
internal_reference = db.Column(db.String(), unique=True)
|
||||
naming_format = db.Column(db.String())
|
||||
created_by_user_id = db.Column(db.Integer(), db.ForeignKey('user.id'))
|
||||
date_created = db.Column(DateTime)
|
||||
language_id = db.Column(db.Integer(), db.ForeignKey('languages.id'))
|
||||
report_type_id = db.Column(db.Integer(), db.ForeignKey('report_type.id'))
|
||||
|
||||
report_type = relationship('ReportType')
|
||||
language = relationship('Languages')
|
||||
created_by_user = relationship('User')
|
||||
|
||||
|
||||
class Tlp(db.Model):
|
||||
__tablename__ = 'tlp'
|
||||
|
||||
tlp_id = Column(Integer, primary_key=True)
|
||||
tlp_name = Column(Text)
|
||||
tlp_bscolor = Column(Text)
|
||||
|
||||
|
||||
class Ioc(db.Model):
|
||||
__tablename__ = 'ioc'
|
||||
|
||||
ioc_id = Column(BigInteger, primary_key=True)
|
||||
ioc_uuid = Column(UUID(as_uuid=True), server_default=text("gen_random_uuid()"), nullable=False)
|
||||
ioc_value = Column(Text)
|
||||
ioc_type_id = Column(ForeignKey('ioc_type.type_id'))
|
||||
ioc_description = Column(Text)
|
||||
ioc_tags = Column(String(512))
|
||||
user_id = Column(ForeignKey('user.id'))
|
||||
ioc_misp = Column(Text)
|
||||
ioc_tlp_id = Column(ForeignKey('tlp.tlp_id'))
|
||||
custom_attributes = Column(JSON)
|
||||
ioc_enrichment = Column(JSONB)
|
||||
|
||||
user = relationship('User')
|
||||
tlp = relationship('Tlp')
|
||||
ioc_type = relationship('IocType')
|
||||
|
||||
alerts = relationship('Alert', secondary=alert_iocs_association, back_populates='iocs')
|
||||
|
||||
|
||||
class CustomAttribute(db.Model):
|
||||
__tablename__ = 'custom_attribute'
|
||||
|
||||
attribute_id = Column(Integer, primary_key=True)
|
||||
attribute_display_name = Column(Text)
|
||||
attribute_description = Column(Text)
|
||||
attribute_for = Column(Text)
|
||||
attribute_content = Column(JSON)
|
||||
|
||||
|
||||
class DataStorePath(db.Model):
|
||||
__tablename__ = 'data_store_path'
|
||||
|
||||
path_id = Column(BigInteger, primary_key=True)
|
||||
path_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4)
|
||||
path_name = Column(Text, nullable=False)
|
||||
path_parent_id = Column(BigInteger)
|
||||
path_is_root = Column(Boolean)
|
||||
path_case_id = Column(ForeignKey('cases.case_id'), nullable=False)
|
||||
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class DataStoreFile(db.Model):
|
||||
__tablename__ = 'data_store_file'
|
||||
|
||||
file_id = Column(BigInteger, primary_key=True)
|
||||
file_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"), nullable=False)
|
||||
file_original_name = Column(Text, nullable=False)
|
||||
file_local_name = Column(Text, nullable=False)
|
||||
file_description = Column(Text)
|
||||
file_date_added = Column(DateTime)
|
||||
file_tags = Column(Text)
|
||||
file_size = Column(BigInteger)
|
||||
file_is_ioc = Column(Boolean)
|
||||
file_is_evidence = Column(Boolean)
|
||||
file_password = Column(Text)
|
||||
file_parent_id = Column(ForeignKey('data_store_path.path_id'), nullable=False)
|
||||
file_sha256 = Column(Text)
|
||||
added_by_user_id = Column(ForeignKey('user.id'), nullable=False)
|
||||
modification_history = Column(JSON)
|
||||
file_case_id = Column(ForeignKey('cases.case_id'), nullable=False)
|
||||
|
||||
case = relationship('Cases')
|
||||
user = relationship('User')
|
||||
data_parent = relationship('DataStorePath')
|
||||
|
||||
|
||||
class IocType(db.Model):
|
||||
__tablename__ = 'ioc_type'
|
||||
|
||||
type_id = Column(Integer, primary_key=True)
|
||||
type_name = Column(Text)
|
||||
type_description = Column(Text)
|
||||
type_taxonomy = Column(Text)
|
||||
type_validation_regex = Column(Text)
|
||||
type_validation_expect = Column(Text)
|
||||
|
||||
|
||||
class IocLink(db.Model):
|
||||
__tablename__ = 'ioc_link'
|
||||
|
||||
ioc_link_id = Column(Integer, primary_key=True)
|
||||
ioc_id = Column(ForeignKey('ioc.ioc_id'))
|
||||
case_id = Column(ForeignKey('cases.case_id'), nullable=False)
|
||||
|
||||
ioc = relationship('Ioc')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class IocAssetLink(db.Model):
|
||||
__tablename__ = 'ioc_asset_link'
|
||||
|
||||
ioc_asset_link_id = Column(Integer, primary_key=True)
|
||||
ioc_id = Column(ForeignKey('ioc.ioc_id'), nullable=False)
|
||||
asset_id = Column(ForeignKey('case_assets.asset_id'), nullable=False)
|
||||
|
||||
ioc = relationship('Ioc')
|
||||
asset = relationship('CaseAssets')
|
||||
|
||||
|
||||
class OsType(db.Model):
|
||||
__tablename__ = 'os_type'
|
||||
|
||||
type_id = Column(Integer, primary_key=True)
|
||||
type_name = Column(String(155))
|
||||
|
||||
|
||||
class CasesAssetsExt(db.Model):
|
||||
__tablename__ = 'cases_assets_ext'
|
||||
|
||||
asset_id = Column(Integer, primary_key=True)
|
||||
type_id = Column(ForeignKey('assets_type.asset_id'))
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
asset_content = Column(Text)
|
||||
|
||||
type = relationship('AssetsType')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class Notes(db.Model):
|
||||
__tablename__ = 'notes'
|
||||
|
||||
note_id = Column(BigInteger, primary_key=True)
|
||||
note_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"), nullable=False)
|
||||
note_title = Column(String(155))
|
||||
note_content = Column(Text)
|
||||
note_user = Column(ForeignKey('user.id'))
|
||||
note_creationdate = Column(DateTime)
|
||||
note_lastupdate = Column(DateTime)
|
||||
note_case_id = Column(ForeignKey('cases.case_id'))
|
||||
custom_attributes = Column(JSON)
|
||||
|
||||
user = relationship('User')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class NotesGroup(db.Model):
|
||||
__tablename__ = 'notes_group'
|
||||
|
||||
group_id = Column(BigInteger, primary_key=True)
|
||||
group_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"),
|
||||
nullable=False)
|
||||
group_title = Column(String(155))
|
||||
group_user = Column(ForeignKey('user.id'))
|
||||
group_creationdate = Column(DateTime)
|
||||
group_lastupdate = Column(DateTime)
|
||||
group_case_id = Column(ForeignKey('cases.case_id'))
|
||||
|
||||
user = relationship('User')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class NotesGroupLink(db.Model):
|
||||
__tablename__ = 'notes_group_link'
|
||||
|
||||
link_id = Column(BigInteger, primary_key=True)
|
||||
group_id = Column(ForeignKey('notes_group.group_id'))
|
||||
note_id = Column(ForeignKey('notes.note_id'))
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
|
||||
note = relationship('Notes')
|
||||
note_group = relationship('NotesGroup')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class CaseKanban(db.Model):
|
||||
__tablename__ = 'case_kanban'
|
||||
|
||||
case_id = Column(ForeignKey('cases.case_id'), primary_key=True)
|
||||
kanban_data = Column(Text)
|
||||
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class CaseReceivedFile(db.Model):
|
||||
__tablename__ = 'case_received_file'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
file_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"), nullable=False)
|
||||
filename = Column(Text)
|
||||
date_added = Column(DateTime)
|
||||
file_hash = Column(String(65))
|
||||
file_description = Column(Text)
|
||||
file_size = Column(BigInteger)
|
||||
case_id = Column(ForeignKey('cases.case_id'))
|
||||
user_id = Column(ForeignKey('user.id'))
|
||||
custom_attributes = Column(JSON)
|
||||
|
||||
case = relationship('Cases')
|
||||
user = relationship('User')
|
||||
|
||||
|
||||
class TaskStatus(db.Model):
|
||||
__tablename__ = 'task_status'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
status_name = Column(Text)
|
||||
status_description = Column(Text)
|
||||
status_bscolor = Column(Text)
|
||||
|
||||
|
||||
class CaseTasks(db.Model):
|
||||
__tablename__ = 'case_tasks'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
task_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"), nullable=False)
|
||||
task_title = Column(Text)
|
||||
task_description = Column(Text)
|
||||
task_tags = Column(Text)
|
||||
task_open_date = Column(DateTime)
|
||||
task_close_date = Column(DateTime)
|
||||
task_last_update = Column(DateTime)
|
||||
task_userid_open = Column(ForeignKey('user.id'))
|
||||
task_userid_close = Column(ForeignKey('user.id'))
|
||||
task_userid_update = Column(ForeignKey('user.id'))
|
||||
task_status_id = Column(ForeignKey('task_status.id'))
|
||||
task_case_id = Column(ForeignKey('cases.case_id'))
|
||||
custom_attributes = Column(JSON)
|
||||
|
||||
case = relationship('Cases')
|
||||
user_open = relationship('User', foreign_keys=[task_userid_open])
|
||||
user_close = relationship('User', foreign_keys=[task_userid_close])
|
||||
user_update = relationship('User', foreign_keys=[task_userid_update])
|
||||
status = relationship('TaskStatus', foreign_keys=[task_status_id])
|
||||
|
||||
|
||||
class Tags(db.Model):
|
||||
__tablename__ = 'tags'
|
||||
|
||||
id = Column(BigInteger, primary_key=True, nullable=False)
|
||||
tag_title = Column(Text, unique=True)
|
||||
tag_creation_date = Column(DateTime)
|
||||
|
||||
cases = relationship('Cases', secondary="case_tags", back_populates='tags', viewonly=True)
|
||||
|
||||
def __init__(self, tag_title):
|
||||
self.id = None
|
||||
self.tag_title = tag_title
|
||||
self.tag_creation_date = datetime.datetime.now()
|
||||
|
||||
def save(self):
|
||||
existing_tag = self.get_by_title(self.tag_title)
|
||||
if existing_tag is not None:
|
||||
return existing_tag
|
||||
else:
|
||||
db.session.add(self)
|
||||
db.session.commit()
|
||||
return self
|
||||
|
||||
@classmethod
|
||||
def get_by_title(cls, tag_title):
|
||||
return cls.query.filter_by(tag_title=tag_title).first()
|
||||
|
||||
|
||||
class TaskAssignee(db.Model):
|
||||
__tablename__ = "task_assignee"
|
||||
|
||||
id = Column(BigInteger, primary_key=True, nullable=False)
|
||||
user_id = Column(BigInteger, ForeignKey('user.id'), nullable=False)
|
||||
task_id = Column(BigInteger, ForeignKey('case_tasks.id'), nullable=False)
|
||||
|
||||
user = relationship('User')
|
||||
task = relationship('CaseTasks')
|
||||
|
||||
UniqueConstraint('user_id', 'task_id')
|
||||
|
||||
|
||||
class GlobalTasks(db.Model):
|
||||
__tablename__ = 'global_tasks'
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
task_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"), nullable=False)
|
||||
task_title = Column(Text)
|
||||
task_description = Column(Text)
|
||||
task_tags = Column(Text)
|
||||
task_open_date = Column(DateTime)
|
||||
task_close_date = Column(DateTime)
|
||||
task_last_update = Column(DateTime)
|
||||
task_userid_open = Column(ForeignKey('user.id'))
|
||||
task_userid_close = Column(ForeignKey('user.id'))
|
||||
task_userid_update = Column(ForeignKey('user.id'))
|
||||
task_assignee_id = Column(ForeignKey('user.id'), nullable=True)
|
||||
task_status_id = Column(ForeignKey('task_status.id'))
|
||||
|
||||
user_open = relationship('User', foreign_keys=[task_userid_open])
|
||||
user_close = relationship('User', foreign_keys=[task_userid_close])
|
||||
user_update = relationship('User', foreign_keys=[task_userid_update])
|
||||
user_assigned = relationship('User', foreign_keys=[task_assignee_id])
|
||||
status = relationship('TaskStatus', foreign_keys=[task_status_id])
|
||||
|
||||
|
||||
class UserActivity(db.Model):
|
||||
__tablename__ = "user_activity"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
user_id = Column(ForeignKey('user.id'), nullable=True)
|
||||
case_id = Column(ForeignKey('cases.case_id'), nullable=True)
|
||||
activity_date = Column(DateTime)
|
||||
activity_desc = Column(Text)
|
||||
user_input = Column(Boolean, default=False)
|
||||
is_from_api = Column(Boolean, default=False)
|
||||
display_in_ui = Column(Boolean, default=True)
|
||||
|
||||
user = relationship('User')
|
||||
case = relationship('Cases')
|
||||
|
||||
|
||||
class ServerSettings(db.Model):
|
||||
__table_name__ = "server_settings"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
https_proxy = Column(Text)
|
||||
http_proxy = Column(Text)
|
||||
prevent_post_mod_repush = Column(Boolean)
|
||||
prevent_post_objects_repush = Column(Boolean, default=False)
|
||||
has_updates_available = Column(Boolean)
|
||||
enable_updates_check = Column(Boolean)
|
||||
password_policy_min_length = Column(Integer)
|
||||
password_policy_upper_case = Column(Boolean)
|
||||
password_policy_lower_case = Column(Boolean)
|
||||
password_policy_digit = Column(Boolean)
|
||||
password_policy_special_chars = Column(Text)
|
||||
|
||||
|
||||
class Comments(db.Model):
|
||||
__tablename__ = "comments"
|
||||
|
||||
comment_id = Column(BigInteger, primary_key=True)
|
||||
comment_uuid = Column(UUID(as_uuid=True), default=uuid.uuid4, server_default=text("gen_random_uuid()"),
|
||||
nullable=False)
|
||||
comment_text = Column(Text)
|
||||
comment_date = Column(DateTime)
|
||||
comment_update_date = Column(DateTime)
|
||||
comment_user_id = Column(ForeignKey('user.id'))
|
||||
comment_case_id = Column(ForeignKey('cases.case_id'))
|
||||
comment_alert_id = Column(ForeignKey('alerts.alert_id'))
|
||||
|
||||
user = relationship('User')
|
||||
case = relationship('Cases')
|
||||
alert = relationship('Alert')
|
||||
|
||||
|
||||
class EventComments(db.Model):
|
||||
__tablename__ = "event_comments"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
comment_id = Column(ForeignKey('comments.comment_id'))
|
||||
comment_event_id = Column(ForeignKey('cases_events.event_id'))
|
||||
|
||||
event = relationship('CasesEvent')
|
||||
comment = relationship('Comments')
|
||||
|
||||
|
||||
class TaskComments(db.Model):
|
||||
__tablename__ = "task_comments"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
comment_id = Column(ForeignKey('comments.comment_id'))
|
||||
comment_task_id = Column(ForeignKey('case_tasks.id'))
|
||||
|
||||
task = relationship('CaseTasks')
|
||||
comment = relationship('Comments')
|
||||
|
||||
|
||||
class IocComments(db.Model):
|
||||
__tablename__ = "ioc_comments"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
comment_id = Column(ForeignKey('comments.comment_id'))
|
||||
comment_ioc_id = Column(ForeignKey('ioc.ioc_id'))
|
||||
|
||||
ioc = relationship('Ioc')
|
||||
comment = relationship('Comments')
|
||||
|
||||
|
||||
class AssetComments(db.Model):
|
||||
__tablename__ = "asset_comments"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
comment_id = Column(ForeignKey('comments.comment_id'))
|
||||
comment_asset_id = Column(ForeignKey('case_assets.asset_id'))
|
||||
|
||||
asset = relationship('CaseAssets')
|
||||
comment = relationship('Comments')
|
||||
|
||||
|
||||
class EvidencesComments(db.Model):
|
||||
__tablename__ = "evidence_comments"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
comment_id = Column(ForeignKey('comments.comment_id'))
|
||||
comment_evidence_id = Column(ForeignKey('case_received_file.id'))
|
||||
|
||||
evidence = relationship('CaseReceivedFile')
|
||||
comment = relationship('Comments')
|
||||
|
||||
|
||||
class NotesComments(db.Model):
|
||||
__tablename__ = "note_comments"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
comment_id = Column(ForeignKey('comments.comment_id'))
|
||||
comment_note_id = Column(ForeignKey('notes.note_id'))
|
||||
|
||||
note = relationship('Notes')
|
||||
comment = relationship('Comments')
|
||||
|
||||
|
||||
class IrisModule(db.Model):
|
||||
__tablename__ = "iris_module"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
added_by_id = Column(ForeignKey('user.id'), nullable=False)
|
||||
module_human_name = Column(Text)
|
||||
module_name = Column(Text)
|
||||
module_description = Column(Text)
|
||||
module_version = Column(Text)
|
||||
interface_version = Column(Text)
|
||||
date_added = Column(DateTime)
|
||||
is_active = Column(Boolean)
|
||||
has_pipeline = Column(Boolean)
|
||||
pipeline_args = Column(JSON)
|
||||
module_config = Column(JSON)
|
||||
module_type = Column(Text)
|
||||
|
||||
user = relationship('User')
|
||||
|
||||
|
||||
class IrisHook(db.Model):
|
||||
__tablename__ = "iris_hooks"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
hook_name = Column(Text)
|
||||
hook_description = Column(Text)
|
||||
|
||||
|
||||
class IrisModuleHook(db.Model):
|
||||
__tablename__ = "iris_module_hooks"
|
||||
|
||||
id = Column(BigInteger, primary_key=True)
|
||||
module_id = Column(ForeignKey('iris_module.id'), nullable=False)
|
||||
hook_id = Column(ForeignKey('iris_hooks.id'), nullable=False)
|
||||
is_manual_hook = Column(Boolean)
|
||||
manual_hook_ui_name = Column(Text)
|
||||
retry_on_fail = Column(Boolean)
|
||||
max_retry = Column(Integer)
|
||||
run_asynchronously = Column(Boolean)
|
||||
wait_till_return = Column(Boolean)
|
||||
|
||||
module = relationship('IrisModule')
|
||||
hook = relationship('IrisHook')
|
||||
|
||||
|
||||
class IrisReport(db.Model):
|
||||
__tablename__ = 'iris_reports'
|
||||
|
||||
report_id = Column(db.Integer, Sequence("iris_reports_id_seq"), primary_key=True)
|
||||
case_id = Column(ForeignKey('cases.case_id'), nullable=False)
|
||||
report_title = Column(String(155))
|
||||
report_date = Column(DateTime)
|
||||
report_content = Column('report_content', JSON)
|
||||
user_id = Column(ForeignKey('user.id'))
|
||||
|
||||
user = relationship('User')
|
||||
case = relationship('Cases')
|
||||
|
||||
def __init__(self, case_id, report_title, report_date, report_content, user_id):
|
||||
self.case_id = case_id
|
||||
self.report_title = report_title
|
||||
self.report_date = report_date
|
||||
self.report_content = report_content
|
||||
self.user_id = user_id
|
||||
|
||||
def save(self):
|
||||
# Create an engine and a session because this method
|
||||
# will be called from Celery thread and might cause
|
||||
# error if it uses the session context of the app
|
||||
engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'])
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
||||
|
||||
# inject self into db session
|
||||
session.add(self)
|
||||
|
||||
# commit change and save the object
|
||||
session.commit()
|
||||
|
||||
# Close session
|
||||
session.close()
|
||||
|
||||
# Dispose engine
|
||||
engine.dispose()
|
||||
|
||||
return self
|
||||
|
||||
|
||||
class SavedFilter(db.Model):
|
||||
__tablename__ = 'saved_filters'
|
||||
|
||||
filter_id = Column(BigInteger, primary_key=True)
|
||||
created_by = Column(ForeignKey('user.id'), nullable=False)
|
||||
filter_name = Column(Text, nullable=False)
|
||||
filter_description = Column(Text)
|
||||
filter_data = Column(JSON, nullable=False)
|
||||
filter_is_private = Column(Boolean, nullable=False)
|
||||
filter_type = Column(Text, nullable=False)
|
||||
|
||||
user = relationship('User', foreign_keys=[created_by])
|
||||
|
||||
|
||||
class ReviewStatus(db.Model):
|
||||
__tablename__ = 'review_status'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
status_name = Column(Text, nullable=False)
|
||||
|
||||
|
||||
class CeleryTaskMeta(db.Model):
|
||||
__bind_key__ = 'iris_tasks'
|
||||
__tablename__ = 'celery_taskmeta'
|
||||
|
||||
id = Column(BigInteger, Sequence('task_id_sequence'), primary_key=True)
|
||||
task_id = Column(String(155))
|
||||
status = Column(String(50))
|
||||
result = Column(LargeBinary)
|
||||
date_done = Column(DateTime)
|
||||
traceback = Column(Text)
|
||||
name = Column(String(155))
|
||||
args = Column(LargeBinary)
|
||||
kwargs = Column(LargeBinary)
|
||||
worker = Column(String(155))
|
||||
retries = Column(Integer)
|
||||
queue = Column(String(155))
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.id) + ' - ' + str(self.user)
|
||||
|
||||
|
||||
def create_safe_attr(session, attribute_display_name, attribute_description, attribute_for, attribute_content):
|
||||
cat = CustomAttribute.query.filter(
|
||||
CustomAttribute.attribute_display_name == attribute_display_name,
|
||||
CustomAttribute.attribute_description == attribute_description,
|
||||
CustomAttribute.attribute_for == attribute_for
|
||||
).first()
|
||||
|
||||
if cat:
|
||||
return False
|
||||
else:
|
||||
instance = CustomAttribute()
|
||||
instance.attribute_display_name = attribute_display_name
|
||||
instance.attribute_description = attribute_description
|
||||
instance.attribute_for = attribute_for
|
||||
instance.attribute_content = attribute_content
|
||||
session.add(instance)
|
||||
session.commit()
|
||||
return True
|
||||
|
||||
|
Reference in New Issue
Block a user