feat: write timestamped blocklist change reports on firewall sync
This commit is contained in:
1 parent
48c5629b4b
commit
80a67635de
4 files changed
+110
-3
No files matched your search
+35
-2
@@ -8,8 +8,15 @@ and outputs a single consolidated MikroTik RouterOS blocklist.
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from .blocklist_history import (
|
||||
committed_lines,
|
||||
cumulative_blocklist,
|
||||
current_file_lines,
|
||||
write_blocklist_report,
|
||||
)
|
||||
from .constants import (
|
||||
COPYPARTY_LOG_PATH,
|
||||
COPYPARTY_REPORT_DIR,
|
||||
@@ -70,6 +77,7 @@ class ScanResult:
|
||||
blocklist_v6_path: str | None = None
|
||||
firewall_connected: bool = False
|
||||
firewall_changes: dict | None = None
|
||||
blocklist_report_path: str | None = None
|
||||
errors: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
@@ -173,12 +181,22 @@ def run_scan(params: ScanParams) -> ScanResult:
|
||||
print(f"Total target blocks/subnets: {len(final_blocked_targets)}")
|
||||
|
||||
# --- Step 6: write consolidated blocklists to reports/app/data ----------
|
||||
blocklist_v4_path, blocklist_v6_path = write_blocklist_files(
|
||||
blocked_ipv4, blocked_ipv6, params.report_dir)
|
||||
# Capture the previous blocklist state BEFORE the files are overwritten so
|
||||
# the change report can compute the complete-set delta.
|
||||
app_data_dir = os.path.join(params.report_dir, "app", "data")
|
||||
blocklist_v4_path = os.path.join(app_data_dir, "blocklist_ipv4.txt")
|
||||
blocklist_v6_path = os.path.join(app_data_dir, "blocklist_ipv6.txt")
|
||||
prev_v4 = current_file_lines(blocklist_v4_path)
|
||||
prev_v6 = current_file_lines(blocklist_v6_path)
|
||||
history_v4 = committed_lines(blocklist_v4_path)
|
||||
history_v6 = committed_lines(blocklist_v6_path)
|
||||
|
||||
write_blocklist_files(blocked_ipv4, blocked_ipv6, params.report_dir)
|
||||
print(f"blocklist files:\n {blocklist_v4_path}\n {blocklist_v6_path}")
|
||||
|
||||
# --- Steps 5+7: compare current state with candidates and apply ---------
|
||||
firewall_changes: dict | None = None
|
||||
blocklist_report_path: str | None = None
|
||||
if firewall is not None:
|
||||
try:
|
||||
firewall_changes = firewall.sync_blocklist(
|
||||
@@ -192,6 +210,20 @@ def run_scan(params: ScanParams) -> ScanResult:
|
||||
f"remove {len(firewall_changes['removed_ipv4'])} IPv4 and "
|
||||
f"{len(firewall_changes['removed_ipv6'])} IPv6 addresses.")
|
||||
|
||||
# Timestamped change report — only when the router was reachable.
|
||||
complete_v4, complete_v6 = cumulative_blocklist(
|
||||
blocklist_v4_path, blocklist_v6_path,
|
||||
blocked_ipv4, blocked_ipv6)
|
||||
blocklist_report_path = write_blocklist_report(
|
||||
params.report_dir,
|
||||
history_v4=history_v4, history_v6=history_v6,
|
||||
prev_v4=prev_v4, prev_v6=prev_v6,
|
||||
complete_v4=complete_v4, complete_v6=complete_v6,
|
||||
firewall_changes=firewall_changes,
|
||||
dry_run=params.dry_run,
|
||||
errors=errors)
|
||||
print(f"blocklist report: {blocklist_report_path}")
|
||||
|
||||
return ScanResult(
|
||||
ok=True,
|
||||
cp_exists=cp_exists,
|
||||
@@ -206,6 +238,7 @@ def run_scan(params: ScanParams) -> ScanResult:
|
||||
blocklist_v6_path=blocklist_v6_path,
|
||||
firewall_connected=firewall is not None,
|
||||
firewall_changes=firewall_changes,
|
||||
blocklist_report_path=blocklist_report_path,
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
|
||||
Reference in new issue
Block a user