feat: Implement comprehensive tests and fixes for Coraza WAF integration
- Add unit tests for WAF ruleset selection priority and handler validation in config_waf_test.go. - Enhance manager.go to sanitize ruleset names, preventing path traversal vulnerabilities. - Introduce debug logging for WAF configuration state in manager.go to aid troubleshooting. - Create integration tests to verify WAF handler presence and ruleset sanitization in manager_additional_test.go. - Update coraza_integration.sh to include verification steps for WAF configuration and improved error handling. - Document the Coraza WAF integration fix plan, detailing root cause analysis and implementation tasks.
This commit is contained in:
+107
-11
@@ -8,12 +8,98 @@ set -euo pipefail
|
||||
# 3. Wait for API to be ready and then configure a ruleset that blocks a simple signature
|
||||
# 4. Request a path containing the signature and verify 403 (or WAF block response)
|
||||
|
||||
echo "Starting Coraza integration test..."
|
||||
|
||||
# Ensure we operate from repo root
|
||||
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# ============================================================================
|
||||
# Helper Functions
|
||||
# ============================================================================
|
||||
|
||||
# Verifies WAF handler is present in Caddy config with correct ruleset
|
||||
verify_waf_config() {
|
||||
local expected_ruleset="${1:-integration-xss}"
|
||||
local retries=10
|
||||
local wait=3
|
||||
|
||||
echo "Verifying WAF config (expecting ruleset: ${expected_ruleset})..."
|
||||
|
||||
for i in $(seq 1 $retries); do
|
||||
# Fetch Caddy config via admin API
|
||||
local caddy_config
|
||||
caddy_config=$(curl -s http://localhost:2019/config 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$caddy_config" ]; then
|
||||
echo " Attempt $i/$retries: Caddy admin API not responding, retrying..."
|
||||
sleep $wait
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check for WAF handler
|
||||
if echo "$caddy_config" | grep -q '"handler":"waf"'; then
|
||||
echo " ✓ WAF handler found in Caddy config"
|
||||
|
||||
# Also verify the directives include our ruleset
|
||||
if echo "$caddy_config" | grep -q "$expected_ruleset"; then
|
||||
echo " ✓ Ruleset '${expected_ruleset}' found in directives"
|
||||
return 0
|
||||
else
|
||||
echo " ⚠ WAF handler present but ruleset '${expected_ruleset}' not found in directives"
|
||||
fi
|
||||
else
|
||||
echo " Attempt $i/$retries: WAF handler not found, waiting..."
|
||||
fi
|
||||
|
||||
sleep $wait
|
||||
done
|
||||
|
||||
echo " ✗ WAF handler verification failed after $retries attempts"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Dumps debug information on failure
|
||||
on_failure() {
|
||||
local exit_code=$?
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo "=== FAILURE DEBUG INFO (exit code: $exit_code) ==="
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
|
||||
echo "=== Charon API Logs (last 150 lines) ==="
|
||||
docker logs charon-debug 2>&1 | tail -150 || echo "Could not retrieve container logs"
|
||||
echo ""
|
||||
|
||||
echo "=== Caddy Admin API Config ==="
|
||||
curl -s http://localhost:2019/config 2>/dev/null | head -300 || echo "Could not retrieve Caddy config"
|
||||
echo ""
|
||||
|
||||
echo "=== Ruleset Files in Container ==="
|
||||
docker exec charon-debug sh -c 'ls -la /app/data/caddy/coraza/rulesets/ 2>/dev/null' || echo "No rulesets directory found"
|
||||
echo ""
|
||||
|
||||
echo "=== Ruleset File Contents ==="
|
||||
docker exec charon-debug sh -c 'cat /app/data/caddy/coraza/rulesets/*.conf 2>/dev/null' || echo "No ruleset files found"
|
||||
echo ""
|
||||
|
||||
echo "=== Security Config in API ==="
|
||||
curl -s http://localhost:8080/api/v1/security/config 2>/dev/null || echo "Could not retrieve security config"
|
||||
echo ""
|
||||
|
||||
echo "=== Proxy Hosts ==="
|
||||
curl -s http://localhost:8080/api/v1/proxy-hosts 2>/dev/null | head -50 || echo "Could not retrieve proxy hosts"
|
||||
echo ""
|
||||
|
||||
echo "=============================================="
|
||||
echo "=== END DEBUG INFO ==="
|
||||
echo "=============================================="
|
||||
}
|
||||
|
||||
# Set up trap to dump debug info on any error
|
||||
trap on_failure ERR
|
||||
|
||||
echo "Starting Coraza integration test..."
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "docker is not available; aborting"
|
||||
exit 1
|
||||
@@ -99,18 +185,26 @@ echo "Enable WAF globally and set ruleset source to integration-xss..."
|
||||
SEC_CFG_PAYLOAD='{"name":"default","enabled":true,"waf_mode":"block","waf_rules_source":"integration-xss","admin_whitelist":"0.0.0.0/0"}'
|
||||
curl -s -X POST -H "Content-Type: application/json" -d "${SEC_CFG_PAYLOAD}" -b ${TMP_COOKIE} http://localhost:8080/api/v1/security/config
|
||||
|
||||
echo "Waiting for Caddy to apply WAF configuration..."
|
||||
sleep 3
|
||||
|
||||
# Verify WAF handler is properly configured before proceeding
|
||||
if ! verify_waf_config "integration-xss"; then
|
||||
echo "ERROR: WAF configuration verification failed - aborting test"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Apply rules and test payload..."
|
||||
# create minimal proxy host if needed; omitted here for brevity; test will target local Caddy root
|
||||
|
||||
echo "Dumping Caddy config routes to verify waf handler and rules_files..."
|
||||
curl -s http://localhost:2019/config | grep -n "waf" || true
|
||||
curl -s http://localhost:2019/config | grep -n "integration-xss" || true
|
||||
echo "Verifying Caddy config has WAF handler..."
|
||||
curl -s http://localhost:2019/config | grep -E '"handler":"waf"' || echo "WARNING: WAF handler not found in initial config check"
|
||||
|
||||
echo "Inspecting ruleset file inside container..."
|
||||
docker exec charon-debug sh -c 'cat /app/data/caddy/coraza/rulesets/integration-xss-*.conf' || true
|
||||
docker exec charon-debug sh -c 'cat /app/data/caddy/coraza/rulesets/integration-xss-*.conf' || echo "WARNING: Could not read ruleset file"
|
||||
|
||||
echo "Recent caddy logs (may contain plugin errors):"
|
||||
docker logs charon-debug | tail -n 200 || true
|
||||
echo ""
|
||||
echo "=== Testing BLOCK mode ==="
|
||||
|
||||
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -d "<script>alert(1)</script>" -H "Host: integration.local" http://localhost/post)
|
||||
if [ "$RESPONSE" = "403" ]; then
|
||||
@@ -129,6 +223,11 @@ curl -s -X POST -H "Content-Type: application/json" -d "${SEC_CFG_MONITOR}" -b $
|
||||
echo "Wait for Caddy to apply monitor mode config..."
|
||||
sleep 5
|
||||
|
||||
# Verify WAF handler is still present after mode switch
|
||||
if ! verify_waf_config "integration-xss"; then
|
||||
echo "WARNING: WAF config verification failed after mode switch, proceeding anyway..."
|
||||
fi
|
||||
|
||||
echo "Inspecting ruleset file (should now have DetectionOnly)..."
|
||||
docker exec charon-debug sh -c 'cat /app/data/caddy/coraza/rulesets/integration-xss-*.conf | head -5' || true
|
||||
|
||||
@@ -141,9 +240,6 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== All Coraza integration tests passed ==="
|
||||
|
||||
echo ""
|
||||
echo "=== All Coraza integration tests passed ==="
|
||||
echo "Cleaning up..."
|
||||
|
||||
Reference in New Issue
Block a user