uacme: add use_auto_staging
authorLeonardo Mörlein <git@irrelefant.net>
Sun, 11 Apr 2021 23:30:48 +0000 (01:30 +0200)
committerRosen Penev <rosenp@gmail.com>
Sat, 24 Apr 2021 08:16:57 +0000 (01:16 -0700)
Staging certificates have the advantage that their retry limits are loose.
Therefore they can be obtained quickly when automatic retries are used.
Unfortunately they can not be used for deployments because their CA is not
accepted by clients. Production certificates do not have this limitation, but
their retry limits are strict. For production certificates, automatic retries
can only be performed a few times per hour. This makes automatic obtainment of
certificates tenacious.

With use_auto_staging=1, the advantages of the two certificate types are
combined. Uacme will first obtain a staging certificate. When the staging
certificate is successfully obtained, uacme will switch and obtain a production
certificate. Since the staging certificate has already been successfully
obtained, we can ensure that the production certificate is successfully
obtained in the first attempt. This means that "retries" are performed on the
staging certificate and the production certificate is obtained in the first
attempt.

In summary, this feature enables fast obtaining of production certificates when
automatic retries are used.

By default, this feature is set to use_auto_staging=0, which means that
uacme will behave as before by default.

Signed-off-by: Leonardo Mörlein <git@irrelefant.net>
net/uacme/files/run.sh

index 247e563bcd2e147dd431c0af90e5c81c71c33e9d..556bcc2f9f8c38963a4e1004e61b7720635d299e 100644 (file)
@@ -407,12 +407,17 @@ issue_cert_with_retries() {
        local section="$1"
        local use_staging
        local retries
+       local use_auto_staging
        local infinite_retries
        config_get_bool use_staging "$section" use_staging
+       config_get_bool use_auto_staging "$section" use_auto_staging
+       config_get_bool enabled "$section" enabled
        config_get retries "$section" retries
 
        [ -z "$retries" ] && retries=1
+       [ -z "$use_auto_staging" ] && use_auto_staging=0
        [ "$retries" -eq "0" ] && infinite_retries=1
+       [ "$enabled" -eq "1" ] || return 0
 
        while true; do
                issue_cert "$1"; ret=$?
@@ -421,6 +426,13 @@ issue_cert_with_retries() {
                        # An error occurred while retrieving the certificate.
                        retries="$((retries-1))"
 
+                       if [ "$use_auto_staging" -eq "1" ] && [ "$use_staging" -eq "0" ]; then
+                               log "Production certificate could not be obtained. Switching to staging server."
+                               use_staging=1
+                               uci set "acme.$1.use_staging=1"
+                               uci commit acme
+                       fi
+
                        if [ -z "$infinite_retries" ] && [ "$retries" -lt "1" ]; then
                                log "An error occurred while retrieving the certificate. Retries exceeded."
                                return "$ret"
@@ -442,7 +454,19 @@ issue_cert_with_retries() {
                        sleep "$sleeptime"
                        continue
                else
-                       return "$ret";
+                       if [ "$use_auto_staging" -eq "1" ]; then
+                               if [ "$use_staging" -eq "0" ]; then
+                                       log "Production certificate obtained. Exiting."
+                               else
+                                       log "Staging certificate obtained. Continuing with production server."
+                                       use_staging=0
+                                       uci set "acme.$1.use_staging=0"
+                                       uci commit acme
+                                       continue
+                               fi
+                       fi
+
+                       return "$ret"
                fi
        done
 }