worked poc
This commit is contained in:
+33
-2
@@ -10,6 +10,7 @@ from .policy import PolicyEngine
|
||||
from .routeros import RouterOSClient
|
||||
from .state import RuntimeStats
|
||||
from .store import AlertStore
|
||||
from .tuning import AlertTuner
|
||||
|
||||
|
||||
class EVEWatcher(threading.Thread):
|
||||
@@ -17,20 +18,25 @@ class EVEWatcher(threading.Thread):
|
||||
self,
|
||||
path: str,
|
||||
store: AlertStore,
|
||||
tuner: AlertTuner,
|
||||
policy: PolicyEngine,
|
||||
routeros: RouterOSClient,
|
||||
block_timeout: str,
|
||||
dedup_window_seconds: int,
|
||||
stats: RuntimeStats,
|
||||
stop_event: threading.Event,
|
||||
) -> None:
|
||||
super().__init__(name="eve-watcher", daemon=True)
|
||||
self.path = path
|
||||
self.store = store
|
||||
self.tuner = tuner
|
||||
self.policy = policy
|
||||
self.routeros = routeros
|
||||
self.block_timeout = block_timeout
|
||||
self.dedup_window_seconds = max(0, int(dedup_window_seconds))
|
||||
self.stats = stats
|
||||
self.stop_event = stop_event
|
||||
self._initial_seek_done = False
|
||||
|
||||
def run(self) -> None:
|
||||
while not self.stop_event.is_set():
|
||||
@@ -45,7 +51,12 @@ class EVEWatcher(threading.Thread):
|
||||
|
||||
def _follow_file(self) -> None:
|
||||
with open(self.path, "r", encoding="utf-8", errors="replace") as handle:
|
||||
handle.seek(0, os.SEEK_END)
|
||||
# Ignore historical EVE only on the first attach. After rotation or
|
||||
# truncation read the replacement file from byte 0 so alerts that
|
||||
# arrived during the hand-off are not skipped.
|
||||
if not self._initial_seek_done:
|
||||
handle.seek(0, os.SEEK_END)
|
||||
self._initial_seek_done = True
|
||||
inode = os.fstat(handle.fileno()).st_ino
|
||||
print(f"[eve] following {self.path}", flush=True)
|
||||
|
||||
@@ -71,11 +82,31 @@ class EVEWatcher(threading.Thread):
|
||||
return
|
||||
|
||||
self.stats.inc("eve_events")
|
||||
if event.get("event_type") != "alert":
|
||||
event_type = event.get("event_type")
|
||||
if event_type == "stats":
|
||||
raw_stats = event.get("stats")
|
||||
if isinstance(raw_stats, dict):
|
||||
self.stats.update_suricata(raw_stats, str(event.get("timestamp") or ""))
|
||||
return
|
||||
if event_type != "alert":
|
||||
return
|
||||
|
||||
self.stats.inc("eve_alerts")
|
||||
self.stats.stamp("last_alert_at")
|
||||
|
||||
tuning = self.tuner.evaluate(event)
|
||||
if not tuning.keep:
|
||||
self.stats.inc("alerts_filtered")
|
||||
key = f"alerts_filtered_{tuning.reason}"
|
||||
self.stats.inc(key)
|
||||
return
|
||||
|
||||
duplicate_id = self.store.find_recent_duplicate(event, self.dedup_window_seconds)
|
||||
if duplicate_id is not None:
|
||||
self.store.bump_duplicate(duplicate_id, event)
|
||||
self.stats.inc("alerts_deduplicated")
|
||||
return
|
||||
|
||||
decision = self.policy.evaluate(event)
|
||||
blocked = False
|
||||
reason = decision.reason
|
||||
|
||||
Reference in New Issue
Block a user