]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: acme: add the global option 'acme.scheduler'
authorWilliam Lallemand <wlallemand@haproxy.com>
Fri, 9 May 2025 11:45:48 +0000 (13:45 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Fri, 9 May 2025 12:00:39 +0000 (14:00 +0200)
The automatic scheduler is useful but sometimes you don't want to use,
or schedule manually.

This patch adds an 'acme.scheduler' option in the global section, which
can be set to either 'auto' or 'off'. (auto is the default value)

This also change the ouput of the 'acme status' command so it does not
shows scheduled values. The state will be 'Stopped' instead of
'Scheduled'.

doc/configuration.txt
include/haproxy/ssl_sock-t.h
src/acme.c
src/ssl_sock.c

index 7c17f54080b151ad0f244a9020baadaceae14313..3acf5c15e67ada884935ffcb9d01a826afee452b 100644 (file)
@@ -1824,6 +1824,18 @@ The following keywords are supported in the "global" section :
   Please note that this option is only available when HAProxy has been
   compiled with USE_51DEGREES and 51DEGREES_VER=4.
 
+acme.scheduler { auto | off }
+  Enable or disable the ACME scheduler.
+
+  The ACME scheduler starts at HAProxy startup, it will loop over the
+  certificates and start an ACME renewal task when the notAfter value is past
+  curtime + (notAfter - notBefore) / 12, or 7 days if notBefore is not defined.
+  The scheduler will then sleep and wakeup after 12 hours.
+
+  The default value is "auto".
+
+  See also: acme
+
 ca-base <dir>
   Assigns a default directory to fetch SSL CA certificates and CRLs from when a
   relative path is used with "ca-file", "ca-verify-file" or "crl-file"
index 2c7f73b3b17c96df64e0ef73c74eac6d0062288e..44055492b955c96626f9847f21aa97fa7a526ef5 100644 (file)
@@ -316,6 +316,10 @@ struct global_ssl {
                int disable;
        } ocsp_update;
 #endif
+
+#ifdef HAVE_ACME
+       int acme_scheduler;
+#endif
 };
 
 /* The order here matters for picking a default context,
index a49c621b3db68fb2daf642441a745e29f394e0f3..2700adf5f38bdc0f5a08d1308cd6d4c8632e14ba 100644 (file)
@@ -411,6 +411,34 @@ out:
        return err_code;
 }
 
+/* parse 'acme.scheduler' option */
+static int cfg_parse_global_acme_sched(char **args, int section_type, struct proxy *curpx, const struct proxy *defpx,
+                                       const char *file, int linenum, char **err)
+{
+       int err_code = 0;
+
+       if (!*args[1]) {
+               memprintf(err, "parsing [%s:%d]: keyword '%s' in '%s' section requires an argument\n", file, linenum, args[0], cursection);
+               goto error;
+       }
+       if (alertif_too_many_args(1, file, linenum, args, &err_code))
+               goto error;
+
+       if (strcmp(args[1], "auto") == 0) {
+               global_ssl.acme_scheduler = 1;
+       } else if (strcmp(args[1], "off") == 0) {
+               global_ssl.acme_scheduler = 0;
+       } else {
+               memprintf(err, "parsing [%s:%d]: keyword '%s' in '%s' section requires either 'auto' or 'off' argument", file, linenum, args[0], cursection);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       return -1;
+}
+
 /* Initialize stuff once the section is parsed */
 static int cfg_postsection_acme()
 {
@@ -545,7 +573,7 @@ static int cfg_postparser_acme()
        }
 
 
-       if (acme_cfgs) {
+       if (acme_cfgs && global_ssl.acme_scheduler) {
                task = task_new_anywhere();
                if (!task) {
                        ret++;
@@ -589,6 +617,7 @@ static struct cfg_kw_list cfg_kws_acme = {ILH, {
        { CFG_ACME, "bits",  cfg_parse_acme_cfg_key },
        { CFG_ACME, "curves",  cfg_parse_acme_cfg_key },
        { CFG_ACME, "map",  cfg_parse_acme_kws },
+       { CFG_GLOBAL, "acme.scheduler", cfg_parse_global_acme_sched },
        { 0, NULL, NULL },
 }};
 
@@ -2054,6 +2083,9 @@ time_t acme_schedule_date(struct ckch_store *store)
        time_t notAfter = 0;
        time_t notBefore = 0;
 
+       if (!global_ssl.acme_scheduler)
+               return 0;
+
        /* compute the validity period of the leaf certificate */
        if (!store->data || !store->data->cert)
                return 0;
@@ -2347,12 +2379,18 @@ static int cli_acme_status_io_handler(struct appctx *appctx)
 
                if (store->conf.acme.id) {
                        char str[50] = {};
-                       char *state = "Scheduled";
+                       char *state;
                        time_t notAfter = 0;
                        time_t sched = 0;
                        time_t remain = 0;
+                       int running = !!store->acme_task;
 
-                       if (store->acme_task)
+                       if (global_ssl.acme_scheduler)
+                               state = "Scheduled";
+                       else
+                               state = "Stopped";
+
+                       if (running)
                                state = "Running";
 
                        chunk_appendf(&trash, "%s\t%s\t%s\t", store->path, store->conf.acme.id, state);
@@ -2367,12 +2405,16 @@ static int cli_acme_status_io_handler(struct appctx *appctx)
 
                        /* Scheduled time */
                        remain = 0;
-                       sched = acme_schedule_date(store);
+                       if (!running) /* if running no schedule date yet */
+                               sched = acme_schedule_date(store);
                        if (sched > date.tv_sec)
                                remain = sched - date.tv_sec;
                        strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%SZ", gmtime(&sched));
-                       chunk_appendf(&trash, "%s\t", str);
-                       chunk_appendf(&trash, "%lud %luh%02lum%02lus\n", remain / 86400, (remain % 86400) / 3600, (remain % 3600) / 60, (remain % 60));
+                       chunk_appendf(&trash, "%s\t", sched ? str : "-");
+                       if (sched)
+                               chunk_appendf(&trash, "%lud %luh%02lum%02lus\n", remain / 86400, (remain % 86400) / 3600, (remain % 3600) / 60, (remain % 60));
+                       else
+                               chunk_appendf(&trash, "%s\n", "-");
 
                        if (applet_putchk(appctx, &trash) == -1)
                                return 1;
index 793862b94fbc43354c7d59dc95fdfe900ebd9c58..e7f01bc84ffc407004626f6c2763707b9670fe06 100644 (file)
@@ -145,6 +145,10 @@ struct global_ssl global_ssl = {
        .ocsp_update.mode = SSL_SOCK_OCSP_UPDATE_OFF,
        .ocsp_update.disable = 0,
 #endif
+#ifdef HAVE_ACME
+       .acme_scheduler = 1,
+#endif
+
 };
 
 static BIO_METHOD *ha_meth;