init
This commit is contained in:
291
results/scripts/run-pmi-tests.sh
Normal file
291
results/scripts/run-pmi-tests.sh
Normal file
@@ -0,0 +1,291 @@
|
||||
#!/bin/bash
|
||||
set -uo pipefail
|
||||
|
||||
NGINX_A="http://172.28.0.2"
|
||||
NGINX_D="http://172.29.0.2"
|
||||
HTTPS="https://172.28.0.2"
|
||||
TLS_HOST="172.28.0.2:443"
|
||||
ALLOWED_IF="172.28.0.20"
|
||||
DENIED_IF="172.29.0.20"
|
||||
SSL="/ssl"
|
||||
REPORT="${REPORT:-/reports/pmi.log}"
|
||||
AUTH_MODE="/auth-mode/mode"
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
SKIP=0
|
||||
|
||||
log() { echo "$@" | tee -a "$REPORT"; }
|
||||
|
||||
pass() { log "PASS #$1 $2"; PASS=$((PASS + 1)); }
|
||||
fail() { log "FAIL #$1 $2"; FAIL=$((FAIL + 1)); }
|
||||
skip() { log "SKIP #$1 $2"; SKIP=$((SKIP + 1)); }
|
||||
|
||||
http_code() {
|
||||
local iface="$1" url="$2"
|
||||
shift 2
|
||||
curl -s -o /dev/null -w '%{http_code}' --interface "$iface" --connect-timeout 10 "$url" "$@"
|
||||
}
|
||||
|
||||
set_auth_mode() {
|
||||
echo "$1" > "$AUTH_MODE"
|
||||
sleep 0.5
|
||||
}
|
||||
|
||||
: > "$REPORT"
|
||||
log "=== PMI tests $(date -Iseconds) ==="
|
||||
log ""
|
||||
|
||||
# --- 1. IP allow/deny ---
|
||||
c1=$(http_code "$ALLOWED_IF" "$NGINX_A/admin/")
|
||||
c2=$(http_code "$DENIED_IF" "$NGINX_D/admin/")
|
||||
if [ "$c1" = "200" ] && [ "$c2" = "403" ]; then
|
||||
pass 1 "IP allow/deny (allowed=$c1 denied=$c2)"
|
||||
else
|
||||
fail 1 "IP allow/deny (allowed=$c1 denied=$c2, expected 200/403)"
|
||||
fi
|
||||
|
||||
# --- 2. Basic auth ---
|
||||
c_no=$(http_code "$ALLOWED_IF" "$NGINX_A/secure/")
|
||||
c_wrong=$(http_code "$ALLOWED_IF" "$NGINX_A/secure/" -u 'wrong:wrong')
|
||||
c_ok=$(http_code "$ALLOWED_IF" "$NGINX_A/secure/" -u 'user:password')
|
||||
if [ "$c_no" = "401" ] && [ "$c_wrong" = "401" ] && [ "$c_ok" = "200" ]; then
|
||||
pass 2 "Basic auth (401/401/200)"
|
||||
else
|
||||
fail 2 "Basic auth ($c_no/$c_wrong/$c_ok expected 401/401/200)"
|
||||
fi
|
||||
|
||||
# --- 3. mTLS ---
|
||||
c3_no=$(curl -sk -o /dev/null -w '%{http_code}' --interface "$ALLOWED_IF" \
|
||||
--resolve nginx-test-mtls:443:172.28.0.2 https://nginx-test-mtls/)
|
||||
c3_ok=$(curl -sk -o /dev/null -w '%{http_code}' --interface "$ALLOWED_IF" \
|
||||
--resolve nginx-test-mtls:443:172.28.0.2 --cert "$SSL/client.crt" --key "$SSL/client.key" --cacert "$SSL/ca.crt" \
|
||||
https://nginx-test-mtls/)
|
||||
c3_bad=$(curl -sk -o /dev/null -w '%{http_code}' --interface "$ALLOWED_IF" \
|
||||
--resolve nginx-test-mtls:443:172.28.0.2 --cert "$SSL/untrusted.crt" --key "$SSL/untrusted.key" --cacert "$SSL/ca.crt" \
|
||||
https://nginx-test-mtls/)
|
||||
if [ "$c3_no" = "400" ] && [ "$c3_ok" = "200" ] && [ "$c3_bad" = "400" ]; then
|
||||
pass 3 "Client TLS certificate (400/200/400)"
|
||||
else
|
||||
fail 3 "Client TLS certificate ($c3_no/$c3_ok/$c3_bad expected 400/200/400)"
|
||||
fi
|
||||
|
||||
# --- 4. auth_request ---
|
||||
set_auth_mode 200
|
||||
c4a=$(http_code "$ALLOWED_IF" "$NGINX_A/auth-protected/status")
|
||||
set_auth_mode 401
|
||||
c4b=$(http_code "$ALLOWED_IF" "$NGINX_A/auth-protected/status")
|
||||
set_auth_mode 403
|
||||
c4c=$(http_code "$ALLOWED_IF" "$NGINX_A/auth-protected/status")
|
||||
set_auth_mode 200
|
||||
if [ "$c4a" = "200" ] && [ "$c4b" = "401" ] && [ "$c4c" = "403" ]; then
|
||||
pass 4 "auth_request (200/401/403)"
|
||||
else
|
||||
fail 4 "auth_request ($c4a/$c4b/$c4c expected 200/401/403)"
|
||||
fi
|
||||
|
||||
# --- 5. satisfy all ---
|
||||
c5a=$(http_code "$ALLOWED_IF" "$NGINX_A/admin-combined/" -u 'user:password')
|
||||
c5b=$(http_code "$ALLOWED_IF" "$NGINX_A/admin-combined/")
|
||||
c5c=$(http_code "$DENIED_IF" "$NGINX_D/admin-combined/" -u 'user:password')
|
||||
c5d=$(http_code "$DENIED_IF" "$NGINX_D/admin-combined/")
|
||||
if [ "$c5a" = "200" ] && [ "$c5b" = "401" ] && [ "$c5c" = "403" ] && [ "$c5d" = "403" ]; then
|
||||
pass 5 "satisfy all matrix (200/401/403/403)"
|
||||
else
|
||||
fail 5 "satisfy all ($c5a/$c5b/$c5c/$c5d expected 200/401/403/403)"
|
||||
fi
|
||||
|
||||
# --- 6. URL separation ---
|
||||
c6a=$(http_code "$ALLOWED_IF" "$NGINX_A/public/index.html")
|
||||
c6b=$(http_code "$DENIED_IF" "$NGINX_D/admin/")
|
||||
if [ "$c6a" = "200" ] && [ "$c6b" = "403" ]; then
|
||||
pass 6 "URL access rules (/public/ vs /admin/)"
|
||||
else
|
||||
fail 6 "URL access ($c6a/$c6b expected 200/403)"
|
||||
fi
|
||||
|
||||
# --- 7. limit_except ---
|
||||
c7g=$(http_code "$ALLOWED_IF" "$NGINX_A/api/status" -X GET)
|
||||
c7p=$(http_code "$ALLOWED_IF" "$NGINX_A/api/status" -X POST)
|
||||
c7u=$(http_code "$ALLOWED_IF" "$NGINX_A/api/status" -X PUT)
|
||||
c7d=$(http_code "$ALLOWED_IF" "$NGINX_A/api/status" -X DELETE)
|
||||
if [ "$c7g" = "200" ] && [ "$c7p" = "200" ] && [ "$c7u" = "403" ] && [ "$c7d" = "403" ]; then
|
||||
pass 7 "limit_except GET POST (PUT/DELETE=403)"
|
||||
else
|
||||
fail 7 "limit_except ($c7g/$c7p/$c7u/$c7d expected 200/200/403/403)"
|
||||
fi
|
||||
|
||||
# --- 8. internal ---
|
||||
c8a=$(http_code "$ALLOWED_IF" "$NGINX_A/protected/document.pdf")
|
||||
c8b=$(http_code "$ALLOWED_IF" "$NGINX_A/download")
|
||||
if [ "$c8a" = "404" ] && [ "$c8b" = "200" ]; then
|
||||
pass 8 "internal location (direct=404 rewrite=200)"
|
||||
else
|
||||
fail 8 "internal ($c8a/$c8b expected 404/200)"
|
||||
fi
|
||||
|
||||
# --- 9. TLS connection ---
|
||||
s9=$(echo | openssl s_client -connect "$TLS_HOST" -servername nginx-test 2>&1 || true)
|
||||
if echo "$s9" | grep -qE "Verify return code: (0|18|19|21)|SSL-Session:"; then
|
||||
pass 9 "HTTPS TLS handshake"
|
||||
else
|
||||
fail 9 "HTTPS TLS handshake failed"
|
||||
fi
|
||||
|
||||
# --- 10. TLS versions ---
|
||||
s10ok=$(echo | openssl s_client -connect "$TLS_HOST" -servername nginx-test -tls1_2 2>&1 || true)
|
||||
s10bad=$(echo | openssl s_client -connect "$TLS_HOST" -servername nginx-test -tls1_1 2>&1 || true)
|
||||
if echo "$s10ok" | grep -q "Protocol : TLSv1.2" && echo "$s10bad" | grep -qi "alert protocol version\|no protocols available\|wrong version"; then
|
||||
pass 10 "TLSv1.2 ok, TLSv1.1 rejected"
|
||||
else
|
||||
fail 10 "TLS version policy"
|
||||
fi
|
||||
|
||||
# --- 11. HTTPS redirect + HSTS ---
|
||||
h11=$(curl -sI --interface "$ALLOWED_IF" -H "Host: redirect-test" "$NGINX_A/" | tr -d '\r')
|
||||
hsts=$(curl -skI --interface "$ALLOWED_IF" "$HTTPS/" -H "Host: nginx-test" | tr -d '\r')
|
||||
ok11=0
|
||||
echo "$h11" | grep -q "301" && ok11=$((ok11 + 1))
|
||||
echo "$h11" | grep -qi "location: https://" && ok11=$((ok11 + 1))
|
||||
echo "$hsts" | grep -qi "strict-transport-security:" && ok11=$((ok11 + 1))
|
||||
if [ "$ok11" -eq 3 ]; then
|
||||
pass 11 "HTTP redirect 301 + HSTS header"
|
||||
else
|
||||
fail 11 "Redirect/HSTS (checks $ok11/3)"
|
||||
fi
|
||||
|
||||
# --- 12-13. access/error logs (detailed check in run-pmi-log-checks.sh) ---
|
||||
curl -s --interface "$ALLOWED_IF" "$NGINX_A/test-page" > /dev/null
|
||||
curl -s --interface "$ALLOWED_IF" "$NGINX_A/another-page" > /dev/null
|
||||
curl -s --max-time 5 --interface "$ALLOWED_IF" "$NGINX_A/broken/" > /dev/null || true
|
||||
|
||||
# --- 14. syslog ---
|
||||
curl -s --interface "$ALLOWED_IF" "$NGINX_A/syslog-probe-$(date +%s)" > /dev/null || true
|
||||
ok14=0
|
||||
for _ in 1 2 3 4 5; do
|
||||
sleep 1
|
||||
if [ -f /reports/nginx-syslog.log ] && grep -q "nginx" /reports/nginx-syslog.log 2>/dev/null; then
|
||||
ok14=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$ok14" -eq 1 ]; then
|
||||
pass 14 "syslog receives nginx events"
|
||||
else
|
||||
fail 14 "syslog log missing or empty (/reports/nginx-syslog.log)"
|
||||
fi
|
||||
|
||||
# --- 15. limit_req ---
|
||||
count503=0
|
||||
count200=0
|
||||
codes15=""
|
||||
for i in $(seq 1 5); do
|
||||
c=$(http_code "$ALLOWED_IF" "$NGINX_A/rate-limit-check")
|
||||
codes15="$codes15 $c"
|
||||
[ "$c" = "503" ] && count503=$((count503 + 1))
|
||||
[ "$c" = "200" ] && count200=$((count200 + 1))
|
||||
done
|
||||
if [ "$count503" -gt 0 ] && [ "$count200" -gt 0 ]; then
|
||||
pass 15 "limit_req returns 503 ($count503) and 200 ($count200) in:$codes15"
|
||||
elif [ "$count503" -gt 0 ]; then
|
||||
pass 15 "limit_req returns 503 ($count503 of 5 in:$codes15)"
|
||||
else
|
||||
fail 15 "limit_req no 503 in:$codes15"
|
||||
fi
|
||||
|
||||
# --- 16. limit_conn ---
|
||||
pids=""
|
||||
for i in 1 2 3 4 5; do
|
||||
curl -s -o /tmp/s16_$i -w '%{http_code}' --interface "$ALLOWED_IF" --max-time 25 "$NGINX_A/slow/" > /tmp/c16_$i &
|
||||
pids="$pids $!"
|
||||
done
|
||||
for p in $pids; do wait "$p" 2>/dev/null || true; done
|
||||
codes16=$(cat /tmp/c16_* 2>/dev/null | tr '\n' ' ')
|
||||
if echo "$codes16" | grep -q "503"; then
|
||||
pass 16 "limit_conn returns 503 ($codes16)"
|
||||
else
|
||||
fail 16 "limit_conn no 503 in: $codes16"
|
||||
fi
|
||||
rm -f /tmp/c16_* /tmp/s16_* 2>/dev/null || true
|
||||
|
||||
# --- 17. client_max_body_size ---
|
||||
dd if=/dev/zero of=/tmp/pmi-small bs=1024 count=100 status=none 2>/dev/null
|
||||
dd if=/dev/zero of=/tmp/pmi-large bs=1M count=2 status=none 2>/dev/null
|
||||
c17s=$(curl -s -o /dev/null -w '%{http_code}' --interface "$ALLOWED_IF" -X POST -T /tmp/pmi-small "$NGINX_A/upload")
|
||||
c17l=$(curl -s -o /dev/null -w '%{http_code}' --interface "$ALLOWED_IF" -X POST -T /tmp/pmi-large "$NGINX_A/upload")
|
||||
if [ "$c17s" = "200" ] && [ "$c17l" = "413" ]; then
|
||||
pass 17 "client_max_body_size (small=$c17s large=$c17l)"
|
||||
else
|
||||
fail 17 "client_max_body_size ($c17s/$c17l expected 200/413)"
|
||||
fi
|
||||
|
||||
# --- 18. client_body_timeout ---
|
||||
if dd if=/dev/zero bs=1K count=800 2>/dev/null | curl -s -o /dev/null -w '%{http_code}' \
|
||||
--interface "$ALLOWED_IF" --limit-rate 1K -m 30 -X POST -d @- "$NGINX_A/upload" | grep -qv 200; then
|
||||
pass 18 "client_body_timeout (slow upload rejected/timed out)"
|
||||
else
|
||||
# curl may return 000 on timeout
|
||||
ec=$?
|
||||
if [ "$ec" -ne 0 ]; then
|
||||
pass 18 "client_body_timeout (curl exit $ec)"
|
||||
else
|
||||
fail 18 "client_body_timeout (upload unexpectedly succeeded quickly)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# --- 19. server_tokens off ---
|
||||
hdr=$(curl -sI --interface "$ALLOWED_IF" "$NGINX_A/public/index.html" | tr -d '\r')
|
||||
body=$(curl -s --interface "$ALLOWED_IF" "$NGINX_A/nonexistent-page-19")
|
||||
if echo "$hdr" | grep -i "^server: nginx$" && ! echo "$hdr" | grep -q "nginx/"; then
|
||||
if ! echo "$body" | grep -q "nginx/"; then
|
||||
pass 19 "server_tokens off"
|
||||
else
|
||||
fail 19 "server_tokens off (version in error body)"
|
||||
fi
|
||||
else
|
||||
fail 19 "server_tokens off (Server header: $(echo "$hdr" | grep -i ^server:))"
|
||||
fi
|
||||
|
||||
# --- 20. error_page ---
|
||||
b20=$(curl -s --interface "$ALLOWED_IF" "$NGINX_A/nonexistent-page-20")
|
||||
if echo "$b20" | grep -q "Custom 404"; then
|
||||
pass 20 "custom error_page 404"
|
||||
else
|
||||
fail 20 "custom error_page (body missing Custom 404)"
|
||||
fi
|
||||
|
||||
# --- 21. autoindex off ---
|
||||
c21=$(http_code "$ALLOWED_IF" "$NGINX_A/files/")
|
||||
body21=$(curl -s --interface "$ALLOWED_IF" "$NGINX_A/files/")
|
||||
if [ "$c21" = "403" ] && ! echo "$body21" | grep -qi "<title>Index of"; then
|
||||
pass 21 "autoindex off (403, no listing)"
|
||||
else
|
||||
fail 21 "autoindex ($c21, listing=$(echo "$body21" | head -1))"
|
||||
fi
|
||||
|
||||
# --- 22. proxy_pass ---
|
||||
c22=$(http_code "$ALLOWED_IF" "$NGINX_A/api/status")
|
||||
if [ "$c22" = "200" ]; then
|
||||
pass 22 "proxy_pass to backend ($c22)"
|
||||
else
|
||||
fail 22 "proxy_pass ($c22 expected 200)"
|
||||
fi
|
||||
|
||||
# --- 23. path traversal ---
|
||||
c23a=$(http_code "$ALLOWED_IF" "$NGINX_A/index.html")
|
||||
c23b=$(http_code "$ALLOWED_IF" "$NGINX_A/../../../etc/passwd")
|
||||
if [ "$c23a" = "200" ] && [ "$c23b" = "404" ]; then
|
||||
pass 23 "web root restriction ($c23a/$c23b)"
|
||||
else
|
||||
fail 23 "web root ($c23a/$c23b expected 200/404)"
|
||||
fi
|
||||
|
||||
# --- 24. FIM (run-fim-checksum.sh) ---
|
||||
|
||||
log ""
|
||||
log "=== Summary: PASS=$PASS FAIL=$FAIL SKIP=$SKIP ==="
|
||||
|
||||
if [ "$FAIL" -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
Reference in New Issue
Block a user