mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-04-03 01:51:05 +02:00
MEDIUM: acme: split the initial delay from the retry DNS delay
The previous ACME_RSLV_WAIT state served a dual role: it applied the
initial dns-delay before the first DNS probe and also handled the
delay between retries. There was no way to simply wait a fixed delay
before submitting the challenge without also triggering DNS pre-checks.
Replace ACME_RSLV_WAIT with two distinct states:
- ACME_INITIAL_DELAY: an optional initial wait before proceeding,
only applied when "challenge-ready" includes the new "delay" keyword
- ACME_RSLV_RETRY_DELAY: the delay between resolution retries, always
applied when DNS pre-checks are in progress
The new "delay" keyword in "challenge-ready" can be used standalone
(wait then submit the challenge directly) or combined with "dns" (wait
then start the DNS pre-checks). When "delay" is not set, the first DNS
probe fires immediately.
Update the documentation accordingly.
This commit is contained in:
parent
6ca83eb731
commit
6df3662077
@ -32290,14 +32290,19 @@ challenge-ready <value>[,<value>]*
|
||||
option is independent of the CLI command, so no human intervention
|
||||
is required.
|
||||
|
||||
delay - apply an initial wait of "dns-delay" before proceeding. Without
|
||||
"dns", the challenge is submitted after the delay expires. When
|
||||
combined with "dns", the initial wait is applied before starting
|
||||
the DNS pre-checks.
|
||||
|
||||
none - no readiness condition; the challenge is submitted to the ACME
|
||||
server immediately without waiting for any external confirmation.
|
||||
This option cannot be combined with others.
|
||||
|
||||
Multiple values can be combined with a comma so that both conditions must be
|
||||
met. The order of the values is not significant. When "cli" and "dns" are
|
||||
combined, HAProxy first waits for the CLI confirmation before triggering the
|
||||
DNS propagation check.
|
||||
Multiple values can be combined with a comma. When several conditions are
|
||||
specified, HAProxy processes them in the following order: first it waits for
|
||||
the CLI confirmation ("cli"), then applies the initial delay ("delay"), then
|
||||
performs the DNS pre-checks ("dns").
|
||||
|
||||
This option is only compatible with the dns-01 challenge type.
|
||||
|
||||
@ -32322,9 +32327,20 @@ directory <string>
|
||||
directory https://acme-staging-v02.api.letsencrypt.org/directory
|
||||
|
||||
dns-delay <time>
|
||||
When "challenge-ready" includes "dns", configure the delay before the first
|
||||
DNS resolution attempt and between retries. The value is a time expressed in
|
||||
HAProxy time format (e.g. "5m", "300s"). Default is 30 seconds.
|
||||
Configure the delay used by "challenge-ready" conditions "delay" and "dns".
|
||||
The value is a time expressed in HAProxy time format (e.g. "5m", "300s").
|
||||
Default is 30 seconds.
|
||||
|
||||
Its role depends on the "challenge-ready" conditions in use:
|
||||
|
||||
delay - the challenge is submitted after this delay expires, without
|
||||
any DNS pre-check.
|
||||
|
||||
dns - the delay between two consecutive DNS resolution attempts.
|
||||
The first probe fires immediately without any initial wait.
|
||||
|
||||
dns+delay - the initial wait before the first DNS resolution attempt, and
|
||||
the delay between subsequent retries.
|
||||
|
||||
Note that the resolution goes through the configured "default" resolvers
|
||||
section, not the authoritative name servers. Results may therefore still be
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#define ACME_RDY_NONE 0x00
|
||||
#define ACME_RDY_CLI 0x01
|
||||
#define ACME_RDY_DNS 0x02
|
||||
#define ACME_RDY_DELAY 0x04
|
||||
|
||||
/* acme section configuration */
|
||||
struct acme_cfg {
|
||||
@ -52,7 +53,8 @@ enum acme_st {
|
||||
ACME_NEWORDER,
|
||||
ACME_AUTH,
|
||||
ACME_CLI_WAIT, /* wait for the ACME_RDY_CLI */
|
||||
ACME_RSLV_WAIT,
|
||||
ACME_INITIAL_DELAY,
|
||||
ACME_RSLV_RETRY_DELAY,
|
||||
ACME_RSLV_TRIGGER,
|
||||
ACME_RSLV_READY,
|
||||
ACME_CHALLENGE,
|
||||
|
||||
82
src/acme.c
82
src/acme.c
@ -115,22 +115,23 @@ static void acme_trace(enum trace_level level, uint64_t mask, const struct trace
|
||||
}
|
||||
chunk_appendf(&trace_buf, ", st: ");
|
||||
switch (ctx->state) {
|
||||
case ACME_RESOURCES: chunk_appendf(&trace_buf, "ACME_RESOURCES"); break;
|
||||
case ACME_NEWNONCE: chunk_appendf(&trace_buf, "ACME_NEWNONCE"); break;
|
||||
case ACME_CHKACCOUNT: chunk_appendf(&trace_buf, "ACME_CHKACCOUNT"); break;
|
||||
case ACME_NEWACCOUNT: chunk_appendf(&trace_buf, "ACME_NEWACCOUNT"); break;
|
||||
case ACME_NEWORDER: chunk_appendf(&trace_buf, "ACME_NEWORDER"); break;
|
||||
case ACME_AUTH: chunk_appendf(&trace_buf, "ACME_AUTH"); break;
|
||||
case ACME_CLI_WAIT : chunk_appendf(&trace_buf, "ACME_CLI_WAIT"); break;
|
||||
case ACME_RSLV_WAIT: chunk_appendf(&trace_buf, "ACME_RSLV_WAIT"); break;
|
||||
case ACME_RSLV_TRIGGER: chunk_appendf(&trace_buf, "ACME_RSLV_TRIGGER"); break;
|
||||
case ACME_RSLV_READY: chunk_appendf(&trace_buf, "ACME_RSLV_READY"); break;
|
||||
case ACME_CHALLENGE: chunk_appendf(&trace_buf, "ACME_CHALLENGE"); break;
|
||||
case ACME_CHKCHALLENGE: chunk_appendf(&trace_buf, "ACME_CHKCHALLENGE"); break;
|
||||
case ACME_FINALIZE: chunk_appendf(&trace_buf, "ACME_FINALIZE"); break;
|
||||
case ACME_CHKORDER: chunk_appendf(&trace_buf, "ACME_CHKORDER"); break;
|
||||
case ACME_CERTIFICATE: chunk_appendf(&trace_buf, "ACME_CERTIFICATE"); break;
|
||||
case ACME_END: chunk_appendf(&trace_buf, "ACME_END"); break;
|
||||
case ACME_RESOURCES: chunk_appendf(&trace_buf, "ACME_RESOURCES"); break;
|
||||
case ACME_NEWNONCE: chunk_appendf(&trace_buf, "ACME_NEWNONCE"); break;
|
||||
case ACME_CHKACCOUNT: chunk_appendf(&trace_buf, "ACME_CHKACCOUNT"); break;
|
||||
case ACME_NEWACCOUNT: chunk_appendf(&trace_buf, "ACME_NEWACCOUNT"); break;
|
||||
case ACME_NEWORDER: chunk_appendf(&trace_buf, "ACME_NEWORDER"); break;
|
||||
case ACME_AUTH: chunk_appendf(&trace_buf, "ACME_AUTH"); break;
|
||||
case ACME_CLI_WAIT : chunk_appendf(&trace_buf, "ACME_CLI_WAIT"); break;
|
||||
case ACME_INITIAL_DELAY: chunk_appendf(&trace_buf, "ACME_INITIAL_DELAY"); break;
|
||||
case ACME_RSLV_RETRY_DELAY: chunk_appendf(&trace_buf, "ACME_RSLV_RETRY_DELAY"); break;
|
||||
case ACME_RSLV_TRIGGER: chunk_appendf(&trace_buf, "ACME_RSLV_TRIGGER"); break;
|
||||
case ACME_RSLV_READY: chunk_appendf(&trace_buf, "ACME_RSLV_READY"); break;
|
||||
case ACME_CHALLENGE: chunk_appendf(&trace_buf, "ACME_CHALLENGE"); break;
|
||||
case ACME_CHKCHALLENGE: chunk_appendf(&trace_buf, "ACME_CHKCHALLENGE"); break;
|
||||
case ACME_FINALIZE: chunk_appendf(&trace_buf, "ACME_FINALIZE"); break;
|
||||
case ACME_CHKORDER: chunk_appendf(&trace_buf, "ACME_CHKORDER"); break;
|
||||
case ACME_CERTIFICATE: chunk_appendf(&trace_buf, "ACME_CERTIFICATE"); break;
|
||||
case ACME_END: chunk_appendf(&trace_buf, "ACME_END"); break;
|
||||
}
|
||||
}
|
||||
if (mask & (ACME_EV_REQ|ACME_EV_RES)) {
|
||||
@ -480,6 +481,9 @@ static int cfg_parse_acme_kws(char **args, int section_type, struct proxy *curpx
|
||||
} else if (strcmp(str, "dns") == 0) {
|
||||
/* wait for the DNS-check to run the challenge */
|
||||
cur_acme->cond_ready |= ACME_RDY_DNS;
|
||||
} else if (strcmp(str, "delay") == 0) {
|
||||
/* wait for the DNS-check to run the challenge */
|
||||
cur_acme->cond_ready |= ACME_RDY_DELAY;
|
||||
} else if (strcmp(str, "none") == 0) {
|
||||
if (cur_acme->cond_ready || (saveptr && *saveptr)) {
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
@ -2417,11 +2421,49 @@ re:
|
||||
goto wait;
|
||||
|
||||
/* next step */
|
||||
st = ACME_RSLV_WAIT;
|
||||
st = ACME_INITIAL_DELAY;
|
||||
goto nextreq;
|
||||
}
|
||||
break;
|
||||
case ACME_RSLV_WAIT: {
|
||||
case ACME_INITIAL_DELAY: {
|
||||
struct acme_auth *auth;
|
||||
int all_cond_ready = ctx->cfg->cond_ready;
|
||||
|
||||
for (auth = ctx->auths; auth != NULL; auth = auth->next) {
|
||||
all_cond_ready &= auth->ready;
|
||||
}
|
||||
|
||||
/* if everything is ready, let's do the challenge request */
|
||||
if ((all_cond_ready & ctx->cfg->cond_ready) == ctx->cfg->cond_ready) {
|
||||
st = ACME_CHALLENGE;
|
||||
goto nextreq;
|
||||
}
|
||||
|
||||
/* if we don't have an initial delay, let's trigger */
|
||||
if (!(ctx->cfg->cond_ready & ACME_RDY_DELAY)) {
|
||||
st = ACME_RSLV_TRIGGER;
|
||||
goto nextreq;
|
||||
}
|
||||
|
||||
for (auth = ctx->auths; auth != NULL; auth = auth->next) {
|
||||
auth->ready |= ACME_RDY_DELAY;
|
||||
}
|
||||
|
||||
/* either trigger the resolution of the challenge */
|
||||
if (ctx->cfg->cond_ready & ACME_RDY_DNS)
|
||||
st = ACME_RSLV_TRIGGER;
|
||||
else
|
||||
st = ACME_CHALLENGE;
|
||||
ctx->http_state = ACME_HTTP_REQ;
|
||||
ctx->state = st;
|
||||
send_log(NULL, LOG_NOTICE, "acme: %s: dns-01: waiting %ds\n",
|
||||
ctx->store->path, ctx->cfg->dns_delay);
|
||||
|
||||
task->expire = tick_add(now_ms, ctx->cfg->dns_delay * 1000);
|
||||
return task;
|
||||
}
|
||||
break;
|
||||
case ACME_RSLV_RETRY_DELAY: {
|
||||
struct acme_auth *auth;
|
||||
int all_cond_ready = ctx->cfg->cond_ready;
|
||||
|
||||
@ -2448,7 +2490,7 @@ re:
|
||||
st = ACME_RSLV_TRIGGER;
|
||||
ctx->http_state = ACME_HTTP_REQ;
|
||||
ctx->state = st;
|
||||
send_log(NULL, LOG_NOTICE, "acme: %s: dns-01: triggering the resolution in %ds\n",
|
||||
send_log(NULL, LOG_NOTICE, "acme: %s: dns-01: retrying the resolution in %ds\n",
|
||||
ctx->store->path, ctx->cfg->dns_delay);
|
||||
|
||||
task->expire = tick_add(now_ms, ctx->cfg->dns_delay * 1000);
|
||||
@ -2519,7 +2561,7 @@ re:
|
||||
}
|
||||
|
||||
/* not all ready yet, retry after dns-delay */
|
||||
st = ACME_RSLV_WAIT;
|
||||
st = ACME_RSLV_RETRY_DELAY;
|
||||
ctx->http_state = ACME_HTTP_REQ;
|
||||
ctx->state = st;
|
||||
goto nextreq;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user