feat(detmir): add rust-first operations tooling
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
Description=Run AWatch DLP CEF Exporter every 5 minutes
|
||||
|
||||
[Timer]
|
||||
OnBootSec=2min
|
||||
OnUnitActiveSec=5min
|
||||
OnCalendar=*:6/10:30
|
||||
AccuracySec=30s
|
||||
RandomizedDelaySec=30s
|
||||
Unit=aw-dlp-cef-exporter.service
|
||||
Persistent=true
|
||||
Persistent=false
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
Description=Run AWatch DLP syslog forwarder every 3 minutes
|
||||
|
||||
[Timer]
|
||||
OnBootSec=3min
|
||||
OnUnitActiveSec=3min
|
||||
Persistent=true
|
||||
OnCalendar=*:7/10:40
|
||||
AccuracySec=30s
|
||||
RandomizedDelaySec=30s
|
||||
Persistent=false
|
||||
Unit=aw-dlp-syslog-forwarder.service
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -57,7 +57,7 @@ def iter_new_incidents(aw_base: str, state: dict[str, Any], per_bucket_limit: in
|
||||
for bid in bucket_ids:
|
||||
try:
|
||||
events = http_json(f"{aw_base}/buckets/{bid}/events?limit={int(per_bucket_limit)}")
|
||||
except error.HTTPError as exc:
|
||||
except (TimeoutError, OSError, error.URLError, error.HTTPError) as exc:
|
||||
LOG.warning("skip bucket %s: %s", bid, exc)
|
||||
continue
|
||||
prev = int(last_ids.get(bid, 0))
|
||||
@@ -126,7 +126,11 @@ def main() -> None:
|
||||
app_name = str(cfg.get("app_name", "aw-dlp"))
|
||||
|
||||
state = load_json(state_path)
|
||||
incidents, max_ids = iter_new_incidents(aw_base=aw_base, state=state, per_bucket_limit=per_bucket_limit)
|
||||
try:
|
||||
incidents, max_ids = iter_new_incidents(aw_base=aw_base, state=state, per_bucket_limit=per_bucket_limit)
|
||||
except (TimeoutError, OSError, error.URLError, error.HTTPError) as exc:
|
||||
LOG.warning("skip syslog forwarder run: AW API unavailable: %s", exc)
|
||||
return
|
||||
|
||||
sent = 0
|
||||
for event in incidents:
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
MODULE_PATH = Path(__file__).with_name("syslog_forwarder.py")
|
||||
SPEC = importlib.util.spec_from_file_location("syslog_forwarder", MODULE_PATH)
|
||||
MODULE = importlib.util.module_from_spec(SPEC)
|
||||
sys.modules[SPEC.name] = MODULE
|
||||
SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
def test_iter_new_incidents_skips_timed_out_bucket(monkeypatch):
|
||||
def fake_http_json(url, timeout=15):
|
||||
if url.endswith("/buckets/"):
|
||||
return {"aw-dlp-incidents_SHARKON2025": {}}
|
||||
raise TimeoutError("timed out")
|
||||
|
||||
monkeypatch.setattr(MODULE, "http_json", fake_http_json)
|
||||
|
||||
incidents, max_ids = MODULE.iter_new_incidents(
|
||||
aw_base="http://127.0.0.1:5600/api/0",
|
||||
state={"last_ids": {"aw-dlp-incidents_SHARKON2025": 42}},
|
||||
per_bucket_limit=300,
|
||||
)
|
||||
|
||||
assert incidents == []
|
||||
assert max_ids == {}
|
||||
|
||||
|
||||
def test_main_skips_aw_api_timeout_without_overwriting_state(monkeypatch, tmp_path):
|
||||
state_path = tmp_path / "syslog-forwarder-state.json"
|
||||
original_state = {"last_ids": {"aw-dlp-incidents_SHARKON2025": 99}}
|
||||
state_path.write_text(json.dumps(original_state), encoding="utf-8")
|
||||
|
||||
monkeypatch.setattr(
|
||||
MODULE,
|
||||
"load_yaml",
|
||||
lambda path: {
|
||||
"aw_api_base": "http://127.0.0.1:5600/api/0",
|
||||
"state_path": str(state_path),
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
MODULE,
|
||||
"iter_new_incidents",
|
||||
lambda aw_base, state, per_bucket_limit: (_ for _ in ()).throw(TimeoutError("timed out")),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
MODULE,
|
||||
"save_json",
|
||||
lambda path, payload: (_ for _ in ()).throw(AssertionError("state should not be saved on AW API timeout")),
|
||||
)
|
||||
|
||||
MODULE.main()
|
||||
|
||||
assert json.loads(state_path.read_text(encoding="utf-8")) == original_state
|
||||
@@ -2,10 +2,11 @@
|
||||
Description=Run AWatch DLP Webhook sender every 2 minutes
|
||||
|
||||
[Timer]
|
||||
OnBootSec=90s
|
||||
OnUnitActiveSec=2min
|
||||
OnCalendar=*:8/10:45
|
||||
AccuracySec=30s
|
||||
RandomizedDelaySec=30s
|
||||
Unit=aw-dlp-webhook-sender.service
|
||||
Persistent=true
|
||||
Persistent=false
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
|
||||
Reference in New Issue
Block a user