-
-
Notifications
You must be signed in to change notification settings - Fork 174
/
run_certbot.sh
173 lines (152 loc) · 6.66 KB
/
run_certbot.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
#!/bin/bash
set -e
# URLs used when requesting certificates.
# These are picked up from the environment if they are set, which enables
# advanced usage of custom ACME servers, else it will use the default Let's
# Encrypt servers defined here.
: "${CERTBOT_PRODUCTION_URL=https://acme-v02.api.letsencrypt.org/directory}"
: "${CERTBOT_STAGING_URL=https://acme-staging-v02.api.letsencrypt.org/directory}"
# Source in util.sh so we can have our nice tools.
. "$(cd "$(dirname "$0")"; pwd)/util.sh"
info "Starting certificate renewal process"
# We require an email to be able to request a certificate.
if [ -z "${CERTBOT_EMAIL}" ]; then
error "CERTBOT_EMAIL environment variable undefined; certbot will do nothing!"
exit 1
fi
# Use the correct challenge URL depending on if we want staging or not.
if [ "${STAGING}" = "1" ]; then
debug "Using staging environment"
letsencrypt_url="${CERTBOT_STAGING_URL}"
else
debug "Using production environment"
letsencrypt_url="${CERTBOT_PRODUCTION_URL}"
fi
# Ensure that an RSA key size is set.
if [ -z "${RSA_KEY_SIZE}" ]; then
debug "RSA_KEY_SIZE unset, defaulting to 2048"
RSA_KEY_SIZE=2048
fi
# Ensure that an elliptic curve is set.
if [ -z "${ELLIPTIC_CURVE}" ]; then
debug "ELLIPTIC_CURVE unset, defaulting to 'secp256r1'"
ELLIPTIC_CURVE="secp256r1"
fi
if [ "${1}" = "force" ]; then
info "Forcing renewal of certificates"
force_renew="--force-renewal"
fi
# Helper function to ask certbot to request a certificate for the given cert
# name. The CERTBOT_EMAIL environment variable must be defined, so that
# Let's Encrypt may contact you in case of security issues.
#
# $1: The name of the certificate (e.g. domain.rsa.dns-rfc2136)
# $2: String with all requested domains (e.g. -d domain.org -d www.domain.org)
# $3: Type of key algorithm to use (rsa or ecdsa)
# $4: The authenticator to use to solve the challenge
get_certificate() {
local authenticator="${4,,}"
local authenticator_params=""
local challenge_type=""
# Add correct parameters for the different authenticator types.
if [ "${authenticator}" == "webroot" ]; then
challenge_type="http-01"
authenticator_params="--webroot-path=/var/www/letsencrypt"
elif [[ "${authenticator}" == dns-* ]]; then
challenge_type="dns-01"
if [ "${authenticator#dns-}" == "route53" ]; then
# This one is special and makes use of a different configuration.
if [[ ( -z "${AWS_ACCESS_KEY_ID}" || -z "${AWS_SECRET_ACCESS_KEY}" ) && ! -f "${HOME}/.aws/config" ]]; then
error "Authenticator is '${authenticator}' but neither '${HOME}/.aws/config' or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY are found"
return 1
fi
else
local configfile="/etc/letsencrypt/${authenticator#dns-}.ini"
if [ ! -f "${configfile}" ]; then
error "Authenticator is '${authenticator}' but '${configfile}' is missing"
return 1
fi
authenticator_params="--${authenticator}-credentials=${configfile}"
fi
if [ -n "${CERTBOT_DNS_PROPAGATION_SECONDS}" ]; then
authenticator_params="${authenticator_params} --${authenticator}-propagation-seconds=${CERTBOT_DNS_PROPAGATION_SECONDS}"
fi
else
error "Unknown authenticator '${authenticator}' for '${1}'"
return 1
fi
info "Requesting an ${3^^} certificate for '${1}' (${challenge_type} through ${authenticator})"
certbot certonly \
--agree-tos --keep -n --text \
--preferred-challenges ${challenge_type} \
--authenticator ${authenticator} \
${authenticator_params} \
--email "${CERTBOT_EMAIL}" \
--server "${letsencrypt_url}" \
--rsa-key-size "${RSA_KEY_SIZE}" \
--elliptic-curve "${ELLIPTIC_CURVE}" \
--key-type "${3}" \
--cert-name "${1}" \
${2} \
--debug ${force_renew}
}
# Get all the cert names for which we should create certificate requests and
# have them signed, along with the corresponding server names.
#
# This will return an associative array that looks something like this:
# "cert_name" => "server_name1 server_name2"
declare -A certificates
for conf_file in /etc/nginx/conf.d/*.conf*; do
parse_config_file "${conf_file}" certificates
done
# Iterate over each key and make a certificate request for them.
for cert_name in "${!certificates[@]}"; do
server_names=(${certificates["$cert_name"]})
# Determine which type of key algorithm to use for this certificate
# request. Having the algorithm specified in the certificate name will
# take precedence over the environmental variable.
if [[ "${cert_name,,}" =~ (^|[-.])ecdsa([-.]|$) ]]; then
debug "Found variant of 'ECDSA' in name '${cert_name}"
key_type="ecdsa"
elif [[ "${cert_name,,}" =~ (^|[-.])ecc([-.]|$) ]]; then
debug "Found variant of 'ECC' in name '${cert_name}"
key_type="ecdsa"
elif [[ "${cert_name,,}" =~ (^|[-.])rsa([-.]|$) ]]; then
debug "Found variant of 'RSA' in name '${cert_name}"
key_type="rsa"
elif [ "${USE_ECDSA}" == "0" ]; then
key_type="rsa"
else
key_type="ecdsa"
fi
# Determine the authenticator to use to solve the authentication challenge.
# Having the authenticator specified in the certificate name will take
# precedence over the environmental variable.
if [[ "${cert_name,,}" =~ (^|[-.])webroot([-.]|$) ]]; then
authenticator="webroot"
debug "Found mention of 'webroot' in name '${cert_name}"
elif [[ "${cert_name,,}" =~ (^|[-.])(dns-($(echo ${CERTBOT_DNS_AUTHENTICATORS} | sed 's/ /|/g')))([-.]|$) ]]; then
authenticator=${BASH_REMATCH[2]}
debug "Found mention of authenticator '${authenticator}' in name '${cert_name}'"
elif [ -n "${CERTBOT_AUTHENTICATOR}" ]; then
authenticator="${CERTBOT_AUTHENTICATOR}"
else
authenticator="webroot"
fi
# Assemble the list of domains to be included in the request from
# the parsed 'server_names'
domain_request=""
for server_name in "${server_names[@]}"; do
domain_request="${domain_request} -d ${server_name}"
done
# Hand over all the info required for the certificate request, and
# let certbot decide if it is necessary to update the certificate.
if ! get_certificate "${cert_name}" "${domain_request}" "${key_type}" "${authenticator}"; then
error "Certbot failed for '${cert_name}'. Check the logs for details."
fi
done
# After trying to get all our certificates, auto enable any configs that we
# did indeed get certificates for.
auto_enable_configs
# Finally, tell Nginx to reload the configs.
nginx -s reload