Skip to content

Commit 909744d

Browse files
authored
Merge pull request #251 from buchdag/buchdag-revoke1
Fix certificate revocation
2 parents f996bba + 5aea8b9 commit 909744d

File tree

7 files changed

+175
-10
lines changed

7 files changed

+175
-10
lines changed

bin/ovpn_initpki

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ openvpn --genkey --secret $EASYRSA_PKI/ta.key
3838

3939
# For a server key with a password, manually init; this is autopilot
4040
easyrsa build-server-full "$OVPN_CN" nopass
41+
42+
# Generate the CRL for client/server certificates revocation.
43+
easyrsa gen-crl

bin/ovpn_revokeclient

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/bash
2+
3+
#
4+
# Revoke a client certificate
5+
#
6+
7+
if [ "$DEBUG" == "1" ]; then
8+
set -x
9+
fi
10+
11+
set -e
12+
13+
if [ -z "$OPENVPN" ]; then
14+
export OPENVPN="$PWD"
15+
fi
16+
if ! source "$OPENVPN/ovpn_env.sh"; then
17+
echo "Could not source $OPENVPN/ovpn_env.sh."
18+
exit 1
19+
fi
20+
if [ -z "$EASYRSA_PKI" ]; then
21+
export EASYRSA_PKI="$OPENVPN/pki"
22+
fi
23+
24+
cn="$1"
25+
parm="$2"
26+
27+
if [ ! -f "$EASYRSA_PKI/private/${cn}.key" ]; then
28+
echo "Unable to find \"${cn}\", please try again or generate the key first" >&2
29+
exit 1
30+
fi
31+
32+
revoke_client_certificate(){
33+
easyrsa revoke "$1"
34+
echo "Generating the Certificate Revocation List :"
35+
easyrsa gen-crl
36+
cp -f "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
37+
chmod 644 "$OPENVPN/crl.pem"
38+
}
39+
40+
remove_files(){
41+
rm -v "$EASYRSA_PKI/issued/${1}.crt"
42+
rm -v "$EASYRSA_PKI/private/${1}.key"
43+
rm -v "$EASYRSA_PKI/reqs/${1}.req"
44+
}
45+
46+
case "$parm" in
47+
"remove")
48+
revoke_client_certificate "$cn"
49+
remove_files "$cn"
50+
;;
51+
"" | "keep")
52+
revoke_client_certificate "$cn"
53+
;;
54+
*)
55+
echo "When revoking a client certificate, this script let you choose if you want to remove the corresponding crt, key and req files." >&2
56+
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
57+
echo " 1. keep (default): Keep the files." >&2
58+
echo " 2. remove: Remove the files." >&2
59+
echo "Please specify one of those options as second parameter." >&2
60+
;;
61+
esac

bin/ovpn_run

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,14 @@ if [ "$OVPN_DEFROUTE" != "0" ] || [ "$OVPN_NAT" == "1" ] ; then
7474
setupIptablesAndRouting
7575
fi
7676

77-
# Use a hacky hardlink as the CRL Needs to be readable by the user/group
77+
# Use a copy of crl.pem as the CRL Needs to be readable by the user/group
7878
# OpenVPN is running as. Only pass arguments to OpenVPN if it's found.
79-
if [ -r "$EASYRSA_PKI/crl.pem" ]; then
80-
if [ ! -r "$OPENVPN/crl.pem" ]; then
81-
ln "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
82-
chmod 644 "$OPENVPN/crl.pem"
83-
fi
79+
if [ "$EASYRSA_PKI/crl.pem" -nt "$OPENVPN/crl.pem" ]; then
80+
cp -f "$EASYRSA_PKI/crl.pem" "$OPENVPN/crl.pem"
81+
chmod 644 "$OPENVPN/crl.pem"
82+
fi
83+
84+
if [ -r "$OPENVPN/crl.pem" ]; then
8485
addArg "--crl-verify" "$OPENVPN/crl.pem"
8586
fi
8687

docs/clients.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ After doing so, you will find the following files in each of the `$cn` directori
3434

3535
## Revoking Client Certificates
3636

37-
Revoke `client1`'s certificate and generate the certificate revocation list (CRL):
37+
Revoke `client1`'s certificate and generate the certificate revocation list (CRL) using [`ovpn_revokeclient`](/bin/ovpn_revokeclient) script :
3838

39-
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn easyrsa revoke client1
40-
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn easyrsa gen-crl
39+
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient client1
4140

4241
The OpenVPN server will read this change every time a client connects (no need to restart server) and deny clients access using revoked certificates.
42+
43+
You can optionally pass `remove` as second parameter to ovpn_revokeclient to remove the corresponding crt, key and req files :
44+
45+
docker run --rm -it -v $OVPN_DATA:/etc/openvpn kylemanna/openvpn ovpn_revokeclient client1 remove

