A single dnsExchangeTimeout around CheckCAA let slow empty
answers at child names consume the budget before parent
policy was queried. Give each label its own exchange timeout
inside the climb instead.
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Keep the previous per-lookup dnsExchangeTimeout around CheckCAA
so rebased dnsclient calls do not drop main's deadline.
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Extract shared DNS checks into dnsclient and fail closed on
truncated or non-success CAA responses. Climb past eTLD+1,
validate RFC 8659 issue-value syntax, and map NXDOMAIN TXT
lookups to the pending-verification path.
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Custom-domain CNAME and SAML TXT checks accepted answers without
confirming the record owner matched the hostname being verified, so
an apex record could satisfy verification for a subdomain. CAA checks
also looked only at the exact hostname and ignored parent policy.
Add dnsverify helpers to compare owner names and walk from the
requested hostname up to the registrable apex for CAA (RFC 6844).
Require matching record owners for CNAME and TXT answers.
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Bryan FRIMIN <bryan@frimin.fr>
Operators could see that a rate-limit cooldown was active, but not
when it ends, and failure logs omitted most of the CA problem
document. Add a until-timestamp gauge and log the full acme.Error
surface so cooldowns and ACME responses are diagnosable.
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
Several race and validity gaps could leave certificate provisioning
stuck, unusable, or noisy:
- Accept the HTTP-01 challenge only after the key authorization is
committed, so the CA cannot hit the token before this instance can
serve it and invalidate the order.
- Persist challenge metadata under a blocking write-back lock; a row
merely locked by a competing transaction no longer silently drops the
accepted order.
- Abandon a recovered VALID order and restart instead of issuing it
with a freshly generated key that cannot match the existing cert.
- Exclude rate-limited rows from the ten-minute stale reset so the
resumable order survives the ACME cooldown.
- Size the provisioning poll lease to exceed the max processing window
so a released claim lock cannot let another worker process the same
row concurrently.
- Parse Retry-After as unsigned seconds and clamp overflow so malformed
values fall back to the default cooldown instead of disabling it.
- Normalize the acme_errors problem_type label to the RFC 8555 set to
bound Prometheus cardinality.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Address several provisioning defects that either stalled the retry
budget or crashed the process:
- Classify CAA resolver/transport failures apart from a real CAA policy
denial. Both shared the "caa records" wording, so a transient resolver
error was persisted as customer misconfiguration and retried forever
without consuming the retry budget. A new ErrCAANotPermitted sentinel
now marks the genuine misconfiguration; other CAA errors are treated
as ordinary transient failures.
- Honor an explicit Retry-After: 0 (or a past date) as permission for an
immediate retry instead of promoting it to the one-hour default
cooldown. acme.RateLimit collapses zero, invalid, and absent headers
to a zero duration, so the header is now parsed directly to tell an
explicit zero apart from a missing one.
- Reuse already-registered Prometheus collectors when a second
ACMEService shares a registerer. The fixed-name collectors were
MustRegistered, so a duplicate registration panicked the process.
- Persist provisioning failures on a context detached from the process
tick deadline. A timed-out attempt reached persistFailure with an
expired context, so the write-back failed and the retry budget never
advanced, leaving the certificate indefinitely retriable.
- Use pgx.StrictNamedArgs in the certificate FOR UPDATE loaders to match
the coredata SQL contract.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Rate limits no longer inflate ssl_retry_count into an instant FAILED
path. Centralize outcomes in decideProvisioningOutcome, keep ACME
order state on transient and rate-limit errors, bound each Process
tick with a timeout, and block on FOR UPDATE when persisting a
freshly issued certificate.
Signed-off-by: Ludovic Vielle <ludovic@probo.com>
Signed-off-by: Bryan Frimin <bryan@probo.com>
Host chmod cannot open 0700 dirs owned by UID 1000, so
`-f` never sees root_ca.crt. Chmod from inside the
container as root while waiting for the cert.
Signed-off-by: Bryan Frimin <bryan@probo.com>
Replace the Provisioner and Renewer with poll-based provision and renew
workers orchestrated by a certmanager Service. Certificate operations are
now hostname-centric and driven by the certificates table, decoupled from
custom-domain business logic.
Signed-off-by: Bryan Frimin <bryan@probo.com>