Files
npm-scanner/dev/testbed/check.sh
T
2026-10-25 20:46:32 +01:00

100 lines
4.6 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# npm-scanner – automated testbed checks (run as root next to docker-compose.yaml)
#
# ./check.sh prepare create the simulated NPM log directories (before `docker compose up`)
# ./check.sh run all checks against the running testbed
# ./check.sh cleanup unban the test addresses
#
# Test addresses are from the documentation ranges (RFC 5737) and never route anywhere.
set -uo pipefail
cd "$(dirname "$0")"
C=npm-scanner-testbed
F=./fake-npm-logs.sh
pass=0 fail=0
ok() { echo " ok $*"; pass=$((pass + 1)); }
bad() { echo " FAIL $*"; fail=$((fail + 1)); }
f2b() { docker exec "$C" fail2ban-client "$@"; }
banned() { f2b get "$1" banip 2>/dev/null | tr ' ' '\n' | grep -qx "$2"; }
wait_ban() { # jail ip [seconds]
for _ in $(seq 1 "${3:-15}"); do banned "$1" "$2" && return 0; sleep 1; done
return 1
}
if [[ "${1:-}" == "prepare" ]]; then
mkdir -p npm-logs/log npm-logs/logs data
touch npm-logs/log/proxy-host-1_access.log npm-logs/log/default-host_access.log
echo "prepared: npm-logs/log, npm-logs/logs, data"
exit 0
fi
if [[ "${1:-}" == "cleanup" ]]; then
for ip in 198.51.100.77 198.51.100.78 198.51.100.79 198.51.100.80 192.0.2.10 198.51.100.81 198.51.100.82; do
f2b unban "$ip" >/dev/null 2>&1 || true
done
echo "test addresses unbanned"
exit 0
fi
echo "== 1. container"
state=$(docker inspect -f '{{.State.Health.Status}}' "$C" 2>/dev/null)
[[ "$state" == healthy ]] && ok "health: $state" || bad "health: ${state:-not running}"
jails=$(f2b status | sed -n 's/.*Jail list:\s*//p')
[[ "$jails" == *npm-scanner* ]] && ok "jails: $jails" || bad "npm-scanner jail missing ($jails)"
[[ "$jails" == *npm-wplogin* ]] && ok "npm-wplogin active" || bad "npm-wplogin missing (ENABLE_WPLOGIN=true?)"
docker exec "$C" test -f /usr/share/npm-scanner/filter-tests.passed && ok "filter tests passed in build" || bad "filter test marker missing"
echo "== 2. scanner ban (log/, host 1)"
$F scan 198.51.100.77 3 1 log >/dev/null
wait_ban npm-scanner 198.51.100.77 && ok "198.51.100.77 banned" || bad "198.51.100.77 not banned"
iptables -S DOCKER-USER | grep -q -- '-j f2b-npm-scan' && ok "DOCKER-USER jumps to f2b-npm-scan" || bad "no jump in DOCKER-USER"
iptables -S f2b-npm-scan 2>/dev/null | grep -q '198.51.100.77' && ok "rule for 198.51.100.77 on the host" || bad "no host rule for 198.51.100.77"
echo "== 3. new host in second directory (logs/, host 40) -> watcher"
$F newhost 40 logs >/dev/null
sleep 6
f2b get npm-scanner logpath | grep -q '/logs/npm2/proxy-host-40_access.log' && ok "host 40 watched after reload" || bad "host 40 not watched"
docker logs "$C" 2>&1 | grep -q 'proxy-host-40_access.log – npm-scanner reloaded' && ok "watcher logged the reload" || bad "no watcher message"
banned npm-scanner 198.51.100.77 && ok "ban survived the reload" || bad "ban lost after reload"
$F scan 198.51.100.78 3 40 logs >/dev/null
wait_ban npm-scanner 198.51.100.78 && ok "198.51.100.78 banned from host 40" || bad "198.51.100.78 not banned"
echo "== 4. default host 444"
$F fallback 198.51.100.79 3 >/dev/null
wait_ban npm-scanner 198.51.100.79 && ok "198.51.100.79 banned (444)" || bad "198.51.100.79 not banned"
echo "== 5. wp-login brute force"
$F wplogin 198.51.100.80 5 1 log >/dev/null
wait_ban npm-wplogin 198.51.100.80 && ok "198.51.100.80 banned by npm-wplogin" || bad "198.51.100.80 not banned"
echo "== 6. must NOT ban"
$F scan 192.0.2.10 5 1 log >/dev/null
$F harmless 198.51.100.81 10 1 log >/dev/null
$F scan 198.51.100.82 2 1 log >/dev/null
sleep 5
banned npm-scanner 192.0.2.10 && bad "whitelisted 192.0.2.10 banned" || ok "whitelisted 192.0.2.10 not banned"
banned npm-scanner 198.51.100.81 && bad "harmless 198.51.100.81 banned" || ok "harmless 404/200 not banned"
banned npm-scanner 198.51.100.82 && bad "198.51.100.82 banned after 2 hits" || ok "2 hits below maxretry"
echo "== 7. restart keeps bans"
docker restart "$C" >/dev/null
for _ in $(seq 1 30); do f2b ping >/dev/null 2>&1 && break; sleep 1; done
sleep 3
banned npm-scanner 198.51.100.77 && ok "198.51.100.77 restored after restart" || bad "bans lost after restart"
iptables -S f2b-npm-scan 2>/dev/null | grep -q '198.51.100.77' && ok "host rule restored" || bad "host rule missing after restart"
echo "== 8. stop removes the rules"
docker stop "$C" >/dev/null
if iptables -S 2>/dev/null | grep -q 'f2b-npm-'; then bad "f2b-npm-* rules left after stop"; else ok "no f2b-npm-* rules after stop"; fi
docker start "$C" >/dev/null
for _ in $(seq 1 30); do f2b ping >/dev/null 2>&1 && break; sleep 1; done
sleep 3
banned npm-scanner 198.51.100.77 && ok "bans back after start" || bad "bans missing after start"
echo
echo "result: $pass ok, $fail failed"
[[ $fail -eq 0 ]]