From 40e6fb737cf86b71e6e40417bf22a7558a2955c9 Mon Sep 17 00:00:00 2001 From: Tomas Barton Date: Thu, 30 Mar 2023 10:35:55 +0200 Subject: [PATCH] Avoid race condition when renewing certificates Only single certificate can be processed at the same time. Make sure to obtain exclusive lock before executing renewal command. --- files/certbot_lock.sh | 14 ++++++++++++++ manifests/init.pp | 6 ++++++ templates/renew-script.sh.erb | 5 +++++ 3 files changed, 25 insertions(+) create mode 100644 files/certbot_lock.sh diff --git a/files/certbot_lock.sh b/files/certbot_lock.sh new file mode 100644 index 00000000..0f27f86f --- /dev/null +++ b/files/certbot_lock.sh @@ -0,0 +1,14 @@ +# Managed by Puppet +LOCKFILE="/var/lock/certbot" +LOCKFD=99 +# private +function _lock() { flock "$@" $LOCKFD; } +function _release_lock() { _lock -u; _lock -xn && rm -f $LOCKFILE; } +function _prepare_lock() { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _release_lock EXIT; } + +# on start +_prepare_lock + +# public +function exlock() { _lock -x --timeout 30; } # obtain an exclusive lock +function unlock() { _lock -u; } # drop a lock diff --git a/manifests/init.pp b/manifests/init.pp index d5a4c989..64afa31c 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -92,6 +92,12 @@ contain letsencrypt::renew + file { '/usr/share/certbot_lock.sh': + ensure => file, + mode => '0544', + content => file("${module_name}/certbot_lock.sh"), + } + $certificates.each |$certificate, $properties| { letsencrypt::certonly { $certificate: * => $properties } } diff --git a/templates/renew-script.sh.erb b/templates/renew-script.sh.erb index a77cde55..28d4e6e2 100644 --- a/templates/renew-script.sh.erb +++ b/templates/renew-script.sh.erb @@ -2,4 +2,9 @@ <%- @environment.each do |environment| -%> export <%= environment %> <%- end -%> +if [ -f '/usr/share/certbot_lock.sh' ]; then + . '/usr/share/misc/certbot_lock.sh' +fi +exlock <%= @cron_cmd %> +unlock