Skip to content

Commit 98df1fd

Browse files
authored
Merge pull request #239 from MISP/do-not-store-events-sql
refactor: do not store events/attributes/objects in sql, use opensearch
2 parents 8d0dd53 + 086198c commit 98df1fd

77 files changed

Lines changed: 2406 additions & 2767 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ Example:
209209
```
210210
from app.worker import tasks
211211
212-
tasks.handle_created_attribute.delay(pulled_attribute.id, pulled_attribute.object_id, pulled_attribute.event_id)
212+
tasks.handle_created_attribute.delay(pulled_attribute.id, pulled_attribute.object_uuid, pulled_attribute.event_uuid)
213213
```
214214

215215
If you add a new task, you have to restart the celery `worker` container, otherwise you will get `NotRegistered('app.worker.tasks.new_task') ` exception.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"""detach object_references FK constraints to events and objects
2+
3+
These are the last DB-level FK constraints that reference the events and objects
4+
tables from an external table, blocking their eventual removal.
5+
6+
Revision ID: c8d7e6f5a4b3
7+
Revises: f3e2d1c0b9a8
8+
Create Date: 2026-03-25 00:00:00.000000
9+
10+
"""
11+
12+
from alembic import op
13+
14+
# revision identifiers, used by Alembic.
15+
revision = "c8d7e6f5a4b3"
16+
down_revision = "f3e2d1c0b9a8"
17+
branch_labels = None
18+
depends_on = None
19+
20+
21+
def upgrade():
22+
op.drop_constraint(
23+
"object_references_event_id_fkey", "object_references", type_="foreignkey"
24+
)
25+
op.drop_constraint(
26+
"object_references_object_id_fkey", "object_references", type_="foreignkey"
27+
)
28+
29+
30+
def downgrade():
31+
op.create_foreign_key(
32+
"object_references_event_id_fkey",
33+
"object_references",
34+
"events",
35+
["event_id"],
36+
["id"],
37+
)
38+
op.create_foreign_key(
39+
"object_references_object_id_fkey",
40+
"object_references",
41+
"objects",
42+
["object_id"],
43+
["id"],
44+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""remove event_id columns from attributes and objects tables
2+
3+
Revision ID: d4e5f6a7b8c9
4+
Revises: c8d7e6f5a4b3
5+
Create Date: 2026-03-25 00:00:00.000000
6+
7+
"""
8+
9+
from alembic import op
10+
11+
revision = "d4e5f6a7b8c9"
12+
down_revision = "c8d7e6f5a4b3"
13+
branch_labels = None
14+
depends_on = None
15+
16+
17+
def upgrade():
18+
op.drop_index("ix_attributes_event_id", table_name="attributes", if_exists=True)
19+
op.drop_column("attributes", "event_id")
20+
op.drop_index("ix_objects_event_id", table_name="objects", if_exists=True)
21+
op.drop_column("objects", "event_id")
22+
23+
24+
def downgrade():
25+
import sqlalchemy as sa
26+
27+
op.add_column("objects", sa.Column("event_id", sa.Integer(), nullable=True))
28+
op.create_index("ix_objects_event_id", "objects", ["event_id"])
29+
op.add_column("attributes", sa.Column("event_id", sa.Integer(), nullable=True))
30+
op.create_index("ix_attributes_event_id", "attributes", ["event_id"])
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""drop events table and migrate feeds.event_id to uuid string
2+
3+
Revision ID: e1a2b3c4d5f6
4+
Revises: d4e5f6a7b8c9
5+
Create Date: 2026-03-26 00:00:00.000000
6+
7+
"""
8+
9+
import sqlalchemy as sa
10+
from alembic import op
11+
from sqlalchemy.dialects import postgresql
12+
13+
revision = "e1a2b3c4d5f6"
14+
down_revision = "d4e5f6a7b8c9"
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# Replace event_id (INTEGER) with event_uuid (VARCHAR) in object_references
21+
op.drop_column("object_references", "event_id")
22+
op.add_column("object_references", sa.Column("event_uuid", postgresql.UUID(as_uuid=True), nullable=True))
23+
24+
# Replace event_id (INTEGER) with event_uuid (VARCHAR) in event_tags and attribute_tags
25+
op.drop_column("event_tags", "event_id")
26+
op.add_column("event_tags", sa.Column("event_uuid", postgresql.UUID(as_uuid=True), nullable=True))
27+
op.drop_column("attribute_tags", "event_id")
28+
op.add_column("attribute_tags", sa.Column("event_uuid", postgresql.UUID(as_uuid=True), nullable=True))
29+
30+
# Rename feeds.event_id (INTEGER) to feeds.event_uuid (VARCHAR for UUID string)
31+
op.drop_column("feeds", "event_id")
32+
op.add_column("feeds", sa.Column("event_uuid", postgresql.UUID(as_uuid=True), nullable=True))
33+
34+
# Drop the events table (all FK constraints were removed in prior migrations)
35+
op.drop_table("events")
36+
37+
38+
def downgrade():
39+
# Recreate events table (minimal schema for rollback)
40+
op.create_table(
41+
"events",
42+
sa.Column("id", sa.Integer(), nullable=False, autoincrement=True),
43+
sa.Column("org_id", sa.Integer(), nullable=False),
44+
sa.Column("date", sa.Date(), nullable=False),
45+
sa.Column("info", sa.String(), nullable=True),
46+
sa.Column("user_id", sa.Integer(), nullable=False),
47+
sa.Column("uuid", postgresql.UUID(as_uuid=True), nullable=True),
48+
sa.Column("published", sa.Boolean(), nullable=False, server_default="false"),
49+
sa.Column("attribute_count", sa.Integer(), nullable=True),
50+
sa.Column("object_count", sa.Integer(), nullable=True),
51+
sa.Column("orgc_id", sa.Integer(), nullable=False),
52+
sa.Column("timestamp", sa.Integer(), nullable=False, server_default="0"),
53+
sa.Column("sharing_group_id", sa.Integer(), nullable=True),
54+
sa.Column("proposal_email_lock", sa.Boolean(), nullable=False, server_default="false"),
55+
sa.Column("locked", sa.Boolean(), nullable=False, server_default="false"),
56+
sa.Column("publish_timestamp", sa.Integer(), nullable=False, server_default="0"),
57+
sa.Column("sighting_timestamp", sa.Integer(), nullable=True),
58+
sa.Column("disable_correlation", sa.Boolean(), nullable=True),
59+
sa.Column("extends_uuid", postgresql.UUID(as_uuid=True), nullable=True),
60+
sa.Column("protected", sa.Boolean(), nullable=False, server_default="false"),
61+
sa.Column("deleted", sa.Boolean(), nullable=False, server_default="false"),
62+
sa.PrimaryKeyConstraint("id"),
63+
)
64+
65+
# Revert feeds.event_uuid back to event_id INTEGER
66+
op.drop_column("feeds", "event_uuid")
67+
op.add_column("feeds", sa.Column("event_id", sa.Integer(), nullable=True))
68+
69+
# Revert object_references, event_tags, attribute_tags
70+
op.drop_column("object_references", "event_uuid")
71+
op.add_column("object_references", sa.Column("event_id", sa.Integer(), nullable=False))
72+
op.drop_column("event_tags", "event_uuid")
73+
op.add_column("event_tags", sa.Column("event_id", sa.Integer(), nullable=True))
74+
op.drop_column("attribute_tags", "event_uuid")
75+
op.add_column("attribute_tags", sa.Column("event_id", sa.Integer(), nullable=True))
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""detach event/attribute FK constraints from event_tags and attribute_tags
2+
3+
These FK constraints block dropping the events and attributes tables.
4+
The tag junction tables will remain, referencing only the tags table.
5+
6+
Revision ID: f3e2d1c0b9a8
7+
Revises: a1b2c3d4e5f6
8+
Create Date: 2026-03-25 00:00:00.000000
9+
10+
"""
11+
12+
from alembic import op
13+
14+
# revision identifiers, used by Alembic.
15+
revision = "f3e2d1c0b9a8"
16+
down_revision = "a1b2c3d4e5f6"
17+
branch_labels = None
18+
depends_on = None
19+
20+
21+
def upgrade():
22+
op.drop_constraint(
23+
"event_tags_event_id_fkey", "event_tags", type_="foreignkey"
24+
)
25+
op.drop_constraint(
26+
"attribute_tags_attribute_id_fkey", "attribute_tags", type_="foreignkey"
27+
)
28+
op.drop_constraint(
29+
"attribute_tags_event_id_fkey", "attribute_tags", type_="foreignkey"
30+
)
31+
# Allow NULLs now that FK constraints are removed (events/attributes may not exist in SQL)
32+
op.alter_column("event_tags", "event_id", nullable=True)
33+
op.alter_column("attribute_tags", "event_id", nullable=True)
34+
op.alter_column("attribute_tags", "attribute_id", nullable=True)
35+
36+
37+
def downgrade():
38+
op.alter_column("attribute_tags", "attribute_id", nullable=False)
39+
op.alter_column("attribute_tags", "event_id", nullable=False)
40+
op.alter_column("event_tags", "event_id", nullable=False)
41+
op.create_foreign_key(
42+
"event_tags_event_id_fkey",
43+
"event_tags",
44+
"events",
45+
["event_id"],
46+
["id"],
47+
)
48+
op.create_foreign_key(
49+
"attribute_tags_attribute_id_fkey",
50+
"attribute_tags",
51+
"attributes",
52+
["attribute_id"],
53+
["id"],
54+
)
55+
op.create_foreign_key(
56+
"attribute_tags_event_id_fkey",
57+
"attribute_tags",
58+
"events",
59+
["event_id"],
60+
["id"],
61+
)

api/app/models/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
from app.models.attribute import Attribute # noqa
2-
from app.models.event import Event # noqa
31
from app.models.hunt import Hunt # noqa
42
from app.models.module import ModuleSettings # noqa
5-
from app.models.object import Object # noqa
6-
from app.models.object_reference import ObjectReference # noqa
73
from app.models.organisation import Organisation # noqa
84
from app.models.role import Role # noqa
95
from app.models.server import Server # noqa
@@ -12,7 +8,7 @@
128
SharingGroupOrganisation,
139
SharingGroupServer,
1410
)
15-
from app.models.tag import AttributeTag, EventTag, Tag # noqa
11+
from app.models.tag import Tag # noqa
1612
from app.models.user import User # noqa
1713

1814
# fixes: sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class AAA->bbb, expression 'XXXX' failed to locate a name ('XXXX'). If this is a class name, consider adding this relationship() to the <class 'app.models.bbb.AAAA'> class after both dependent classes have been defined.

api/app/models/attribute.py

Lines changed: 0 additions & 86 deletions
This file was deleted.

0 commit comments

Comments
 (0)