docs/docker-compose.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ docker-compose run --rm openvpn easyrsa build-client-full $CLIENTNAME nopass
5959
docker-compose run --rm openvpn ovpn_getclient $CLIENTNAME > $CLIENTNAME.ovpn
6060
```
6161

62+
* Revoke a client certificate
63+
64+
```bash
65+
# Keep the corresponding crt, key and req files.
66+
docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME
67+
# Remove the corresponding crt, key and req files.
68+
docker-compose run --rm openvpn ovpn_revokeclient $CLIENTNAME remove
69+
```
70+
6271
## Debugging Tips
6372

6473
* Create an environment variable with the name DEBUG and value of 1 to enable debug output (using "docker -e").

test/config.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ testAlias+=(
77

88
imageTests+=(
99
[openvpn]='
10-
paranoid
10+
paranoid
1111
conf_options
1212
basic
1313
dual-proto
1414
otp
1515
iptables
16+
revocation
1617
'
1718
)

test/tests/revocation/run.sh

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/bin/bash
2+
set -e
3+
4+
[ -n "${DEBUG+x}" ] && set -x
5+
6+
OVPN_DATA="basic-data"
7+
CLIENT1="travis-client1"
8+
CLIENT2="travis-client2"
9+
IMG="kylemanna/openvpn"
10+
NAME="ovpn-test"
11+
CLIENT_DIR="$(readlink -f "$(dirname "$BASH_SOURCE")/../../client")"
12+
SERV_IP="$(ip -4 -o addr show scope global | awk '{print $4}' | sed -e 's:/.*::' | head -n1)"
13+
14+
#
15+
# Initialize openvpn configuration and pki.
16+
#
17+
docker volume create --name $OVPN_DATA
18+
docker run --rm -v $OVPN_DATA:/etc/openvpn $IMG ovpn_genconfig -u udp://$SERV_IP
19+
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
20+
21+
#
22+
# Fire up the server.
23+
#
24+
sudo iptables -N DOCKER || echo 'Firewall already configured'
25+
sudo iptables -I FORWARD 1 -j DOCKER
26+
docker run -d -v $OVPN_DATA:/etc/openvpn --cap-add=NET_ADMIN --privileged -p 1194:1194/udp --name $NAME $IMG
27+
28+
#
29+
# Generate a first client certificate and configuration using $CLIENT1 as CN then revoke it.
30+
#
31+
docker exec -it $NAME easyrsa build-client-full $CLIENT1 nopass
32+
docker exec -it $NAME ovpn_getclient $CLIENT1 > $CLIENT_DIR/config.ovpn
33+
docker exec -it $NAME bash -c "echo 'yes' | ovpn_revokeclient $CLIENT1 remove"
34+
35+
#
36+
# Test that openvpn client can't connect using $CLIENT1 config.
37+
#
38+
if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
39+
echo "Client was able to connect after revocation test #1." >&2
40+
exit 2
41+
fi
42+
43+
#
44+
# Generate and revoke a second client certificate using $CLIENT2 as CN, then test for failed client connection.
45+
#
46+
docker exec -it $NAME easyrsa build-client-full $CLIENT2 nopass
47+
docker exec -it $NAME ovpn_getclient $CLIENT2 > $CLIENT_DIR/config.ovpn
48+
docker exec -it $NAME bash -c "echo 'yes' | ovpn_revokeclient $CLIENT2 remove"
49+
50+
if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
51+
echo "Client was able to connect after revocation test #2." >&2
52+
exit 2
53+
fi
54+
55+
#
56+
# Restart the server
57+
#
58+
docker stop $NAME && docker start $NAME
59+
60+
#
61+
# Test for failed connection using $CLIENT2 config again.
62+
#
63+
if docker run --rm -v $CLIENT_DIR:/client --cap-add=NET_ADMIN --privileged --net=host $IMG /client/wait-for-connect.sh; then
64+
echo "Client was able to connect after revocation test #3." >&2
65+
exit 2
66+
fi
67+
68+
#
69+
# Stop the server and clean up
70+
#
71+
docker kill $NAME && docker rm $NAME
72+
docker volume rm $OVPN_DATA
73+
sudo iptables -D FORWARD 1
74+
75+
#
76+
# Celebrate
77+
#
78+
cat <<EOF
79+
___________
80+
< it worked >
81+
-----------
82+
\ ^__^
83+
\ (oo)\_______
84+
(__)\ )\/\\
85+
||----w |
86+
|| ||
87+
EOF

0 commit comments

Comments
 (0)