From 63448d542defa86c6c687bd320deff36a78cdaee Mon Sep 17 00:00:00 2001 From: Stanislas Date: Sat, 14 Mar 2026 14:42:06 +0100 Subject: [PATCH] fix: test client connectivity both before and after cert renewal (#1481) - Fix fingerprint CI test that started consistently failing after the EasyRSA 3.2.6 update - The client config was copied to `/shared/` before server cert renewal changed the fingerprint, causing a TLS handshake failure race condition - Instead of just fixing the race, add proper two-phase connectivity testing: client connects before renewal, server renews certs, client reconnects with the updated config --- test/client-entrypoint.sh | 89 ++++++++++++++++++++++++++++++--------- test/server-entrypoint.sh | 44 ++++++++++--------- 2 files changed, 93 insertions(+), 40 deletions(-) diff --git a/test/client-entrypoint.sh b/test/client-entrypoint.sh index a7406ee..de23a13 100755 --- a/test/client-entrypoint.sh +++ b/test/client-entrypoint.sh @@ -12,6 +12,29 @@ fi echo "TUN device ready" +test_dns_resolution() { + local label="$1" + local success=false + echo "$label: Testing DNS resolution via Unbound ($VPN_GATEWAY)..." + for i in $(seq 1 10); do + DIG_OUTPUT=$(dig @"$VPN_GATEWAY" example.com +short +time=5 2>&1) + if [ -n "$DIG_OUTPUT" ] && ! echo "$DIG_OUTPUT" | grep -qi "timed out\|SERVFAIL\|connection refused"; then + success=true + break + fi + echo "DNS attempt $i failed:" + echo "$DIG_OUTPUT" + sleep 2 + done + if [ "$success" = true ]; then + echo "PASS: DNS resolution through Unbound works" + else + echo "FAIL: DNS resolution through Unbound failed after 10 attempts" + dig @"$VPN_GATEWAY" example.com +time=5 || true + exit 1 + fi +} + # Wait for client config to be available echo "Waiting for client config..." while [ ! -f /shared/client.ovpn ]; do @@ -110,27 +133,7 @@ if [ "${CLIENT_IPV6:-n}" = "y" ]; then fi # Test 3: DNS resolution through Unbound -echo "Test 3: Testing DNS resolution via Unbound ($VPN_GATEWAY)..." -DNS_SUCCESS=false -DNS_MAX_RETRIES=10 -for i in $(seq 1 $DNS_MAX_RETRIES); do - DIG_OUTPUT=$(dig @"$VPN_GATEWAY" example.com +short +time=5 2>&1) - if [ -n "$DIG_OUTPUT" ] && ! echo "$DIG_OUTPUT" | grep -qi "timed out\|SERVFAIL\|connection refused"; then - DNS_SUCCESS=true - break - fi - echo "DNS attempt $i failed:" - echo "$DIG_OUTPUT" - sleep 2 -done -if [ "$DNS_SUCCESS" = true ]; then - echo "PASS: DNS resolution through Unbound works" - echo "Resolved example.com to: $(dig @"$VPN_GATEWAY" example.com +short +time=5)" -else - echo "FAIL: DNS resolution through Unbound failed after $DNS_MAX_RETRIES attempts" - dig @"$VPN_GATEWAY" example.com +time=5 || true - exit 1 -fi +test_dns_resolution "Test 3" echo "" echo "=== Initial connectivity tests PASSED ===" @@ -138,6 +141,50 @@ echo "=== Initial connectivity tests PASSED ===" # Signal server that initial tests passed touch /shared/initial-tests-passed +# ===================================================== +# Post-renewal connectivity tests +# ===================================================== +echo "" +echo "=== Waiting for post-renewal config ===" +while [ ! -f /shared/renewal-config-ready ]; do + sleep 2 + echo "Waiting for renewal config..." +done + +echo "Renewal config ready, reconnecting..." +pkill openvpn || true +sleep 2 + +openvpn --config /shared/client.ovpn --daemon --log /var/log/openvpn-renewal.log + +echo "Waiting for VPN connection after renewal..." +while ! ip addr show tun0 2>/dev/null | grep -q "inet "; do + sleep 2 + echo "Waiting for tun0..." + if [ -f /var/log/openvpn-renewal.log ]; then + tail -3 /var/log/openvpn-renewal.log + fi +done + +echo "=== VPN Connected after renewal! ===" +ip addr show tun0 + +echo "Waiting for routing to stabilize..." +sleep 5 + +echo "Test: Pinging VPN gateway after renewal ($VPN_GATEWAY)..." +while ! ping -c 3 -W 2 "$VPN_GATEWAY" >/dev/null 2>&1; do + echo "Ping failed, retrying..." + sleep 3 +done +echo "PASS: Can ping VPN gateway after renewal" + +test_dns_resolution "Test: Post-renewal DNS" + +echo "" +echo "=== Post-renewal connectivity tests PASSED ===" +touch /shared/renewal-tests-passed + # ===================================================== # Certificate Revocation E2E Tests # ===================================================== diff --git a/test/server-entrypoint.sh b/test/server-entrypoint.sh index 58e5e42..edf54c0 100755 --- a/test/server-entrypoint.sh +++ b/test/server-entrypoint.sh @@ -211,7 +211,7 @@ else exit 1 fi -# Copy client config to shared volume for the client container +# Copy client config to shared volume for initial connectivity tests cp /root/testclient.ovpn /shared/client.ovpn sed -i 's/^remote .*/remote openvpn-server 1194/' /shared/client.ovpn echo "Client config copied to /shared/client.ovpn" @@ -356,6 +356,17 @@ fi echo "=== TLS 1.3 Configuration Verified ===" +# ===================================================== +# Wait for initial client tests to complete +# ===================================================== +echo "" +echo "=== Waiting for initial client connectivity tests ===" +while [ ! -f /shared/initial-tests-passed ]; do + sleep 2 + echo "Waiting for initial tests..." +done +echo "Initial client tests passed, proceeding with renewal tests" + # ===================================================== # Test certificate renewal functionality # ===================================================== @@ -429,11 +440,6 @@ if [ "$AUTH_MODE" = "pki" ]; then fi fi -# Update shared client config with renewed certificate -cp /root/testclient.ovpn /shared/client.ovpn -sed -i 's/^remote .*/remote openvpn-server 1194/' /shared/client.ovpn -echo "Updated client config with renewed certificate" - echo "=== Client Certificate Renewal Tests PASSED ===" # ===================================================== @@ -538,10 +544,21 @@ done # Allow routing to stabilize after renewal restart sleep 3 -# Update shared client config after server renewal (fingerprint changed) cp /root/testclient.ovpn /shared/client.ovpn sed -i 's/^remote .*/remote openvpn-server 1194/' /shared/client.ovpn -echo "Updated client config with new server fingerprint" +touch /shared/renewal-config-ready +echo "Updated client config with renewed certificates" + +# ===================================================== +# Wait for post-renewal client connectivity tests +# ===================================================== +echo "" +echo "=== Waiting for post-renewal client connectivity tests ===" +while [ ! -f /shared/renewal-tests-passed ]; do + sleep 2 + echo "Waiting for renewal tests..." +done +echo "Post-renewal client tests passed" # ===================================================== # Verify Unbound DNS resolver (started by systemd via install script) @@ -749,17 +766,6 @@ fi echo "Allowing routing to stabilize..." sleep 3 -# ===================================================== -# Wait for initial client tests to complete -# ===================================================== -echo "" -echo "=== Waiting for initial client connectivity tests ===" -while [ ! -f /shared/initial-tests-passed ]; do - sleep 2 - echo "Waiting for initial tests..." -done -echo "Initial client tests passed, proceeding with revocation tests" - # ===================================================== # Test certificate revocation functionality # =====================================================