Nessuna descrizione

db.py 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. from __future__ import annotations
  2. from contextlib import contextmanager
  3. import psycopg
  4. from psycopg.rows import dict_row
  5. from app.config import settings
  6. def db_dsn() -> str:
  7. return (
  8. f"host={settings.soc_integrator_db_host} "
  9. f"port={settings.soc_integrator_db_port} "
  10. f"dbname={settings.soc_integrator_db_name} "
  11. f"user={settings.soc_integrator_db_user} "
  12. f"password={settings.soc_integrator_db_password}"
  13. )
  14. @contextmanager
  15. def get_conn():
  16. with psycopg.connect(db_dsn(), row_factory=dict_row, autocommit=True) as conn:
  17. yield conn
  18. def init_schema() -> None:
  19. with get_conn() as conn, conn.cursor() as cur:
  20. cur.execute(
  21. """
  22. CREATE TABLE IF NOT EXISTS incident_index (
  23. incident_key TEXT PRIMARY KEY,
  24. iris_case_id TEXT,
  25. status TEXT NOT NULL,
  26. severity TEXT NOT NULL,
  27. first_seen TIMESTAMPTZ NOT NULL,
  28. last_seen TIMESTAMPTZ NOT NULL
  29. );
  30. """
  31. )
  32. cur.execute(
  33. """
  34. CREATE TABLE IF NOT EXISTS incident_events (
  35. id BIGSERIAL PRIMARY KEY,
  36. incident_key TEXT NOT NULL REFERENCES incident_index(incident_key) ON DELETE CASCADE,
  37. event_id TEXT,
  38. source TEXT NOT NULL,
  39. event_type TEXT NOT NULL,
  40. raw_payload JSONB NOT NULL,
  41. decision_trace JSONB NOT NULL,
  42. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  43. );
  44. """
  45. )
  46. cur.execute(
  47. """
  48. CREATE TABLE IF NOT EXISTS escalation_audit (
  49. id BIGSERIAL PRIMARY KEY,
  50. incident_key TEXT NOT NULL REFERENCES incident_index(incident_key) ON DELETE CASCADE,
  51. attempted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  52. status_code INT,
  53. success BOOLEAN NOT NULL,
  54. response_excerpt TEXT
  55. );
  56. """
  57. )
  58. cur.execute(
  59. """
  60. CREATE TABLE IF NOT EXISTS policy_config (
  61. id INT PRIMARY KEY,
  62. data JSONB NOT NULL,
  63. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  64. );
  65. """
  66. )
  67. cur.execute(
  68. """
  69. CREATE TABLE IF NOT EXISTS ioc_trace (
  70. id BIGSERIAL PRIMARY KEY,
  71. action TEXT NOT NULL,
  72. ioc_type TEXT NOT NULL,
  73. ioc_value TEXT NOT NULL,
  74. providers JSONB NOT NULL,
  75. request_payload JSONB NOT NULL,
  76. response_payload JSONB NOT NULL,
  77. matched BOOLEAN,
  78. severity TEXT,
  79. confidence DOUBLE PRECISION,
  80. error TEXT,
  81. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  82. );
  83. """
  84. )
  85. cur.execute(
  86. """
  87. CREATE TABLE IF NOT EXISTS correlation_state (
  88. entity_key TEXT PRIMARY KEY,
  89. state JSONB NOT NULL,
  90. updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  91. );
  92. """
  93. )
  94. cur.execute(
  95. """
  96. CREATE TABLE IF NOT EXISTS c_detection_events (
  97. id BIGSERIAL PRIMARY KEY,
  98. usecase_id TEXT NOT NULL,
  99. entity TEXT NOT NULL,
  100. severity TEXT NOT NULL,
  101. evidence JSONB NOT NULL,
  102. event_ref JSONB NOT NULL,
  103. incident_key TEXT,
  104. matched_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  105. );
  106. """
  107. )
  108. cur.execute(
  109. "CREATE INDEX IF NOT EXISTS idx_incident_events_incident_key_created_at ON incident_events(incident_key, created_at DESC);"
  110. )
  111. cur.execute(
  112. "CREATE INDEX IF NOT EXISTS idx_incident_events_source_event_id ON incident_events(source, event_id);"
  113. )
  114. cur.execute(
  115. "CREATE INDEX IF NOT EXISTS idx_escalation_audit_incident_key_attempted_at ON escalation_audit(incident_key, attempted_at DESC);"
  116. )
  117. cur.execute(
  118. "CREATE INDEX IF NOT EXISTS idx_ioc_trace_created_at ON ioc_trace(created_at DESC);"
  119. )
  120. cur.execute(
  121. "CREATE INDEX IF NOT EXISTS idx_ioc_trace_type_value ON ioc_trace(ioc_type, ioc_value);"
  122. )
  123. cur.execute(
  124. "CREATE INDEX IF NOT EXISTS idx_correlation_state_updated_at ON correlation_state(updated_at DESC);"
  125. )
  126. cur.execute(
  127. "CREATE INDEX IF NOT EXISTS idx_c_detection_events_usecase_matched_at ON c_detection_events(usecase_id, matched_at DESC);"
  128. )
  129. cur.execute(
  130. "CREATE INDEX IF NOT EXISTS idx_c_detection_events_entity_matched_at ON c_detection_events(entity, matched_at DESC);"
  131. )