feat: write timestamped blocklist change reports on firewall sync

This commit is contained in:
zwitschi committed 2026-08-06 14:31:15 +02:00
1 parent 48c5629b4b
commit 80a67635de
4 files changed
+110 -3

No files matched your search

+35 -2
View File
@@ -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,
)