Merge pull request #251 from buchdag/buchdag-revoke1
Fix certificate revocation
This commit is contained in:
		@@ -38,3 +38,6 @@ openvpn --genkey --secret $EASYRSA_PKI/ta.key
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# For a server key with a password, manually init; this is autopilot
 | 
					# For a server key with a password, manually init; this is autopilot
 | 
				
			||||||
easyrsa build-server-full "$OVPN_CN" nopass
 | 
					easyrsa build-server-full "$OVPN_CN" nopass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Generate the CRL for client/server certificates revocation.
 | 
				
			||||||
 | 
					easyrsa gen-crl
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										61
									
								
								bin/ovpn_revokeclient
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										61
									
								
								bin/ovpn_revokeclient
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Revoke a client certificate
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$DEBUG" == "1" ]; then
 | 
				
			||||||
 | 
					    set -x
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$OPENVPN" ]; then
 | 
				
			||||||
 | 
					    export OPENVPN="$PWD"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					if ! source "$OPENVPN/ovpn_env.sh"; then
 | 
				
			||||||
 | 
					    echo "Could not source $OPENVPN/ovpn_env.sh."
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					if [ -z "$EASYRSA_PKI" ]; then
 | 
				
			||||||
 | 
					    export EASYRSA_PKI="$OPENVPN/pki"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cn="$1"
 | 
				
			||||||
 | 
					parm="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ ! -f "$EASYRSA_PKI/private/${cn}.key" ]; then
 | 
				
			||||||
 | 
					    echo "Unable to find \"${cn}\", please try again or generate the key first" >&2
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					revoke_client_certificate(){
 | 
				
			||||||
 | 
					    easyrsa revoke "$1"
 | 
				
			||||||
 | 
					    echo "Generating the Certificate Revocation List :"
 | 
				
			||||||
 | 
					    easyrsa gen-crl
 | 
				
			||||||
 | 
					    cp -f "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
 | 
				
			||||||
 | 
					    chmod 644 "$OPENVPN/crl.pem"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					remove_files(){
 | 
				
			||||||
 | 
					    rm -v "$EASYRSA_PKI/issued/${1}.crt"
 | 
				
			||||||
 | 
					    rm -v "$EASYRSA_PKI/private/${1}.key"
 | 
				
			||||||
 | 
					    rm -v "$EASYRSA_PKI/reqs/${1}.req"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$parm" in
 | 
				
			||||||
 | 
					    "remove")
 | 
				
			||||||
 | 
					        revoke_client_certificate "$cn"
 | 
				
			||||||
 | 
					        remove_files "$cn"
 | 
				
			||||||
 | 
					        ;;
 | 
				
			||||||
 | 
					    "" | "keep")
 | 
				
			||||||
 | 
					        revoke_client_certificate "$cn"
 | 
				
			||||||
 | 
					        ;;
 | 
				
			||||||
 | 
					    *)
 | 
				
			||||||
 | 
					        echo "When revoking a client certificate, this script let you choose if you want to remove the corresponding crt, key and req files." >&2
 | 
				
			||||||
 | 
					        echo "Pease note that the removal of those files is required if you want to generate a new client certificate using the revoked certificate's CN." >&2
 | 
				
			||||||
 | 
					        echo "    1. keep (default): Keep the files." >&2
 | 
				
			||||||
 | 
					        echo "    2. remove: Remove the files." >&2
 | 
				
			||||||
 | 
					        echo "Please specify one of those options as second parameter." >&2
 | 
				
			||||||
 | 
					        ;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
@@ -74,13 +74,14 @@ if [ "$OVPN_DEFROUTE" != "0" ] || [ "$OVPN_NAT" == "1" ] ; then
 | 
				
			|||||||
	setupIptablesAndRouting
 | 
						setupIptablesAndRouting
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Use a hacky hardlink as the CRL Needs to be readable by the user/group
 | 
					# Use a copy of crl.pem as the CRL Needs to be readable by the user/group
 | 
				
			||||||
# OpenVPN is running as.  Only pass arguments to OpenVPN if it's found.
 | 
					# OpenVPN is running as.  Only pass arguments to OpenVPN if it's found.
 | 
				
			||||||
if [ -r "$EASYRSA_PKI/crl.pem" ]; then
 | 
					if [ "$EASYRSA_PKI/crl.pem" -nt "$OPENVPN/crl.pem" ]; then
 | 
				
			||||||
    if [ ! -r "$OPENVPN/crl.pem" ]; then
 | 
					    cp -f "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
 | 
				
			||||||
        ln "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
 | 
					 | 
				
			||||||
    chmod 644 "$OPENVPN/crl.pem"
 | 
					    chmod 644 "$OPENVPN/crl.pem"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -r "$OPENVPN/crl.pem" ]; then
 | 
				
			||||||
    addArg "--crl-verify" "$OPENVPN/crl.pem"
 | 
					    addArg "--crl-verify" "$OPENVPN/crl.pem"
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,9 +34,12 @@ After doing so, you will find the following files in each of the `$cn` directori
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
## Revoking Client Certificates
 | 
					## Revoking Client Certificates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Revoke `client1`'s certificate and generate the certificate revocation list (CRL):
 | 
					Revoke `client1`'s certificate and generate the certificate revocation list (CRL) using [`ovpn_revokeclient`](/bin/ovpn_revokeclient) script :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn easyrsa revoke client1
 | 
					    docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient client1
 | 
				
			||||||
    docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn easyrsa gen-crl
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
The OpenVPN server will read this change every time a client connects (no need to restart server) and deny clients access using revoked certificates.
 | 
					The OpenVPN server will read this change every time a client connects (no need to restart server) and deny clients access using revoked certificates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can optionally pass `remove` as second parameter to ovpn_revokeclient to remove the corresponding crt, key and req files :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient client1 remove
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,6 +59,15 @@ docker-compose run --rm openvpn easyrsa build-client-full $CLIENTNAME nopass
 | 
				
			|||||||
