[__letsencrypt_cert] Revamp explorers, add locking.
This would fix #839 Certbot uses locking [1] even for read-only operations and does not properly use exit codes, which means that sometimes it would print: "Another instance of Certbot is already running" and exit with success. However, the previous explorers would take that as the certificate being absent and would trigger code generation. The issue was made worse by having many explorers running certbot, so for N certificates, we'd run certbot N*4 times, potentially "in parallel". [1]: https://certbot.eff.org/docs/using.html#id5 This patch joins all explorers in one to avoid starting multiple remote python processes and uses a cdist-specific lock in /tmp/certbot.cdist.lock with a 60 seconds timeout. It has been tested with certbot 0.31.0 and 0.17 that the: from certbot.main import main trick works. It is somewhat well documented so it can be somewhat relied upon.
This commit is contained in:
parent
3a25b80466
commit
a696f3cf00
7 changed files with 87 additions and 42 deletions
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
command -v certbot 2>/dev/null || true
|
|
78
cdist/conf/type/__letsencrypt_cert/explorer/certificate-data
Executable file
78
cdist/conf/type/__letsencrypt_cert/explorer/certificate-data
Executable file
|
@ -0,0 +1,78 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
certbot_path="$(command -v certbot 2>/dev/null || true)"
|
||||||
|
# Defaults
|
||||||
|
certificate_exists="no"
|
||||||
|
certificate_is_test="no"
|
||||||
|
|
||||||
|
if [ -n "${certbot_path}" ]; then
|
||||||
|
# Find python executable that has access to certbot's module
|
||||||
|
python_path=$(sed -n '1s/^#! *//p' "${certbot_path}")
|
||||||
|
|
||||||
|
# Use a lock for cdist due to certbot not exiting with failure
|
||||||
|
# or having any flags for concurrent use.
|
||||||
|
_certbot() {
|
||||||
|
${python_path} - 2>/dev/null <<EOF
|
||||||
|
from certbot.main import main
|
||||||
|
import fcntl
|
||||||
|
lock_file = "/tmp/certbot.cdist.lock"
|
||||||
|
timeout=60
|
||||||
|
with open(lock_file, 'w') as fd:
|
||||||
|
for i in range(timeout):
|
||||||
|
try:
|
||||||
|
# Get exclusive lock
|
||||||
|
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
# Wait if that fails
|
||||||
|
import time
|
||||||
|
time.sleep(1)
|
||||||
|
else:
|
||||||
|
# Timed out, exit with failure
|
||||||
|
import sys
|
||||||
|
sys.exit(1)
|
||||||
|
# Do list certificates
|
||||||
|
main(["certificates", "--cert-name", "${__object_id:?}"])
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_certificate_exists() {
|
||||||
|
if grep -q " Certificate Name: ${__object_id:?}$"; then
|
||||||
|
echo yes
|
||||||
|
else
|
||||||
|
echo no
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_certificate_is_test() {
|
||||||
|
if grep -q 'INVALID: TEST_CERT'; then
|
||||||
|
echo yes
|
||||||
|
else
|
||||||
|
echo no
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_certificate_domains() {
|
||||||
|
grep ' Domains: ' | cut -d ' ' -f 6- | tr ' ' '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get data about all available certificates
|
||||||
|
certificates="$(_certbot)"
|
||||||
|
|
||||||
|
# Check whether or not the certificate exists
|
||||||
|
certificate_exists="$(echo "${certificates}" | _certificate_exists)"
|
||||||
|
|
||||||
|
# Check whether or not the certificate is for testing
|
||||||
|
certificate_is_test="$(echo "${certificates}" | _certificate_is_test)"
|
||||||
|
|
||||||
|
# Get domains for certificate
|
||||||
|
certificate_domains="$(echo "${certificates}" | _certificate_domains)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Return received data
|
||||||
|
cat <<EOF
|
||||||
|
certbot_path:${certbot_path}
|
||||||
|
certificate_exists:${certificate_exists}
|
||||||
|
certificate_is_test:${certificate_is_test}
|
||||||
|
${certificate_domains}
|
||||||
|
EOF
|
|
@ -1,8 +0,0 @@
|
||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
certbot_path=$("${__type_explorer}/certbot-path")
|
|
||||||
if [ -n "${certbot_path}" ]
|
|
||||||
then
|
|
||||||
certbot certificates --cert-name "${__object_id:?}" | grep ' Domains: ' | \
|
|
||||||
cut -d ' ' -f 6- | tr ' ' '\n'
|
|
||||||
fi
|
|
|
@ -1,13 +0,0 @@
|
||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
certbot_path=$("${__type_explorer}/certbot-path")
|
|
||||||
if [ -n "${certbot_path}" ]
|
|
||||||
then
|
|
||||||
if certbot certificates | grep -q " Certificate Name: ${__object_id:?}$"; then
|
|
||||||
echo yes
|
|
||||||
else
|
|
||||||
echo no
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo no
|
|
||||||
fi
|
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/sh -e
|
|
||||||
|
|
||||||
certbot_path=$("${__type_explorer}/certbot-path")
|
|
||||||
if [ -n "${certbot_path}" ]
|
|
||||||
then
|
|
||||||
if certbot certificates --cert-name "${__object_id:?}" | \
|
|
||||||
grep -q 'INVALID: TEST_CERT'; then
|
|
||||||
echo yes
|
|
||||||
else
|
|
||||||
echo no
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo no
|
|
||||||
fi
|
|
|
@ -1,6 +1,10 @@
|
||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
|
||||||
certificate_exists=$(cat "${__object:?}/explorer/certificate-exists")
|
_explorer_var() {
|
||||||
|
grep "^$1:" "${__object:?}/explorer/certificate-data" | cut -d ':' -f 2-
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate_exists="$(_explorer_var certificate_exists)"
|
||||||
name="${__object_id:?}"
|
name="${__object_id:?}"
|
||||||
state=$(cat "${__object}/parameter/state")
|
state=$(cat "${__object}/parameter/state")
|
||||||
|
|
||||||
|
@ -29,8 +33,9 @@ case "${state}" in
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${certificate_exists}" = "yes" ]; then
|
if [ "${certificate_exists}" = "yes" ]; then
|
||||||
existing_domains="${__object}/explorer/certificate-domains"
|
existing_domains=$(mktemp "${TMPDIR:-/tmp}/existing_domains.cdist.XXXXXXXXXX")
|
||||||
certificate_is_test=$(cat "${__object}/explorer/certificate-is-test")
|
tail -n +4 "${__object:?}/explorer/certificate-data" | grep -v '^$' > "${existing_domains}"
|
||||||
|
certificate_is_test="$(_explorer_var certificate_is_test)"
|
||||||
|
|
||||||
sort -uo "${requested_domains}" "${requested_domains}"
|
sort -uo "${requested_domains}" "${requested_domains}"
|
||||||
sort -uo "${existing_domains}" "${existing_domains}"
|
sort -uo "${existing_domains}" "${existing_domains}"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
certbot_fullpath="$(cat "${__object:?}/explorer/certbot-path")"
|
certbot_fullpath="$(grep "^certbot_path:" "${__object:?}/explorer/certificate-data" | cut -d ':' -f 2-)"
|
||||||
state=$(cat "${__object}/parameter/state")
|
state=$(cat "${__object}/parameter/state")
|
||||||
os="$(cat "${__global:?}/explorer/os")"
|
os="$(cat "${__global:?}/explorer/os")"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue