#!/usr/bin/env bats # Behavioral tests for firewall-setup.sh # Reference: PRD FR-004 setup() { export TEST_TMPDIR=$(mktemp -d) } teardown() { rm -rf "$TEST_TMPDIR" } # ============================================================================= # parse_wg_endpoint - PRD FR-004 # ============================================================================= @test "parse_wg_endpoint extracts endpoint from valid config" { source /workspace/src/firewall-setup.sh cat >"$TEST_TMPDIR/wg0.conf" <<'EOF' [Interface] PrivateKey = test123 Address = 10.0.0.2/24 [Peer] PublicKey = peer123 Endpoint = 203.0.113.1:51820 AllowedIPs = 0.0.0.0/0 EOF run parse_wg_endpoint "$TEST_TMPDIR/wg0.conf" [ "$status" -eq 0 ] [ "$output" = "203.0.113.1:51820" ] } @test "parse_wg_endpoint fails when config missing" { source /workspace/src/firewall-setup.sh run parse_wg_endpoint "$TEST_TMPDIR/nonexistent.conf" [ "$status" -ne 0 ] } @test "parse_wg_endpoint fails when no Endpoint line" { source /workspace/src/firewall-setup.sh cat >"$TEST_TMPDIR/wg0.conf" <<'EOF' [Interface] PrivateKey = test123 EOF run parse_wg_endpoint "$TEST_TMPDIR/wg0.conf" [ "$status" -ne 0 ] } # ============================================================================= # generate_nftables_rules - PRD FR-004 # ============================================================================= @test "generate_nftables_rules produces valid nftables config" { source /workspace/src/firewall-setup.sh run generate_nftables_rules "203.0.113.1:51820" [ "$status" -eq 0 ] echo "$output" | grep -q "flush ruleset" echo "$output" | grep -q "table inet filter" } @test "Firewall input chain has DROP policy" { source /workspace/src/firewall-setup.sh result=$(generate_nftables_rules "203.0.113.1:51820") echo "$result" | grep -q "type filter hook input priority 0; policy drop" } @test "Firewall forward chain has DROP policy" { source /workspace/src/firewall-setup.sh result=$(generate_nftables_rules "203.0.113.1:51820") echo "$result" | grep -q "type filter hook forward priority 0; policy drop" } @test "Firewall output chain has DROP policy" { source /workspace/src/firewall-setup.sh result=$(generate_nftables_rules "203.0.113.1:51820") echo "$result" | grep -q "type filter hook output priority 0; policy drop" } @test "Firewall allows loopback traffic" { source /workspace/src/firewall-setup.sh result=$(generate_nftables_rules "203.0.113.1:51820") echo "$result" | grep -q "iif lo accept" echo "$result" | grep -q "oif lo accept" } @test "Firewall allows WireGuard traffic to specific endpoint" { source /workspace/src/firewall-setup.sh result=$(generate_nftables_rules "203.0.113.1:51820") echo "$result" | grep -q "203.0.113.1" echo "$result" | grep -q "51820" } @test "Firewall blocks outbound ICMP ping (reduced attack surface)" { source /workspace/src/firewall-setup.sh result=$(generate_nftables_rules "203.0.113.1:51820") echo "$result" | grep -q "destination-unreachable" ! echo "$result" | grep -q "echo-request accept" } @test "generate_nftables_rules extracts IP and port correctly" { source /workspace/src/firewall-setup.sh result=$(generate_nftables_rules "10.20.30.40:12345") echo "$result" | grep -q "10.20.30.40" echo "$result" | grep -q "12345" } # ============================================================================= # Script Structure # ============================================================================= @test "firewall-setup.sh uses strict mode" { head -5 /workspace/src/firewall-setup.sh | grep -q "set -euo pipefail" } @test "firewall-setup.sh is executable" { [ -x "/workspace/src/firewall-setup.sh" ] } @test "firewall-setup.sh has valid bash syntax" { run bash -n /workspace/src/firewall-setup.sh [ "$status" -eq 0 ] } @test "firewall-setup.sh runs main when executed directly" { grep -q 'BASH_SOURCE\[0\]' /workspace/src/firewall-setup.sh }