Merge pull request #251 from buchdag/buchdag-revoke1

Fix certificate revocation
This commit is contained in:
Kyle Manna 2017-05-10 09:37:03 -07:00 committed by GitHub
commit 909744dd78
7 changed files with 175 additions and 10 deletions

View File

@ -38,3 +38,6 @@ openvpn --genkey --secret $EASYRSA_PKI/ta.key
# For a server key with a password, manually init; this is autopilot
easyrsa build-server-full "$OVPN_CN" nopass
# Generate the CRL for client/server certificates revocation.
easyrsa gen-crl

61
bin/ovpn_revokeclient Executable file
View 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

View File

@ -74,13 +74,14 @@ if [ "$OVPN_DEFROUTE" != "0" ] || [ "$OVPN_NAT" == "1" ] ; then
setupIptablesAndRouting
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.
if [ -r "$EASYRSA_PKI/crl.pem" ]; then
if [ ! -r "$OPENVPN/crl.pem" ]; then
ln "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
chmod 644 "$OPENVPN/crl.pem"
fi
if [ "$EASYRSA_PKI/crl.pem" -nt "$OPENVPN/crl.pem" ]; then
cp -f "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
chmod 644 "$OPENVPN/crl.pem"
fi
if [ -r "$OPENVPN/crl.pem" ]; then
addArg "--crl-verify" "$OPENVPN/crl.pem"
fi

View File

@ -34,9 +34,12 @@ After doing so, you will find the following files in each of the `$cn` directori
## 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 easyrsa gen-crl
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient client1
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

View File

@ -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
```
* 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
* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").

View File

@ -7,11 +7,12 @@ testAlias+=(
imageTests+=(
[openvpn]='
paranoid
paranoid
conf_options
basic
dual-proto
otp
iptables
revocation
'
)

87
test/tests/revocation/run.sh Executable file
View 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