test: add e2e tests for certificate revocation (#1345)

## Summary

- Add end-to-end tests for certificate revocation functionality
- Test that a revoked client certificate cannot connect to the VPN
- Test that a new certificate can be created with the same name as a
revoked one (validating the fix from #1185)
- Test that the new certificate can successfully connect

## Test Flow

1. **Initial connectivity tests** - existing tests pass
2. **Certificate revocation test**:
   - Create a new client `revoketest`
   - Connect with the certificate (verifies it works)
   - Disconnect the client
   - Revoke the certificate via the install script
- Try to reconnect with revoked cert (verifies connection is rejected)
3. **Reuse revoked name test**:
   - Create a new certificate with the same name `revoketest`
   - Verify both revoked and valid entries exist in `index.txt`
   - Connect with the new certificate (verifies it works)

## Changes

| File | Changes |
|------|---------|
| `test/server-entrypoint.sh` | Start OpenVPN in background, add
revocation test orchestration |
| `test/client-entrypoint.sh` | Add revocation test phases with signal
file coordination |
| `docker-compose.yml` | Remove read-only restriction on shared volume
for client |
| `Makefile` | Increase timeout from 60 to 180 iterations |
| `.github/workflows/docker-test.yml` | Increase timeouts, fix shared
volume |
This commit is contained in:
Stanislas
2025-12-11 18:22:16 +01:00
committed by GitHub
parent 690414a56e
commit 0d4d2229f4
5 changed files with 488 additions and 10 deletions

View File

@@ -103,10 +103,265 @@ else
exit 1
fi
echo ""
echo "=== Initial connectivity tests PASSED ==="
# Signal server that initial tests passed
touch /shared/initial-tests-passed
# =====================================================
# Certificate Revocation E2E Tests
# =====================================================
echo ""
echo "=== Starting Certificate Revocation E2E Tests ==="
REVOKE_CLIENT="revoketest"
# Wait for revoke test client config
echo "Waiting for revoke test client config..."
MAX_WAIT=120
WAITED=0
while [ ! -f /shared/revoke-client-config-ready ] && [ $WAITED -lt $MAX_WAIT ]; do
sleep 2
WAITED=$((WAITED + 2))
echo "Waiting for revoke test config... ($WAITED/$MAX_WAIT seconds)"
done
if [ ! -f /shared/revoke-client-config-ready ]; then
echo "FAIL: Revoke test client config not ready in time"
exit 1
fi
if [ ! -f "/shared/$REVOKE_CLIENT.ovpn" ]; then
echo "FAIL: Revoke test client config file not found"
exit 1
fi
echo "Revoke test client config found!"
# Disconnect current VPN (testclient) before connecting with revoke test client
echo "Disconnecting current VPN connection..."
pkill openvpn || true
sleep 2
# Connect with revoke test client
echo "Connecting with '$REVOKE_CLIENT' certificate..."
openvpn --config "/shared/$REVOKE_CLIENT.ovpn" --daemon --log /var/log/openvpn-revoke.log
# Wait for connection
echo "Waiting for VPN connection with revoke test client..."
MAX_WAIT=60
WAITED=0
while ! ip addr show tun0 2>/dev/null | grep -q "inet " && [ $WAITED -lt $MAX_WAIT ]; do
sleep 2
WAITED=$((WAITED + 2))
echo "Waiting for tun0... ($WAITED/$MAX_WAIT seconds)"
if [ -f /var/log/openvpn-revoke.log ]; then
tail -3 /var/log/openvpn-revoke.log
fi
done
if ! ip addr show tun0 2>/dev/null | grep -q "inet "; then
echo "FAIL: VPN connection with revoke test client failed"
cat /var/log/openvpn-revoke.log || true
exit 1
fi
echo "PASS: Connected with '$REVOKE_CLIENT' certificate"
ip addr show tun0
# Verify connectivity
if ping -c 2 10.8.0.1 >/dev/null 2>&1; then
echo "PASS: Can ping VPN gateway with revoke test client"
else
echo "FAIL: Cannot ping VPN gateway with revoke test client"
exit 1
fi
# Signal server that we're connected with revoke test client
touch /shared/revoke-client-connected
# Wait for server to signal us to disconnect
echo "Waiting for server to signal disconnect..."
MAX_WAIT=60
WAITED=0
while [ ! -f /shared/revoke-client-disconnect ] && [ $WAITED -lt $MAX_WAIT ]; do
sleep 2
WAITED=$((WAITED + 2))
done
if [ ! -f /shared/revoke-client-disconnect ]; then
echo "FAIL: Server did not signal disconnect"
exit 1
fi
# Disconnect
echo "Disconnecting revoke test client..."
pkill openvpn || true
# Wait for openvpn to fully exit and tun0 to be released
WAITED=0
MAX_WAIT_DISCONNECT=10
while (pgrep openvpn >/dev/null || ip addr show tun0 2>/dev/null | grep -q "inet ") && [ $WAITED -lt $MAX_WAIT_DISCONNECT ]; do
sleep 1
WAITED=$((WAITED + 1))
done
# Verify disconnected
if ip addr show tun0 2>/dev/null | grep -q "inet "; then
echo "FAIL: tun0 still has IP after disconnect"
exit 1
fi
echo "PASS: Disconnected successfully"
# Signal server that we're disconnected
touch /shared/revoke-client-disconnected
# Wait for server to revoke the certificate and signal us to reconnect
echo "Waiting for server to revoke certificate and signal reconnect..."
MAX_WAIT=60
WAITED=0
while [ ! -f /shared/revoke-try-reconnect ] && [ $WAITED -lt $MAX_WAIT ]; do
sleep 2
WAITED=$((WAITED + 2))
done
if [ ! -f /shared/revoke-try-reconnect ]; then
echo "FAIL: Server did not signal to try reconnect"
exit 1
fi
# Try to reconnect with the now-revoked certificate (should fail)
echo "Attempting to reconnect with revoked certificate (should fail)..."
rm -f /var/log/openvpn-revoke-fail.log
openvpn --config "/shared/$REVOKE_CLIENT.ovpn" --daemon --log /var/log/openvpn-revoke-fail.log
# Wait and check if connection fails
# The connection should fail due to certificate being revoked
echo "Waiting to verify connection is rejected..."
CONNECT_FAILED=false
MAX_WAIT=30
WAITED=0
while [ $WAITED -lt $MAX_WAIT ]; do
sleep 2
WAITED=$((WAITED + 2))
# Check if tun0 came up (would mean revocation didn't work)
if ip addr show tun0 2>/dev/null | grep -q "inet "; then
echo "FAIL: Connection succeeded with revoked certificate!"
cat /var/log/openvpn-revoke-fail.log || true
exit 1
fi
# Check for certificate verification failure in log
if [ -f /var/log/openvpn-revoke-fail.log ]; then
if grep -qi "certificate verify failed\|TLS Error\|AUTH_FAILED\|certificate revoked" /var/log/openvpn-revoke-fail.log; then
echo "Connection correctly rejected (certificate revoked)"
CONNECT_FAILED=true
break
fi
fi
echo "Checking connection status... ($WAITED/$MAX_WAIT seconds)"
if [ -f /var/log/openvpn-revoke-fail.log ]; then
tail -3 /var/log/openvpn-revoke-fail.log
fi
done
# Kill any remaining openvpn process
pkill openvpn 2>/dev/null || true
sleep 1
# Even if we didn't see explicit error, verify tun0 is not up
if ip addr show tun0 2>/dev/null | grep -q "inet "; then
echo "FAIL: tun0 interface exists - revoked cert may have connected"
exit 1
fi
if [ "$CONNECT_FAILED" = true ]; then
echo "PASS: Connection with revoked certificate was correctly rejected"
else
echo "PASS: Connection with revoked certificate did not succeed (no tun0)"
echo "OpenVPN log:"
cat /var/log/openvpn-revoke-fail.log || true
fi
# Signal server that reconnect with revoked cert failed
touch /shared/revoke-reconnect-failed
# =====================================================
# Test connecting with new certificate (same name)
# =====================================================
echo ""
echo "=== Testing connection with recreated certificate ==="
# Wait for server to create new cert and signal us
echo "Waiting for new client config with same name..."
MAX_WAIT=120
WAITED=0
while [ ! -f /shared/new-client-config-ready ] && [ $WAITED -lt $MAX_WAIT ]; do
sleep 2
WAITED=$((WAITED + 2))
echo "Waiting for new config... ($WAITED/$MAX_WAIT seconds)"
done
if [ ! -f /shared/new-client-config-ready ]; then
echo "FAIL: New client config not ready in time"
exit 1
fi
if [ ! -f "/shared/$REVOKE_CLIENT-new.ovpn" ]; then
echo "FAIL: New client config file not found"
exit 1
fi
echo "New client config found!"
# Connect with the new certificate
echo "Connecting with new '$REVOKE_CLIENT' certificate..."
rm -f /var/log/openvpn-new.log
openvpn --config "/shared/$REVOKE_CLIENT-new.ovpn" --daemon --log /var/log/openvpn-new.log
# Wait for connection
echo "Waiting for VPN connection with new certificate..."
MAX_WAIT=60
WAITED=0
while ! ip addr show tun0 2>/dev/null | grep -q "inet " && [ $WAITED -lt $MAX_WAIT ]; do
sleep 2
WAITED=$((WAITED + 2))
echo "Waiting for tun0... ($WAITED/$MAX_WAIT seconds)"
if [ -f /var/log/openvpn-new.log ]; then
tail -3 /var/log/openvpn-new.log
fi
done
if ! ip addr show tun0 2>/dev/null | grep -q "inet "; then
echo "FAIL: VPN connection with new certificate failed"
cat /var/log/openvpn-new.log || true
exit 1
fi
echo "PASS: Connected with new '$REVOKE_CLIENT' certificate"
ip addr show tun0
# Verify connectivity
if ping -c 2 10.8.0.1 >/dev/null 2>&1; then
echo "PASS: Can ping VPN gateway with new certificate"
else
echo "FAIL: Cannot ping VPN gateway with new certificate"
exit 1
fi
# Signal server that we connected with new cert
touch /shared/new-client-connected
echo ""
echo "=== Certificate Revocation E2E Tests PASSED ==="
echo ""
echo "=========================================="
echo " ALL TESTS PASSED!"
echo "=========================================="
# Keep container running for debugging if needed
exec tail -f /var/log/openvpn.log
exec tail -f /var/log/openvpn-new.log 2>/dev/null || tail -f /var/log/openvpn.log 2>/dev/null || sleep infinity