Skip to content

Commit bcaefd1

Browse files
authored
Merge pull request #590 from buchdag/acmev2
Switch to ACME v2
2 parents c5b3715 + 2d41861 commit bcaefd1

File tree

9 files changed

+85
-59
lines changed

9 files changed

+85
-59
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
It handles the automated creation, renewal and use of Let's Encrypt certificates for proxyed Docker containers.
1010

11-
Please note that [letsencrypt-nginx-proxy-companion does not work with ACME v2 endpoints yet](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/issues/319).
11+
Please note that **letsencrypt-nginx-proxy-companion** no longer supports ACME v1 endpoints. The last tagged version that supports ACME v1 is [v1.11](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion/releases/tag/v1.11.2).
1212

1313
### Features:
1414
* Automated creation/renewal of Let's Encrypt (or other ACME CAs) certificates using [**simp_le**](https://github.com/zenhack/simp_le).

app/entrypoint.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,11 @@ function check_default_cert_key {
135135
source /app/functions.sh
136136

137137
if [[ "$*" == "/bin/bash /app/start.sh" ]]; then
138-
acmev2_re='https://acme-.*v02\.api\.letsencrypt\.org/directory'
139-
if [[ "${ACME_CA_URI:-}" =~ $acmev2_re ]]; then
140-
echo "Error: ACME v2 API is not yet supported by simp_le."
141-
echo "See https://github.com/zenhack/simp_le/issues/101"
138+
acmev1_r='acme-(v01\|staging)\.api\.letsencrypt\.org'
139+
if [[ "${ACME_CA_URI:-}" =~ $acmev1_r ]]; then
140+
echo "Error: the ACME v1 API is no longer supported by simp_le."
141+
echo "See https://github.com/zenhack/simp_le/pull/119"
142+
echo "Please use one of Let's Encrypt ACME v2 endpoints instead."
142143
exit 1
143144
fi
144145
check_docker_socket

app/functions.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ function set_ownership_and_permissions {
285285
return 1
286286
fi
287287

288+
[[ "$(lc $DEBUG)" == true ]] && echo "Debug: checking $path ownership and permissions."
289+
288290
# Find the user numeric ID if the FILES_UID environment variable isn't numeric.
289291
if [[ "$user" =~ ^[0-9]+$ ]]; then
290292
user_num="$user"
@@ -329,7 +331,7 @@ function set_ownership_and_permissions {
329331
fi
330332
# If the path is a file, check and modify permissions if required.
331333
elif [[ -f "$path" ]]; then
332-
# Use different permissions for private files (private keys and ACME account keys) ...
334+
# Use different permissions for private files (private keys and ACME account files) ...
333335
if [[ "$path" =~ ^.*(default\.key|key\.pem|\.json)$ ]]; then
334336
if [[ "$(stat -c %a "$path")" != "$f_perms" ]]; then
335337
[[ "$(lc $DEBUG)" == true ]] && echo "Debug: setting $path permissions to $f_perms."

app/letsencrypt_service

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
source /app/functions.sh
55

66
seconds_to_wait=3600
7-
ACME_CA_URI="${ACME_CA_URI:-https://acme-v01.api.letsencrypt.org/directory}"
7+
ACME_CA_URI="${ACME_CA_URI:-https://acme-v02.api.letsencrypt.org/directory}"
88
DEFAULT_KEY_SIZE=4096
99
REUSE_ACCOUNT_KEYS="$(lc ${REUSE_ACCOUNT_KEYS:-true})"
1010
REUSE_PRIVATE_KEYS="$(lc ${REUSE_PRIVATE_KEYS:-false})"
@@ -158,7 +158,7 @@ function update_certs {
158158
fi
159159

160160
test_certificate_varname="LETSENCRYPT_${cid}_TEST"
161-
le_staging_uri="https://acme-staging.api.letsencrypt.org/directory"
161+
le_staging_uri="https://acme-staging-v02.api.letsencrypt.org/directory"
162162
if [[ $(lc "${!test_certificate_varname:-}") == true ]] || \
163163
[[ "$ACME_CA_URI" == "$le_staging_uri" ]]; then
164164
# Use staging Let's Encrypt ACME end point
@@ -215,27 +215,39 @@ function update_certs {
215215
add_location_configuration "$domain" || reload_nginx
216216
done
217217

218-
# The ACME account key full path is derived from the endpoint URI
219-
# + the account alias (set to 'default' if no alias is provided)
220-
account_key_dir="../accounts/${acme_ca_uri#*://}"
221-
account_key_full_path="${account_key_dir}/${account_alias}.json"
218+
if [[ -e "./account_key.json" ]] && [[ ! -e "./account_reg.json" ]]; then
219+
# If there is an account key present without account registration, this is
220+
# a leftover from the ACME v1 version of simp_le. Remove this account key.
221+
rm -f ./account_key.json
222+
[[ "$(lc $DEBUG)" == true ]] \
223+
&& echo "Debug: removed ACME v1 account key $certificate_dir/account_key.json"
224+
fi
225+
226+
# The ACME account key and registration full path are derived from the
227+
# endpoint URI + the account alias (set to 'default' if no alias is provided)
228+
account_dir="../accounts/${acme_ca_uri#*://}"
222229
if [[ $REUSE_ACCOUNT_KEYS == true ]]; then
223-
if [[ -f "$account_key_full_path" ]]; then
224-
# If there is no symlink to the account key, create it
225-
if [[ ! -L ./account_key.json ]]; then
226-
ln -sf "$account_key_full_path" ./account_key.json \
227-
&& set_ownership_and_permissions ./account_key.json
228-
# If the symlink target the wrong account key, replace it
229-
elif [[ "$(readlink -f ./account_key.json)" != "$account_key_full_path" ]]; then
230-
ln -sf "$account_key_full_path" ./account_key.json \
231-
&& set_ownership_and_permissions ./account_key.json
230+
for type in "key" "reg"; do
231+
file_full_path="${account_dir}/${account_alias}_${type}.json"
232+
simp_le_file="./account_${type}.json"
233+
if [[ -f "$file_full_path" ]]; then
234+
# If there is no symlink to the account file, create it
235+
if [[ ! -L "$simp_le_file" ]]; then
236+
ln -sf "$file_full_path" "$simp_le_file" \
237+
&& set_ownership_and_permissions "$simp_le_file"
238+
# If the symlink target the wrong account file, replace it
239+
elif [[ "$(readlink -f "$simp_le_file")" != "$file_full_path" ]]; then
240+
ln -sf "$file_full_path" "$simp_le_file" \
241+
&& set_ownership_and_permissions "$simp_le_file"
242+
fi
232243
fi
233-
fi
244+
done
234245
fi
235246

236247
echo "Creating/renewal $base_domain certificates... (${hosts_array_expanded[*]})"
237248
/usr/bin/simp_le \
238-
-f account_key.json -f key.pem -f chain.pem -f fullchain.pem -f cert.pem \
249+
-f account_key.json -f account_reg.json \
250+
-f key.pem -f chain.pem -f fullchain.pem -f cert.pem \
239251
$params_d_str \
240252
--cert_key_size=$cert_keysize \
241253
--server=$acme_ca_uri \
@@ -244,13 +256,17 @@ function update_certs {
244256
simp_le_return=$?
245257

246258
if [[ $REUSE_ACCOUNT_KEYS == true ]]; then
247-
# If the account key to be reused does not exist yet, copy it
248-
# from the CWD and replace the file in CWD with a symlink
249-
if [[ ! -f "$account_key_full_path" && -f ./account_key.json ]]; then
250-
mkdir -p "$account_key_dir"
251-
cp ./account_key.json "$account_key_full_path"
252-
ln -sf "$account_key_full_path" ./account_key.json
253-
fi
259+
mkdir -p "$account_dir"
260+
for type in "key" "reg"; do
261+
file_full_path="${account_dir}/${account_alias}_${type}.json"
262+
simp_le_file="./account_${type}.json"
263+
# If the account file to be reused does not exist yet, copy it
264+
# from the CWD and replace the file in CWD with a symlink
265+
if [[ ! -f "$file_full_path" && -f "$simp_le_file" ]]; then
266+
cp "$simp_le_file" "$file_full_path"
267+
ln -sf "$file_full_path" "$simp_le_file"
268+
fi
269+
done
254270
fi
255271

256272
popd || return
@@ -262,20 +278,21 @@ function update_certs {
262278
else
263279
create_links "$base_domain" "$domain" && should_reload_nginx='true' && should_restart_container='true'
264280
fi
265-
touch "${certificate_dir}/.companion"
266-
set_ownership_and_permissions "${certificate_dir}/.companion"
267281
done
268-
# Make private key root readable only
269-
for file in cert.pem key.pem chain.pem fullchain.pem account_key.json; do
282+
touch "${certificate_dir}/.companion"
283+
# Set ownership and permissions of the files inside $certificate_dir
284+
for file in .companion cert.pem key.pem chain.pem fullchain.pem account_key.json account_reg.json; do
270285
set_ownership_and_permissions "${certificate_dir}/${file}"
271286
done
272-
# Make the account key and its parent folders (up to
273-
# /etc/nginx/certs/accounts included) root readable only
274-
account_key_perm_path="/etc/nginx/certs/accounts/${acme_ca_uri#*://}/${account_alias}.json"
287+
# Set ownership and permissions of the ACME account key and its parent
288+
# folders (up to /etc/nginx/certs/accounts included)
289+
account_key_perm_path="/etc/nginx/certs/accounts/${acme_ca_uri#*://}/${account_alias}_key.json"
275290
until [[ "$account_key_perm_path" == /etc/nginx/certs ]]; do
276291
set_ownership_and_permissions "$account_key_perm_path"
277292
account_key_perm_path="$(dirname "$account_key_perm_path")"
278293
done
294+
# Set ownership and permissions of the ACME account registration
295+
set_ownership_and_permissions "/etc/nginx/certs/accounts/${acme_ca_uri#*://}/${account_alias}_reg.json"
279296
# Queue nginx reload if a certificate was issued or renewed
280297
[[ $simp_le_return -eq 0 ]] && should_reload_nginx='true' && should_restart_container='true'
281298
fi

install_simp_le.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ apk add --update python3 git gcc musl-dev libffi-dev python3-dev openssl-dev
1010
[[ -e /usr/bin/python ]] || ln -sf /usr/bin/python3 /usr/bin/python
1111

1212
# Get Let's Encrypt simp_le client source
13-
branch="0.14.0"
13+
branch="0.16.0"
1414
mkdir -p /src
1515
git -C /src clone --depth=1 --branch $branch https://github.com/zenhack/simp_le.git
1616

test/setup/setup-boulder.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
set -e
44

5-
acme_endpoint='http://boulder:4000/directory'
5+
acme_endpoint='http://boulder:4001/directory'
66

77
setup_boulder() {
88
export GOPATH=${TRAVIS_BUILD_DIR}/go
99
[[ ! -d $GOPATH/src/github.com/letsencrypt/boulder ]] \
1010
&& git clone https://github.com/letsencrypt/boulder \
1111
$GOPATH/src/github.com/letsencrypt/boulder
1212
pushd $GOPATH/src/github.com/letsencrypt/boulder
13-
git checkout release-2019-06-17
13+
git checkout release-2019-10-07
1414
if [[ "$(uname)" == 'Darwin' ]]; then
1515
# Set Standard Ports
1616
sed -i '' 's/ 5002/ 80/g' test/config/va.json

test/tests/permissions_custom/run.sh

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ wait_for_symlink "${domains[0]}" "$le_container_name"
4242
# Array of folder paths to test
4343
folders=( \
4444
[0]="/etc/nginx/certs/accounts" \
45-
[1]="/etc/nginx/certs/accounts/boulder:4000" \
46-
[2]="/etc/nginx/certs/accounts/boulder:4000/directory" \
45+
[1]="/etc/nginx/certs/accounts/boulder:4001" \
46+
[2]="/etc/nginx/certs/accounts/boulder:4001/directory" \
4747
[3]="/etc/nginx/certs/${domains[0]}" \
4848
)
4949

@@ -62,6 +62,7 @@ symlinks=( \
6262
[2]="/etc/nginx/certs/${domains[0]}.chain.pem" \
6363
[3]="/etc/nginx/certs/${domains[0]}.dhparam.pem" \
6464
[4]="/etc/nginx/certs/${domains[0]}/account_key.json" \
65+
[5]="/etc/nginx/certs/${domains[0]}/account_reg.json" \
6566
)
6667

6768
# Test symlinks paths
@@ -75,8 +76,9 @@ symlinks=( \
7576
# Array of private file paths to test
7677
private_files=( \
7778
[0]="/etc/nginx/certs/default.key" \
78-
[1]="/etc/nginx/certs/accounts/boulder:4000/directory/default.json" \
79-
[2]="/etc/nginx/certs/${domains[0]}/key.pem" \
79+
[1]="/etc/nginx/certs/accounts/boulder:4001/directory/default_key.json" \
80+
[2]="/etc/nginx/certs/accounts/boulder:4001/directory/default_reg.json" \
81+
[3]="/etc/nginx/certs/${domains[0]}/key.pem" \
8082
)
8183

8284
# Test private file paths
@@ -89,11 +91,12 @@ done
8991

9092
# Array of public files paths to test
9193
public_files=( \
92-
[0]="/etc/nginx/certs/${domains[0]}/cert.pem" \
93-
[1]="/etc/nginx/certs/${domains[0]}/chain.pem" \
94-
[2]="/etc/nginx/certs/${domains[0]}/fullchain.pem" \
95-
[3]="/etc/nginx/certs/default.crt" \
96-
[4]="/etc/nginx/certs/dhparam.pem" \
94+
[0]="/etc/nginx/certs/${domains[0]}/.companion" \
95+
[1]="/etc/nginx/certs/${domains[0]}/cert.pem" \
96+
[2]="/etc/nginx/certs/${domains[0]}/chain.pem" \
97+
[3]="/etc/nginx/certs/${domains[0]}/fullchain.pem" \
98+
[4]="/etc/nginx/certs/default.crt" \
99+
[5]="/etc/nginx/certs/dhparam.pem" \
97100
)
98101

99102
# Test public file paths

test/tests/permissions_default/run.sh

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ wait_for_symlink "${domains[0]}" "$le_container_name"
3636
# Array of folder paths to test
3737
folders=( \
3838
[0]="/etc/nginx/certs/accounts" \
39-
[1]="/etc/nginx/certs/accounts/boulder:4000" \
40-
[2]="/etc/nginx/certs/accounts/boulder:4000/directory" \
39+
[1]="/etc/nginx/certs/accounts/boulder:4001" \
40+
[2]="/etc/nginx/certs/accounts/boulder:4001/directory" \
4141
[3]="/etc/nginx/certs/${domains[0]}" \
4242
)
4343

@@ -56,6 +56,7 @@ symlinks=( \
5656
[2]="/etc/nginx/certs/${domains[0]}.chain.pem" \
5757
[3]="/etc/nginx/certs/${domains[0]}.dhparam.pem" \
5858
[4]="/etc/nginx/certs/${domains[0]}/account_key.json" \
59+
[5]="/etc/nginx/certs/${domains[0]}/account_reg.json" \
5960
)
6061

6162
# Test symlinks paths
@@ -69,8 +70,9 @@ symlinks=( \
6970
# Array of private file paths to test
7071
private_files=( \
7172
[0]="/etc/nginx/certs/default.key" \
72-
[1]="/etc/nginx/certs/accounts/boulder:4000/directory/default.json" \
73-
[2]="/etc/nginx/certs/${domains[0]}/key.pem" \
73+
[1]="/etc/nginx/certs/accounts/boulder:4001/directory/default_key.json" \
74+
[2]="/etc/nginx/certs/accounts/boulder:4001/directory/default_reg.json" \
75+
[3]="/etc/nginx/certs/${domains[0]}/key.pem" \
7476
)
7577

7678
# Test private file paths
@@ -83,11 +85,12 @@ done
8385

8486
# Array of public files paths to test
8587
public_files=( \
86-
[0]="/etc/nginx/certs/${domains[0]}/cert.pem" \
87-
[1]="/etc/nginx/certs/${domains[0]}/chain.pem" \
88-
[2]="/etc/nginx/certs/${domains[0]}/fullchain.pem" \
89-
[3]="/etc/nginx/certs/default.crt" \
90-
[4]="/etc/nginx/certs/dhparam.pem" \
88+
[0]="/etc/nginx/certs/${domains[0]}/.companion" \
89+
[1]="/etc/nginx/certs/${domains[0]}/cert.pem" \
90+
[2]="/etc/nginx/certs/${domains[0]}/chain.pem" \
91+
[3]="/etc/nginx/certs/${domains[0]}/fullchain.pem" \
92+
[4]="/etc/nginx/certs/default.crt" \
93+
[5]="/etc/nginx/certs/dhparam.pem" \
9194
)
9295

9396
# Test public file paths

test/tests/test-functions.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function run_le_container {
2424
$cli_args \
2525
--env "DHPARAM_BITS=256" \
2626
--env "DEBUG=true" \
27-
--env "ACME_CA_URI=http://boulder:4000/directory" \
27+
--env "ACME_CA_URI=http://boulder:4001/directory" \
2828
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
2929
--network boulder_bluenet \
3030
"$image" > /dev/null && echo "Started letsencrypt container for test ${name%%_2*}"

0 commit comments

Comments
 (0)