mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-28 21:17:36 +00:00
fix(annuaire): threatmesh-bridge reads cscli itself (heredoc/stdin clash) — 0.3.2 (ref #768)
Some checks are pending
License Headers / check (push) Waiting to run
Some checks are pending
License Headers / check (push) Waiting to run
This commit is contained in:
parent
dfa0a778c2
commit
fd47aa99b6
|
|
@ -1,4 +1,4 @@
|
|||
secubox-annuaire (0.3.1-1~bookworm1) bookworm; urgency=medium
|
||||
secubox-annuaire (0.3.2-1~bookworm1) bookworm; urgency=medium
|
||||
|
||||
* feat(#768): threatmesh WAF hook — crowdsec -> mesh bridge.
|
||||
/usr/sbin/sbx-threatmesh-bridge reads local `cscli decisions list` and
|
||||
|
|
|
|||
|
|
@ -2,16 +2,14 @@
|
|||
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
|
||||
# SecuBox-Deb :: sbx-threatmesh-bridge (#768)
|
||||
# Federate this node's LOCAL crowdsec ban decisions into the gondwana threatmesh
|
||||
# so every peer enforces them too. Reads `cscli decisions list`, publishes each
|
||||
# NEW ban via `annuairectl ban` (TTL = the crowdsec duration, so it auto-expires
|
||||
# in the mesh in step). Idempotent via a small state file; safe no-op without
|
||||
# crowdsec or annuairectl. This is the WAF -> mesh hook: detect once, block fleet.
|
||||
# so every peer enforces them too. Publishes each NEW ban via `annuairectl ban`
|
||||
# (TTL = the crowdsec duration; reason = the scenario), idempotent via a state
|
||||
# file. Safe no-op without crowdsec/annuairectl. WAF hook: detect once, block fleet.
|
||||
set -euo pipefail
|
||||
command -v cscli >/dev/null 2>&1 || exit 0
|
||||
command -v annuairectl >/dev/null 2>&1 || exit 0
|
||||
STATE=/var/lib/secubox/annuaire/threatmesh-bridge.json
|
||||
|
||||
cscli decisions list -o json 2>/dev/null | python3 - "$STATE" <<'PY'
|
||||
python3 - /var/lib/secubox/annuaire/threatmesh-bridge.json <<'PY'
|
||||
import json, os, re, subprocess, sys, time
|
||||
state_path = sys.argv[1]
|
||||
try:
|
||||
|
|
@ -26,8 +24,10 @@ def dur_to_s(d):
|
|||
return sum(int(n) * mult[u] for n, u in re.findall(r"(\d+)([hms])", d or "")) or 3600
|
||||
|
||||
try:
|
||||
data = json.load(sys.stdin) or []
|
||||
except Exception:
|
||||
out = subprocess.check_output(["cscli", "decisions", "list", "-o", "json"], timeout=15)
|
||||
data = json.loads(out or b"[]") or []
|
||||
except Exception as e:
|
||||
print("threatmesh-bridge: cscli read failed:", e)
|
||||
sys.exit(0)
|
||||
|
||||
published = 0
|
||||
|
|
@ -39,12 +39,11 @@ for alert in data:
|
|||
if not ip or ip in state:
|
||||
continue
|
||||
ttl = dur_to_s(dec.get("duration"))
|
||||
reason = "crowdsec:" + (dec.get("scenario") or "").split("/")[-1]
|
||||
reason = ("crowdsec:" + (dec.get("scenario") or "").split("/")[-1])[:64]
|
||||
r = subprocess.run(["annuairectl", "ban", ip, "--ttl", str(ttl),
|
||||
"--reason", reason[:64], "--severity", "high"],
|
||||
capture_output=True)
|
||||
"--reason", reason, "--severity", "high"], capture_output=True)
|
||||
if r.returncode == 0:
|
||||
state[ip] = now + ttl * 0.9 # refresh a little before expiry
|
||||
state[ip] = now + ttl * 0.9
|
||||
published += 1
|
||||
|
||||
os.makedirs(os.path.dirname(state_path), exist_ok=True)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user