A name has no resolver entry until the serial reconcile loop reaches it, so it is served the fallback #57
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
From the v2.0.0 security audit.
load_into_resolvertombstones only names that already have acertificatesrow, so a fresh install tombstones nothing. The tombstone is written insidereconcile_once's per-name loop, after the previous name's ACME order has completed.Issuance is serial with
ORDER_SPACINGplus up to ~4 minutes of ACME per name (24×5s propagation poll, two 120spoll_ready/poll_certificatetimeouts). On a fresh deployment with a dozen configured names, the last names have no resolver entry for tens of minutes — so SNI for them resolves to the self-signededge-router.localfallback instead of aborting the handshake. The same window opens for a name added over the API or by a config reload while a pass holdsPASS.src/api.rs:597already comments on exactly this symptom ("had no certificate and was being served the fallback"), but only the readiness report was fixed, not the serving.Distinct from #53 (a stale tombstone outliving its route) and #48 (deletion with no grace period) — this is a name that has no entry yet rather than one whose entry is wrong.
Fix
Seed
mark_unavailablefor every desired-but-unknown name at the top of the pass, before the first order. Cheap, and it makes the window refuse rather than substitute.Worth checking the readiness interaction while doing it: a name tombstoned
Unavailablecounts against/ready, which is correct here — it genuinely is not ready — but confirm a fresh install reports not-ready rather than flapping.Fixed in
99adeaa.reconcile_oncenow seeds a tombstone for every desired name before any ordering begins, instead of writing each one as the serial loop reaches it.Seeding touches only names with no resolver entry, so a loaded certificate keeps serving across a pass and an existing tombstone is left alone. The tombstone kind matches what the loop would choose (
NotCertifiablefor a reserved name,Unavailableotherwise), so a.localhostroute does not briefly count against readiness — which answers the readiness question raised in the issue.Two tests:
every_desired_name_is_tombstoned_before_the_first_orderasserts from inside the firstorder()call, via a snapshotting orderer that records the resolver's known names. Asserting after the pass would prove nothing, because by then every name has an entry either way.seeding_a_tombstone_does_not_clobber_a_loaded_certificateis the negative control: a name with a usable certificate must still resolve after a pass.354 tests green, clippy clean, fmt clean.