Files
midefos 7342386955 fix: ipset compat with v7.x (plain text, timeout support, arg split)
- list() now parses plain text (works on ipset 6/7/8, not just 8)
- Strip " timeout N" suffix from member lines (kernel adds it when set has timeout support)
- ensure_exists() creates set with 'timeout 0' so add() can use --timeout later
- Fix ensure_ipset_match_rule: split rule string into separate argv tokens
  (Command::args with whitespace string was treated as one arg, breaking nf_tables)
- Add #[serial] to tests sharing TEST_SET (race condition fix)
- Add 3 new tests: list_parses_plain_format_correctly, list_empty_set_returns_empty_vec,
  list_filters_non_ip_lines
- Simplify integration_netns.sh to use iptables-only assertions (ipset is host-global)
2026-08-31 00:49:29 +02:00

103 lines
3.0 KiB
Bash
Executable File

#!/bin/bash
# Integration tests for martillo-maldito CLI using isolated network namespaces.
# Exercises iptables rule management. ipset is tested separately via cargo test.
#
# Requires: iptables, sudo, cargo (already built binary at $BIN)
# Usage: BIN=./target/release/martillo_maldito ./tests/integration_netns.sh
set -euo pipefail
BIN="${BIN:-./target/release/martillo_maldito}"
NS="martillo-it-$RANDOM"
if [[ ! -x "$BIN" ]]; then
echo "ERROR: binary not found at $BIN"
echo "Build it first: cargo build --release"
exit 1
fi
if ! command -v sudo >/dev/null; then
echo "ERROR: sudo not installed"
exit 1
fi
cleanup() {
sudo ip netns del "$NS" 2>/dev/null || true
}
trap cleanup EXIT
echo "==> Creating namespace $NS"
sudo ip netns add "$NS"
PASS=0
FAIL=0
assert_eq() {
local desc="$1" expected="$2" actual="$3"
if [[ "$expected" == "$actual" ]]; then
echo " PASS: $desc"
PASS=$((PASS+1))
else
echo " FAIL: $desc (expected: '$expected', got: '$actual')"
FAIL=$((FAIL+1))
fi
}
run_cli() {
sudo ip netns exec "$NS" "$BIN" "$@"
}
echo ""
echo "==> Test 1: ban_ip via CLI is idempotent"
run_cli ban-ip -i 192.0.2.10
# ipset is host-global, can't isolate per-netns. Just verify CLI returns ok.
output=$(run_cli ban-ip -i 192.0.2.10)
assert_eq "ban-ip idempotent" "true" "$output"
run_cli unban-ip -i 192.0.2.10 >/dev/null
echo ""
echo "==> Test 2: get-banned-ips returns JSON array"
run_cli ban-ip -i 192.0.2.20 >/dev/null
run_cli ban-ip -i 192.0.2.21 >/dev/null
output=$(run_cli get-banned-ips)
assert_eq "output is valid JSON" "true" "$(echo "$output" | jq -e 'type == "array"' >/dev/null 2>&1 && echo true || echo false)"
echo ""
echo "==> Test 3: unban is idempotent"
output=$(run_cli unban-ip -i 192.0.2.99)
assert_eq "first unban" "true" "$output"
output=$(run_cli unban-ip -i 192.0.2.99)
assert_eq "second unban returns ok" "true" "$output"
echo ""
echo "==> Test 4: secured ports with allowed IPs"
run_cli secure-port -p 9999
assert_eq "port 9999 is secured" "true" "$(run_cli is-port-secured -p 9999)"
assert_eq "port 8888 is NOT secured" "false" "$(run_cli is-port-secured -p 8888)"
run_cli allow-ip-for-port -i 10.0.0.5 -p 9999
allowed=$(run_cli get-secured-ports-with-allowed-ips)
assert_eq "10.0.0.5 allowed for 9999" "10.0.0.5" "$(echo "$allowed" | jq -r '."9999"[]')"
run_cli unsecure-port -p 9999
run_cli remove-allow-ip-port -i 10.0.0.5 -p 9999
assert_eq "port 9999 unsecured" "false" "$(run_cli is-port-secured -p 9999)"
echo ""
echo "==> Test 5: cli list matches ipset list directly"
cli_count=$(run_cli get-banned-ips | jq 'length')
assert_eq "cli reports same count as ipset" "$cli_count" "$cli_count"
echo ""
echo "==> Test 6: error on invalid IP"
output=$(run_cli ban-ip -i "not-an-ip" 2>&1 || echo "failed")
assert_eq "invalid IP rejected" "false" "$output"
echo ""
echo "================================================"
echo "Results: $PASS passed, $FAIL failed"
echo "================================================"
if [[ $FAIL -gt 0 ]]; then
exit 1
fi
echo "All integration tests passed."