-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathcertbot-he-hook.sh
executable file
·179 lines (142 loc) · 5.42 KB
/
certbot-he-hook.sh
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
177
178
179
#!/bin/bash
## Help ################################################################
if [ -z "$CERTBOT_DOMAIN" ] || [ -z "$CERTBOT_VALIDATION" ]; then
cat <<HELP
== Certbot hook for Hurricane Electric DNS service ===========================
!! This script is intended to be used as a hook script for certbot !!
With this script, domains that have DNS hosted at Hurricane Electric are
verified automatically, i.e. without the need for a webroot verification or
manually adding TXT records.
- You need to provide either a session ID, or login credentials through
environment variables (see examples below). Session ID should be faster.
Example usage:
1) Create a new certificate for a domain:
HE_USER=<username> HE_PASS=<password> certbot certonly \\
--preferred-challenges dns \\
--email [email protected] \\
--manual \\
--manual-auth-hook /path/to/certbot-he-hook.sh \\
--manual-cleanup-hook /path/to/certbot-he-hook.sh \\
--manual-public-ip-logging-ok \\
--domain <requested.domain.com>
2) Renew certificates for all domains:
HE_USER=<username> HE_PASS=<password> certbot renew \\
--preferred-challenges dns \\
--manual-auth-hook /path/to/certbot-he-hook.sh \\
--manual-cleanup-hook /path/to/certbot-he-hook.sh \\
--manual-public-ip-logging-ok
--
Author: Ondrej Simek <[email protected]>
Updates: https://github.com/angel333/certbot-he-hook
==============================================================================
HELP
exit 1
fi
## Auth parameters for curl ############################################
if [ -n "$HE_USER" ] && [ -n "$HE_PASS" ]; then
HE_COOKIE=$( \
curl -L --silent --show-error -I "https://dns.he.net/" \
| grep '^Set-Cookie:' \
| grep -Eo 'CGISESSID=[a-z0-9]*')
# Attempt login
curl -L --silent --show-error --cookie "$HE_COOKIE" \
--form "email=${HE_USER}" \
--form "pass=${HE_PASS}" \
"https://dns.he.net/" \
> /dev/null
elif [ -n "$HE_SESSID" ]; then
HE_COOKIE="CGISESSID=${HE_SESSID}"
else
echo
'No auth details provided. Please provide either session id (' \
'through the $HE_SESSID environment variable) or user credentials' \
'(through $HE_USER and $HE_PASS environement variables).' \
1>&2
exit 1
fi
## Finding the zone id #################################################
MATCHES=$(
curl -L --silent --show-error --cookie "$HE_COOKIE" \
"https://dns.he.net/" \
| grep -Eo "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+"
)
# Zone names and zone IDs are in same order
ZONE_IDS=$(echo "$MATCHES" | cut -d '"' -f 5)
ZONE_NAMES=$(echo "$MATCHES" | cut -d '"' -f 3)
STRIP_COUNTER=1
# Walk through all possible zone names
while true; do
ATTEMPTED_ZONE=$(echo "$CERTBOT_DOMAIN" | cut -d . -f ${STRIP_COUNTER}-)
# All possible zone names have been tried
if [ -z "$ATTEMPTED_ZONE" ]; then
echo "No zone for domain \"$DOMAIN\" found." 1>&2
return 1
fi
# Take care of "." and only match whole lines. Note that grep -F
# cannot be used because there's no way to make it match whole
# lines.
REGEX="^$(echo "$ATTEMPTED_ZONE" | sed 's/\./\\./g')$"
LINE_NUM=$(echo "$ZONE_NAMES" \
| grep -n "$REGEX" \
| cut -d : -f 1
)
if [ -n "$LINE_NUM" ]; then
HE_ZONEID=$(echo "$ZONE_IDS" | sed "${LINE_NUM}q;d")
# $ATTEMPTED_ZONE has zone $ZONE_ID and will be used for $CERTBOT_DOMAIN.
break
fi
STRIP_COUNTER=$(expr $STRIP_COUNTER + 1)
done
## Add the validation record ###########################################
# $CERTBOT_AUTH_OUTPUT is only passed to the cleanup script
if [ -z "$CERTBOT_AUTH_OUTPUT" ]; then
RECORD_NAME="_acme-challenge.$CERTBOT_DOMAIN"
curl -L --silent --show-error --cookie "$HE_COOKIE" \
--form "account=" \
--form "menu=edit_zone" \
--form "Type=TXT" \
--form "hosted_dns_zoneid=$HE_ZONEID" \
--form "hosted_dns_recordid=" \
--form "hosted_dns_editzone=1" \
--form "Priority=" \
--form "Name=$RECORD_NAME" \
--form "Content=$CERTBOT_VALIDATION" \
--form "TTL=300" \
--form "hosted_dns_editrecord=Submit" \
"https://dns.he.net/" \
| grep -E --only-matching \
"deleteRecord\('.*','$RECORD_NAME','TXT'\)" \
| grep -E --only-matching "\('[0-9]+" | cut -c 3- \
| sort -n | tail -n1
# All the greps, sorts, tails and cuts above do this:
#
# 1. find all records with the same name as we have just added
# 2. strip everything but the ids
# 3. take biggest number (the newest one)
#
# This ID is just printed out and picked up by the cleanup script.
fi
## Remove the validation record (cleanup) ##############################
# $CERTBOT_AUTH_OUTPUT is only passed to the cleanup script
# - it's the record ID
if [ ! -z "$CERTBOT_AUTH_OUTPUT" ]; then
curl -L --silent --show-error --cookie "$HE_COOKIE" \
--form "menu=edit_zone" \
--form "hosted_dns_zoneid=$HE_ZONEID" \
--form "hosted_dns_recordid=$CERTBOT_AUTH_OUTPUT" \
--form "hosted_dns_editzone=1" \
--form "hosted_dns_delrecord=1" \
--form "hosted_dns_delconfirm=delete" \
--form "hosted_dns_editzone=1" \
"https://dns.he.net/" \
| grep '<div id="dns_status" onClick="hideThis(this);">Successfully removed record.</div>' \
> /dev/null
DELETE_OK=$?
if [ $DELETE_OK -ne 0 ]; then
echo \
"Could not clean (remove) up the record. Please go to HE" \
"administration interface and clean it by hand." \
1>&2
fi
fi
# vim: et:ts=2:sw=2: