Skip to content

Commit 8484a02

Browse files
committed
enable local ca with yml file
1 parent d01a19d commit 8484a02

File tree

3 files changed

+84
-43
lines changed

3 files changed

+84
-43
lines changed

src/scripts/create_dhparams.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ create_dhparam() {
1414
# Read dhparam-size from config file, falling back to DHPARAM_SIZE environment variable.
1515
local CONFIG_FILE="${NGINX_CERTBOT_CONFIG_FILE:-/etc/nginx-certbot/config.yml}"
1616
if [ -f "${CONFIG_FILE}" ]; then
17+
local YAML_DHPARAM_SIZE
1718
YAML_DHPARAM_SIZE=$(shyaml get-value nginx-certbot.dhparam-size '' < "${CONFIG_FILE}")
1819
if [ -n "${YAML_DHPARAM_SIZE}" ]; then
1920
DHPARAM_SIZE=${YAML_DHPARAM_SIZE}

src/scripts/run_certbot.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fi
3737

3838
# We require an email to be able to request a certificate.
3939
if [ -z "${certbot_email}" ]; then
40-
error "CERTBOT_EMAIL environment variable undefined; certbot will do nothing!"
40+
error "certbot.email or CERTBOT_EMAIL environment variable must be set; without it certbot will do nothing!"
4141
exit 1
4242
fi
4343

@@ -132,10 +132,10 @@ get_certificate() {
132132

133133
# Get all the cert names for which we should create certificate requests and
134134
# have them signed, along with the corresponding server names.
135-
# If we have a config file we request certificates based on the specifications
136-
# within that file otherwise we parse the nginx config files to automatically
135+
# If we have a config file with the 'certificates' key we request certificates based on the
136+
# specifications within that file otherwise we parse the nginx config files to automatically
137137
# discover certificate names, key types, authenticators, and domains.
138-
if [ -f "${CONFIG_FILE}" ]; then
138+
if [ -f "${CONFIG_FILE}" ] && shyaml -q get-value certificates < "${CONFIG_FILE}"; then
139139
debug "Using config file '${CONFIG_FILE}' for certificate specifications"
140140
# Loop over the certificates array and request the certificates
141141
while read -r -d '' cert; do
@@ -158,7 +158,7 @@ if [ -f "${CONFIG_FILE}" ]; then
158158
error "'domains' are missing; ignoring this certificate specification"
159159
continue
160160
fi
161-
debug "Certificate domains are is: ${domains[*]}"
161+
debug "Certificate domains are: ${domains[*]}"
162162
domain_request=""
163163
for domain in "${domains[@]}"; do
164164
domain_request+=" --domain ${domain}"

src/scripts/run_local_ca.sh

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,22 @@ LOCAL_CA_CRT_DIR="${LOCAL_CA_DIR}/new_certs"
1616

1717
info "Starting certificate renewal process with local CA"
1818

19+
# Load some configuration from file with environment variables as fallback
20+
CONFIG_FILE="${NGINX_CERTBOT_CONFIG_FILE:-/etc/nginx-certbot/config.yml}"
21+
if [ -f "${CONFIG_FILE}" ]; then
22+
certbot_email="$(shyaml get-value certbot.email '' < "${CONFIG_FILE}")"
23+
certbot_rsa_key_size="$(shyaml get-value certbot.rsa-key-size '' < "${CONFIG_FILE}")"
24+
fi
25+
: "${certbot_email:=${CERTBOT_EMAIL}}"
26+
: "${certbot_rsa_key_size:=${RSA_KEY_SIZE:-2048}}"
27+
1928
# We require an email to be set here as well, in order to simulate how it would
2029
# be in the real certbot case.
21-
if [ -z "${CERTBOT_EMAIL}" ]; then
22-
error "CERTBOT_EMAIL environment variable undefined; local CA will do nothing!"
30+
if [ -z "${certbot_email}" ]; then
31+
error "certbot.email or CERTBOT_EMAIL environment variable must be set; without it certbot will do nothing!"
2332
exit 1
2433
fi
2534

26-
# Ensure that an RSA key size is set.
27-
if [ -z "${RSA_KEY_SIZE}" ]; then
28-
debug "RSA_KEY_SIZE unset, defaulting to 2048"
29-
RSA_KEY_SIZE=2048
30-
fi
31-
3235
# This is an OpenSSL configuration file that has settings for creating a well
3336
# configured CA, as well as server certificates that adhere to the strict
3437
# standards of web browsers. This is not complete, but will have the missing
@@ -111,7 +114,7 @@ generate_ca() {
111114
# Make sure there is a private key available for the CA.
112115
if [ ! -f "${LOCAL_CA_KEY}" ]; then
113116
info "Generating new private key for local CA"
114-
openssl genrsa -out "${LOCAL_CA_KEY}" "${RSA_KEY_SIZE}"
117+
openssl genrsa -out "${LOCAL_CA_KEY}" "${certbot_rsa_key_size}"
115118
fi
116119

117120
# Make sure there exists a self-signed certificate for the CA.
@@ -136,7 +139,7 @@ generate_ca() {
136139
"0.organizationName = github.com/JonasAlfredsson" \
137140
"organizationalUnitName = docker-nginx-certbot" \
138141
"commonName = Local Debug CA" \
139-
"emailAddress = ${CERTBOT_EMAIL}" \
142+
"emailAddress = ${certbot_email}" \
140143
) \
141144
-extensions ca_cert \
142145
-days "${LOCAL_CA_ROOT_CERT_VALIDITY}" \
@@ -177,15 +180,15 @@ get_certificate() {
177180
# It is good practice to generate a new key every time a new certificate is
178181
# requested, in order to guard against potential key compromises.
179182
info "Generating new private key for '${cert_name}'"
180-
openssl genrsa -out "/etc/letsencrypt/live/${cert_name}/privkey.pem" "${RSA_KEY_SIZE}"
183+
openssl genrsa -out "/etc/letsencrypt/live/${cert_name}/privkey.pem" "${certbot_rsa_key_size}"
181184

182185
# Create a certificate signing request from the private key.
183186
info "Generating certificate signing request for '${cert_name}'"
184187
openssl req -new -config <(printf "%s\n" \
185188
"${openssl_cnf}" \
186189
"[ dn_section ]" \
187190
"commonName = ${cert_name}" \
188-
"emailAddress = ${CERTBOT_EMAIL}" \
191+
"emailAddress = ${certbot_email}" \
189192
) \
190193
-key "/etc/letsencrypt/live/${cert_name}/privkey.pem" \
191194
-out "${LOCAL_CA_DIR}/${cert_name}.csr"
@@ -217,42 +220,79 @@ get_certificate() {
217220
# time this script is invoked.
218221
generate_ca
219222

220-
# Get all the cert names for which we should create certificates for, along
221-
# with the corresponding server names.
222-
#
223-
# This will return an associative array that looks something like this:
224-
# "cert_name" => "server_name1 server_name2"
225-
declare -A certificates
226-
for conf_file in /etc/nginx/conf.d/*.conf*; do
227-
parse_config_file "${conf_file}" certificates
228-
done
229-
230-
# Iterate over each key and create a signed certificate for them.
231-
for cert_name in "${!certificates[@]}"; do
232-
server_names=(${certificates["$cert_name"]})
233-
234-
# Assemble the list of domains to be included in the request.
235-
ip_count=0
236-
dns_count=0
237-
alt_names=()
223+
# Assemble the list of domains to be included in the request.
224+
# $@: All domain name variants
225+
assemble_alt_names() {
226+
local server_names=("${@}")
227+
local ip_count=0
228+
local dns_count=0
229+
local alt_names=()
238230
for server_name in "${server_names[@]}"; do
239231
if is_ip "${server_name}"; then
240232
# See if the alt name looks like an IP address.
241-
ip_count=$((${ip_count} + 1))
233+
ip_count=$((ip_count + 1))
242234
alt_names+=("IP.${ip_count}=${server_name}")
243235
else
244236
# Else we suppose this is a valid DNS name.
245-
dns_count=$((${dns_count} + 1))
237+
dns_count=$((dns_count + 1))
246238
alt_names+=("DNS.${dns_count}=${server_name}")
247239
fi
248240
done
241+
echo "${alt_names[@]}"
242+
}
249243

250-
# Hand over all the info required for the certificate request, and
251-
# let the local CA handle the rest.
252-
if ! get_certificate "${cert_name}" "${alt_names[@]}"; then
253-
error "Local CA failed for '${cert_name}'. Check the logs for details."
254-
fi
255-
done
244+
# Get all the cert names for which we should create certificates for, along
245+
# with the corresponding server names.
246+
if [ -f "${CONFIG_FILE}" ] && shyaml -q get-value certificates < "${CONFIG_FILE}"; then
247+
debug "Using config file '${CONFIG_FILE}' for certificate specifications"
248+
# Loop over the certificates array and request the certificates
249+
while read -r -d '' cert; do
250+
debug "Parsing certificate specification"
251+
cert_name="$(shyaml get-value name '' <<<"${cert}")"
252+
if [ -z "${cert_name}" ]; then
253+
error "'name' is missing; ignoring this certificate specification"
254+
continue
255+
fi
256+
debug "Certificate name is: ${cert_name}"
257+
domains=()
258+
while read -r -d '' domain; do
259+
domains+=("${domain}")
260+
done < <(shyaml get-values-0 domains '' <<<"${cert}")
261+
if [ "${#domains[@]}" -eq 0 ]; then
262+
error "'domains' are missing; ignoring this certificate specification"
263+
continue
264+
fi
265+
debug "Certificate domains are is: ${domains[*]}"
266+
267+
# Assemble the list of domains to be included in the request.
268+
read -ra alt_names < <(assemble_alt_names "${domains[@]}")
269+
# Hand over all the info required for the certificate request, and
270+
# let the local CA handle the rest.
271+
if ! get_certificate "${cert_name}" "${alt_names[@]}"; then
272+
error "Local CA failed for '${cert_name}'. Check the logs for details."
273+
fi
274+
done < <(shyaml -y get-values-0 certificates '' < "${CONFIG_FILE}")
275+
else
276+
debug "Using automatic discovery of nginx conf file for certificate specifications"
277+
# This will return an associative array that looks something like this:
278+
# "cert_name" => "server_name1 server_name2"
279+
declare -A certificates
280+
for conf_file in /etc/nginx/conf.d/*.conf*; do
281+
parse_config_file "${conf_file}" certificates
282+
done
283+
284+
# Iterate over each key and create a signed certificate for them.
285+
for cert_name in "${!certificates[@]}"; do
286+
server_names=("${certificates["$cert_name"]}")
287+
# Assemble the list of domains to be included in the request.
288+
read -ra alt_names < <(assemble_alt_names "${server_names[@]}")
289+
# Hand over all the info required for the certificate request, and
290+
# let the local CA handle the rest.
291+
if ! get_certificate "${cert_name}" "${alt_names[@]}"; then
292+
error "Local CA failed for '${cert_name}'. Check the logs for details."
293+
fi
294+
done
295+
fi
256296

257297
# After trying to sign all of the certificates, auto enable any configs that we
258298
# did indeed succeed with.

0 commit comments

Comments
 (0)