fix(client): discard expired cert on startup - #95
Conversation
An expired certificate cannot be renewed: certmagic references it via the ACME ARI 'replaces' field, and the CA rejects orders that reference a certificate it no longer considers current (RFC 9773, section 5; Let's Encrypt returns HTTP 404 urn:ietf:params:acme:error:malformed), so renewal retries loop forever and the node never gets a usable cert. Happens when a node comes back online after its cert already expired. Discarding the expired cert on startup routes the client through fresh issuance, which sends no 'replaces' field and re-checks broker health and libp2p reachability first.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #95 +/- ##
==========================================
- Coverage 69.17% 69.03% -0.15%
==========================================
Files 22 22
Lines 1765 1805 +40
==========================================
+ Hits 1221 1246 +25
- Misses 425 433 +8
- Partials 119 126 +7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Suggested tag:
Cutting a Release (and modifying code files)This PR is modifying both Automatically created GitHub ReleaseA draft GitHub Release has been created. |
Merging main brought #95, which found that an expired certificate cannot be renewed at all: the authority rejects an order whose ARI 'replaces' names a certificate it no longer considers current, so certmagic retries a doomed renewal forever. The address path had exactly that bug, reaching for a renewal when the certificate in storage had lapsed. It discards and issues fresh now, through the helper #95 added.
Picks up the review round on ipshipyard/p2p-forge#94: an address the address factory holds back is still offered for certification, the error for a node that cannot be validated says whether the port is unreachable or merely the wrong one, and a named TLS handshake is left to certmagic as it was before this feature existed. Also brings ipshipyard/p2p-forge#95 through that branch, so an expired certificate is discarded rather than renewed, on the address path as well as the brokered one.
Problem
A node that comes back online after its TLS cert expired can never renew it. certmagic references the old cert in the ACME ARI
replacesfield, Let's Encrypt rejects the order with HTTP 404urn:ietf:params:acme:error:malformedbecause it no longer knows that cert, and certmagic retries the same rejected order forever.1 The node runs without a usable AutoTLS cert and logs ERRORs every 10 minutes until someone deletes the cert directory by hand. Seen on a kubo 0.43.0-rc1 node that was offline for a year.Fix
NotAfter, discard it (cert, key, metadata) through the certmagicStorageinterfacereplacesfield, and the node re-checks broker health and libp2p reachability firstA daemon that stays up while its cert expires in place can still wedge until restart. That half needs a certmagic fix (drop
replaceswhen the ARI refresh 404s, like the 409 handling in caddyserver/certmagic#361) and is out of scope here. I left it out of the PR because the exposure is narrow: it takes ~45 days of continuously failing renewals with zero restarts, and any restart (kubo upgrade, reboot) heals it once this patch is deployed.Footnotes
RFC 9773, section 5: servers SHOULD validate the certificate referenced by
replacesand SHOULD reject the newOrder request when validation fails. ↩