MINOR: acme: add the global option 'acme.scheduler'

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'.
This commit is contained in:
William Lallemand 2025-05-09 13:45:48 +02:00
parent 0ae14beb2a
commit e7574cd5f0
4 changed files with 68 additions and 6 deletions

View 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"

View 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,

View 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;

View 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;