Files

137 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -u
PASS=0
WARN=0
FAIL=0
ok(){ printf "[PASS] %s\n" "$*"; PASS=$((PASS+1)); }
warn(){ printf "[WARN] %s\n" "$*"; WARN=$((WARN+1)); }
fail(){ printf "[FAIL] %s\n" "$*"; FAIL=$((FAIL+1)); }
if [[ ${EUID:-$(id -u)} -ne 0 ]]; then
exec sudo bash "$0" "$@"
fi
TEST_DISCORD=0
[[ "${1:-}" == "--test-discord" ]] && TEST_DISCORD=1
printf "malware-watch verification | host=%s | time=%s\n\n" "$(hostname)" "$(date -Is)"
for f in \
/etc/malware-watch/config \
/usr/local/sbin/malware-watch.py \
/usr/local/sbin/malware-quarantine.py \
/usr/local/sbin/malware-feed-update.py \
/usr/local/sbin/clamav-watch-scan.sh \
/usr/local/sbin/block-malware-iocs; do
if [[ -f "$f" ]]; then ok "file exists: $f"; else fail "missing file: $f"; fi
done
if [[ -f /etc/malware-watch/config ]]; then
mode=$(stat -c %a /etc/malware-watch/config 2>/dev/null || true)
[[ "$mode" == "600" ]] && ok "config permissions are 600" || warn "config permissions are $mode (expected 600)"
if grep -q '^DISCORD_WEBHOOK=' /etc/malware-watch/config && grep -q '^ABUSECH_AUTH_KEY=' /etc/malware-watch/config; then
ok "Discord webhook and abuse.ch key entries exist"
else
fail "Discord webhook or abuse.ch key entry is missing"
fi
fi
for t in malware-watch.timer malware-feed-update.timer; do
if systemctl is-enabled "$t" >/dev/null 2>&1 && systemctl is-active "$t" >/dev/null 2>&1; then
ok "$t is enabled and active"
else
fail "$t is not enabled/active"
fi
done
if systemctl is-enabled block-malware-iocs.service >/dev/null 2>&1 && systemctl is-active block-malware-iocs.service >/dev/null 2>&1; then
ok "block-malware-iocs.service is enabled and active"
else
fail "block-malware-iocs.service is not enabled/active"
fi
TF=/var/lib/malware-watch/feeds/threatfox.json
MB=/var/lib/malware-watch/feeds/malwarebazaar.json
if [[ -s "$TF" ]]; then
n=$(python3 - "$TF" <<'PY'
import json,sys
try:
d=json.load(open(sys.argv[1])); print(len(d.get("iocs",{})))
except Exception: print(-1)
PY
)
[[ "$n" =~ ^[0-9]+$ ]] && (( n > 0 )) && ok "ThreatFox feed loaded: $n IOCs" || warn "ThreatFox feed exists but contains no parsed IOCs"
else
fail "ThreatFox feed missing/empty"
fi
if [[ -s "$MB" ]]; then
n=$(python3 - "$MB" <<'PY'
import json,sys
try:
d=json.load(open(sys.argv[1])); print(len(d.get("hashes",{})))
except Exception: print(-1)
PY
)
[[ "$n" =~ ^[0-9]+$ ]] && (( n > 0 )) && ok "MalwareBazaar feed loaded: $n hashes" || warn "MalwareBazaar feed exists but contains no parsed hashes"
else
fail "MalwareBazaar feed missing/empty"
fi
if [[ -x /usr/local/bin/clamscan ]]; then
ok "ClamAV installed: $(/usr/local/bin/clamscan --version 2>/dev/null | head -n1)"
if id -u clamav >/dev/null 2>&1; then ok "clamav service account exists"; else fail "clamav service account is missing"; fi
if compgen -G '/var/lib/clamav/*.cvd' >/dev/null || compgen -G '/var/lib/clamav/*.cld' >/dev/null; then
ok "ClamAV signature database exists"
else
warn "ClamAV signature DB is not ready yet; freshclam timer may still need to download it"
fi
for t in clamav-freshclam-local.timer clamav-risk-scan.timer clamav-deep-scan.timer; do
if systemctl is-enabled "$t" >/dev/null 2>&1 && systemctl is-active "$t" >/dev/null 2>&1; then
ok "$t is enabled and active"
else
fail "$t is not enabled/active"
fi
done
else
warn "ClamAV is not installed (INSTALL_CLAMAV may have been disabled)"
fi
if [[ -x /usr/local/sbin/malware-watch.py ]]; then
out=$(/usr/local/sbin/malware-watch.py 2>&1); rc=$?
if (( rc == 0 )); then
ok "malware-watch one-shot execution succeeded: $out"
else
fail "malware-watch one-shot execution failed (rc=$rc): $out"
fi
fi
if (( TEST_DISCORD )); then
if [[ -r /etc/malware-watch/config ]]; then
set -a
. /etc/malware-watch/config
set +a
payload=$(python3 - <<'PY'
import json,socket
print(json.dumps({"content":f"malware-watch verify OK | server: {socket.gethostname()}"},ensure_ascii=False))
PY
)
code=$(curl -sS -o /tmp/malware-watch-discord-verify.out -w '%{http_code}' \
-A 'Mozilla/5.0 (compatible; malware-watch/verify)' \
-H 'Content-Type: application/json' --data "$payload" "$DISCORD_WEBHOOK" || true)
if [[ "$code" == "204" || "$code" == "200" ]]; then
ok "Discord webhook test succeeded (HTTP $code)"
else
fail "Discord webhook test failed (HTTP ${code:-000})"
fi
rm -f /tmp/malware-watch-discord-verify.out
else
fail "cannot test Discord: config unavailable"
fi
fi
printf "\nSummary: PASS=%d WARN=%d FAIL=%d\n" "$PASS" "$WARN" "$FAIL"
(( FAIL == 0 ))