fix(portal,tls): DNS-Prüfung des zusammengesetzten Portal-Hosts + Verwaltungs-Host in TLS-Automation - #231
Merged
Merged
Conversation
…waltungs-Host in TLS-Automation Zwei ACME-Defekte aus einem externen Bug-Report (1.118.5): 1. validatePortalHost prüfte nur die DNS-Verifizierung der Basisdomain, nie den daraus gebauten Host <präfix>.<basis>. Ohne dessen A/AAAA-Eintrag ging er trotzdem in buildTlsAutomation und Caddy versuchte 30 Tage lang (max_duration) beim produktiven Let's-Encrypt-CA ein Zertifikat zu holen — das Limit von 5 fehlgeschlagenen Prüfungen/Stunde/Hostname war sofort erschöpft, ohne Rückmeldung im UI. Der Host wird jetzt selbst aufgelöst (domains.verify) und mit der Server-IP verglichen; Status 'failed' → 400 mit eigenem Fehlertext host_unresolved. 'pending' (Resolver nicht erreichbar) blockiert bewusst nicht, und der Apex-Fall (leeres Präfix) spart den zweiten Roundtrip. 2. Der Verwaltungs-Host aus GC_BASE_URL erreichte buildTlsAutomation nie, weil seine Route erst danach in caddyRoutes eingehängt wird. Er fiel damit auf Caddys Standard-Automation zurück — ein ACME-Konto ohne Kontaktadresse trotz gesetztem GC_CADDY_EMAIL, also keine Ablaufbenachrichtigungen. Er wird jetzt wie homeHost ausdrücklich übergeben; die Domain-Liste ist dedupliziert, damit ein Host, der zugleich Route ist, nicht doppelt als Subject auftaucht. Regressionstests für beide Defekte (ohne Fix rot), bestehende Portal-Host-Tests auf den nun asynchronen Validator umgestellt und ihren Resolver gestubbt (liefen vorher zufällig über den 'pending'-Pfad durch).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Behebt zwei ACME-Defekte aus einem externen Bug-Report gegen 1.118.5.
1. Portal-Host wird ohne DNS-Prüfung übernommen → 30-Tage-ACME-Schleife
validatePortalHostprüfte viadomains.isVerified(base)nur den gespeicherten Status der Basisdomain. Der eigentlich genutzte Host<präfix>.<basis>wurde erst danach zusammengesetzt und nur noch auf Kollisionen geprüft — nie aufgelöst. Dassexample.comeinen A-Eintrag hat, sagt nichts überhome.example.com.Folge: Der nicht auflösbare Host ging in
buildTlsAutomation, bekam korrekt eine ACME-Policy, und Caddy versuchte mitmax_duration = 2592000(30 Tage) beim produktiven Let's-Encrypt-CA zu validieren. Let's Encrypt erlaubt 5 fehlgeschlagene Prüfungen pro Konto/Hostname/Stunde — im Report nach ~15 Minuten erschöpft, und die Schleife bewaffnet das einen Monat lang immer neu. Im UI gab es dazu keinerlei Rückmeldung.Fix: Der zusammengesetzte Host geht durch dasselbe
domains.verify(), das die Domain-Registry schon benutzt (Auflösung + Vergleich mitgetServerPublicIp()).status === 'failed'(NXDOMAIN oder fremde IP) →400mit eigenem Keysettings.portal.host_unresolved, der sagt, welcher Eintrag fehlt.status === 'pending'(unser Resolver ist nicht erreichbar) blockiert nicht — wir können nichts entscheiden, also verweigern wir auch nichts.validatePortalHostist dadurchasync; der einzige Aufrufer (routes/api/settings/portal.js) wurde angepasst.2. Verwaltungs-Host fehlte in der TLS-Automation (eigener Defekt, gleicher Bereich)
caddyConfig.jsbaut die TLS-Automation, bevor der Host ausGC_BASE_URLincaddyRouteseingehängt wird. Bei leerer Routen-Tabelle enthielt die übergebene Domain-Liste damit nurhomeHost— der Verwaltungs-Host bekam nie eine explizite Policy und fiel auf Caddys Standard-Automation zurück: ein ACME-Konto ohne Kontaktadresse, obwohlGC_CADDY_EMAILgesetzt ist. Ergebnis sind zwei LE-Konten auf derselben Installation und keine Ablaufbenachrichtigungen für das Zertifikat des Admin-UI.gcHostwird jetzt genauso ausdrücklich übergeben wiehomeHost— der vorhandene Kommentar nannte fürhomeHostbereits exakt diesen Grund. Die Liste läuft zusätzlich durch einSet, damit ein Host, der zugleich Route und Verwaltungs-Host ist, nicht doppelt als Subject landet (buildTlsAutomationdedupliziert nur den privaten Zweig).Tests
Neu, alle ohne den Fix rot verifiziert:
tests/portal_host_helper.test.js: NXDOMAIN →unresolved, fremde IP →unresolved, Resolver-Timeout → durchgelassen, Apex-Fall löst nicht erneut auf.tests/portal_settings_host.test.js:PUTmit unauflösbarem Host →400, und nichts wird persistiert.tests/caddy_tls_management_host.test.js: Verwaltungs-Host bekommt eine ACME-Policy mit Kontaktadresse; kein doppeltes Subject, wenn eine Route denselben Host bedient.Die bestehenden Portal-Host-Tests liefen bislang zufällig über den
pending-Pfad durch (in der Harness ist keine Server-IP ermittelbar). Sie stubben jetztserver.public_ipund den Resolver explizit und fassen kein Netz mehr an.Volle Suite: 2305/2308 grün. Der eine Fehlschlag (
POST /api/v1/peers … requires wg) besteht unverändert auch ohne diesen Branch — die Umgebung hat kein WireGuard.Nicht enthalten
Der Report schlägt zusätzlich vor, die ACME-Policy zurückzuhalten, bis der Name auflöst (zweite Verteidigungslinie), bzw.
GC_CADDY_ACME_CAbis zur ersten erfolgreichen Auflösung auf Staging zu pinnen. Beides ist hier bewusst weggelassen:validatePortalHostist der einzige Weg, auf demportal.base_domaingesetzt wird, die Prüfung sitzt also bereits an der einzigen Stelle, durch die alle Aufrufer laufen. Sinnvoll wird die zweite Linie erst, wenn ein DNS-Eintrag nach dem Speichern wegfällt — das wäre ein eigener Punkt (periodische Re-Verifizierung des Portal-Hosts).Bestehende Installationen mit bereits gesetztem, kaputtem Portal-Host repariert dieses Update nicht rückwirkend — die Prüfung greift beim Speichern. Dort weiterhin: A-Eintrag anlegen oder die Basisdomain im Portal leeren.
🤖 Generated with Claude Code
https://claude.ai/code/session_01QwdEvuCYgxfjkGdkcPM4vJ