docker-compose run --rm openvpn ovpn_getclient $CLIENTNAME > $CLIENTNAME.ovpn
 | 
					docker-compose run --rm openvpn ovpn_getclient $CLIENTNAME > $CLIENTNAME.ovpn
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Revoke a client certificate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					# Keep the corresponding crt, key and req files.
 | 
				
			||||||
 | 
					docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME
 | 
				
			||||||
 | 
					# Remove the corresponding crt, key and req files.
 | 
				
			||||||
 | 
					docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME remove
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Debugging Tips
 | 
					## Debugging Tips
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").
 | 
					* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,5 +13,6 @@ imageTests+=(
 | 
				
			|||||||
        dual-proto
 | 
					        dual-proto
 | 
				
			||||||
        otp
 | 
					        otp
 | 
				
			||||||
	iptables
 | 
						iptables
 | 
				
			||||||
 | 
						revocation
 | 
				
			||||||
	'
 | 
						'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										87
									
								
								test/tests/revocation/run.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										87
									
								
								test/tests/revocation/run.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[ -n "${DEBUG+x}" ] && set -x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OVPN_DATA="basic-data"
 | 
				
			||||||
 | 
					CLIENT1="travis-client1"
 | 
				
			||||||
 | 
					CLIENT2="travis-client2"
 | 
				
			||||||
 | 
					IMG="kylemanna/openvpn"
 | 
				
			||||||
 | 
					NAME="ovpn-test"
 | 
				
			||||||
 | 
					CLIENT_DIR="$(readlink -f "$(dirname "$BASH_SOURCE")/../../client")"
 | 
				
			||||||
 | 
					SERV_IP="$(ip -4 -o addr show scope global  | awk '{print $4}' | sed -e 's:/.*::' | head -n1)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Initialize openvpn configuration and pki.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					docker volume create --name $OVPN_DATA
 | 
				
			||||||
 | 
					docker run --rm -v $OVPN_DATA:/etc/openvpn $IMG ovpn_genconfig -u udp://$SERV_IP
 | 
				
			||||||
 | 
					docker run --rm -v $OVPN_DATA:/etc/openvpn -it -e "EASYRSA_BATCH=1" -e "EASYRSA_REQ_CN=Travis-CI Test CA" $IMG ovpn_initpki nopass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Fire up the server.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					sudo iptables -N DOCKER || echo 'Firewall already configured'
 | 
				
			||||||
 | 
					sudo iptables -I FORWARD 1 -j DOCKER
 | 
				
			||||||
 | 
					docker run -d -v $OVPN_DATA:/etc/openvpn --cap-add=NET_ADMIN --privileged -p 1194:1194/udp --name $NAME $IMG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Generate a first client certificate and configuration using $CLIENT1 as CN then revoke it.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					docker exec -it $NAME easyrsa build-client-full $CLIENT1 nopass
 | 
				
			||||||
 | 
					docker exec -it $NAME ovpn_getclient $CLIENT1 > $CLIENT_DIR/config.ovpn
 | 
				
			||||||
 | 
					docker exec -it $NAME bash -c "echo 'yes' | ovpn_revokeclient $CLIENT1 remove"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Test that openvpn client can't connect using $CLIENT1 config.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
 | 
				
			||||||
 | 
					    echo "Client was able to connect after revocation test #1." >&2
 | 
				
			||||||
 | 
					    exit 2
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Generate and revoke a second client certificate using $CLIENT2 as CN, then test for failed client connection.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					docker exec -it $NAME easyrsa build-client-full $CLIENT2 nopass
 | 
				
			||||||
 | 
					docker exec -it $NAME ovpn_getclient $CLIENT2 > $CLIENT_DIR/config.ovpn
 | 
				
			||||||
 | 
					docker exec -it $NAME bash -c "echo 'yes' | ovpn_revokeclient $CLIENT2 remove"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
 | 
				
			||||||
 | 
					    echo "Client was able to connect after revocation test #2." >&2
 | 
				
			||||||
 | 
					    exit 2
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Restart the server
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					docker stop $NAME && docker start $NAME
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Test for failed connection using $CLIENT2 config again.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
 | 
				
			||||||
 | 
					    echo "Client was able to connect after revocation test #3." >&2
 | 
				
			||||||
 | 
					    exit 2
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Stop the server and clean up
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					docker kill $NAME && docker rm $NAME
 | 
				
			||||||
 | 
					docker volume rm $OVPN_DATA
 | 
				
			||||||
 | 
					sudo iptables -D FORWARD 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Celebrate
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					cat <<EOF
 | 
				
			||||||
 | 
					 ___________
 | 
				
			||||||
 | 
					< it worked >
 | 
				
			||||||
 | 
					 -----------
 | 
				
			||||||
 | 
					        \   ^__^
 | 
				
			||||||
 | 
					         \  (oo)\_______
 | 
				
			||||||
 | 
					            (__)\       )\/\\
 | 
				
			||||||
 | 
					                ||----w |
 | 
				
			||||||
 | 
					                ||     ||
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
		Reference in New Issue
	
	Block a user