-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathletsencrypt-renew
executable file
·176 lines (154 loc) · 5.41 KB
/
letsencrypt-renew
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/bin/sh
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
VALID_DAYS=21
LETSENCRYPT_DIR="$HOME/.config/letsencrypt"
CERT_DIR=${LETSENCRYPT_DIR}/live
CERT_FILE='cert.pem'
DOMAIN=$(grep -e "[ \t]*domains.*" ${LETSENCRYPT_DIR}/cli.ini| sed "s/ //g" |cut -d "=" -f2 | cut -d "," -f1)
FORCE=0
VERBOSE=0
usage() {
cat >&2 <<__EOF__
Usage:
$0 [-q] [-s wait-time] [-f] [-h] [-u]
Options:
-c Cleanup bogus certificates like domain.tld-0001, created due to a
bug in letsencrypt when a domain was removed from cli.ini
-f Force renewal, even if certificate is still valid
-h Show this message
-v Be verbose. Per default, this script only prints errors, and git/letsencrypt output.
MUST be the first parameter (due to a "feature" in bash)
-s wait-time Time in seconds to wait before checking for
certificate renewal, useful for Uberspace servers, where many instances
of this script are run via crontab @daily
-u Self-update uberspace-tools directory via git before running this script
__EOF__
}
log() {
[[ "$VERBOSE" = 1 ]] && echo "$1"
}
# update base directory via git
# returns: exit status of last command, here git: 0 if 'git pull' was successful
update_self() {
cd `dirname $0`
git pull > /dev/null
}
cleanup_certificates() {
log "WARNING: Going to remove ALL -0001, -0002 etc. files and directories"
log "in ~/.config/letsencrypt - make sure there are no needed certificates there."
cd ${LETSENCRYPT_DIR}
# this is a buggy workaround. Does not cover -0010 and greater numbers
# deletes all these files and directories without asking further.
# beware. May eat your dog.
for f in live/${DOMAIN}-000[1-9]; do
log " deleting ${f}..."
rm -rf ${f};
done
for f in archive/${DOMAIN}-000[1-9]; do
log " deleting ${f}..."
rm -rf ${f};
done
for f in renewal/${DOMAIN}-000[1-9].conf; do
log " deleting ${f}..."
rm -rf ${f};
done
log "Cleanup done."
}
# first, see if -v is present, because it affects all others.
if [[ "$1" = "-v" ]]; then
export VERBOSE=1
shift
fi
if [ "$DOMAIN" == "" ]; then
log "the 'domains' variable in ${LETSENCRYPT_DIR} seems to be malformed or missing."
log "Please check this file. (Hint: have you run uberspace-letsencrypt already?)"
exit 1
fi
# process other arguments
while getopts ":cfuhs:" OPT; do
case "$OPT" in
u)
log "Updating uberspace-tools..."
update_self || exit 1
# call this veryscript again, without the -u option, and with the
# other options that are still there to parse
COMMANDLINE=`ps -p $$ -o args --no-headers |sed "s/-u //" |sed "s/-u$//"`
${COMMANDLINE}
exit 0
;;
q)
echo "The -q switch was removed, as output is muted as default now."
echo "Use -v to add verbosity."
exit 1
;;
s)
# sleep x seconds - if x is an integer, else do nothing
RE='^[0-9]+$'
if [[ "${OPTARG}" =~ ${RE} ]] ; then
log "Sleeping $OPTARG seconds..."
sleep ${OPTARG}
else
echo "Invalid option: '${OPTARG}' is no Integer" >&2
usage
fi
;;
h)
usage
exit 0
;;
f)
FORCE=1
;;
c)
cleanup_certificates
exit 0
;;
\?)
echo "Invalid option: '${OPTARG}'" >&2
usage
exit 1
;;
esac
done
# find certificate
# this usually is the certificate in the first, original $DOMAIN dir, before
# any modifications were done to cli.ini (especiale a domein deleted), and
# -0001 whatever directories.were created.
# So a check if that exact cert is still valid does not mean that
# this is the correct domain, currently used by the web server.
CERT="$(find ${CERT_DIR}/$DOMAIN/ -iname ${CERT_FILE} | sort -k1)"
# check if the currently online certificate matches the local one
LOCAL_FINGERPRINT=$(openssl x509 -fingerprint -sha256 -in "$CERT" -noout)
if [ "${LOCAL_FINGERPRINT}" == "" ]; then
echo "There was a problem creating the fingerprint of the server '${DOMAIN}'." >&2
exit 1
fi
ONLINE_FINGERPRINT=$(echo | openssl s_client -servername $DOMAIN \
-connect $DOMAIN:443 2>/dev/null | openssl x509 -fingerprint -noout -sha256)
if [ "${ONLINE_FINGERPRINT}" == "" ]; then
echo "There was a problem creating the fingerprint of the local file '${cert}'." >&2
exit 1
fi
if [ "${ONLINE_FINGERPRINT}" == "${LOCAL_FINGERPRINT}" ]; then
# ok, FP matches, we can at least proceed updating the certificate.
# first check certificate validation date
openssl x509 -checkend $(( ${VALID_DAYS} * 86400 )) -in "$CERT" > /dev/null
# renew certificates if they are less than only ${VALID_DAYS} valid
if [ $? == 1 -o "${FORCE}" == 1 ]; then
certbot certonly && uberspace-add-certificate \
-k ${CERT_DIR}/$DOMAIN/privkey.pem \
-c ${CERT_DIR}/$DOMAIN/${CERT_FILE}
log "Everything done. Exiting."
fi
else
log "The online certificate does not match the current local certificate."
log "This could be due to a changed (deleted?) domain in cli.ini?"
log "Please correct this manually."
log "Online (${DOMAIN}):"
log " ${ONLINE_FINGERPRINT}"
log "Local (${CERT}):"
log " ${LOCAL_FINGERPRINT}"
log "You could try:"
log " uberspace-add-certificate -k ${CERT_DIR}/$DOMAIN/privkey.pem -c ${CERT_DIR}/$DOMAIN/${CERT_FILE}"
exit 1
fi