connectiopn fix round 2 1

This commit is contained in:
2026-08-21 14:18:27 +02:00
parent ad728ba96c
commit 6b2c5ac8a2
11 changed files with 544 additions and 135 deletions

View File

@ -404,7 +404,14 @@ async def _verified_host_key(
observed_key = await asyncssh.get_server_host_key(
host["address"], port=host["port"], connect_timeout=10
)
except (asyncssh.Error, OSError) as exc:
except Exception as exc:
# Bewusst dieselbe Verbreiterung wie in discover_and_store_host_key():
# (asyncssh.Error, OSError) allein fing nicht jede Art von Fehlschlag
# dieses externen Aufrufs ab (z.B. asyncio.TimeoutError vor Python
# 3.11, kein OSError). Ein hier unbehandelter Fehler wuerde ungefiltert
# bis in terminal_ws.py/sftp.py durchreichen -- SSH_SETUP_ERRORS
# erkennt HostKeyDiscoveryError dort explizit und zeigt eine saubere
# deutsche Meldung statt eines generischen Sitzungsabbruchs.
raise HostKeyDiscoveryError(host["id"], str(exc)) from exc
if observed_key is None:
raise HostKeyDiscoveryError(host["id"], "Das Ziel hat keinen Host-Key gesendet")
@ -526,7 +533,22 @@ async def discover_and_store_host_key(
Jetzt wird asyncssh.get_server_host_key() verwendet: das fuehrt nur den
Key-Exchange durch, versucht gar keine Anmeldung und liefert den
Schluessel direkt zurueck. Ein Auth-Fehler kann die Ermittlung damit
nicht mehr verhindern."""
nicht mehr verhindern.
Bugfix 2 (weiterhin gemeldeter 500er nach obigem Fix): das
except-(asyncssh.Error, OSError) fing NICHT jede Art von Fehlschlag ab,
die asyncssh.get_server_host_key() tatsaechlich werfen kann -- reproduziert
mit einer eigenstaendigen Exception-Klasse, wie sie z.B. asyncio.TimeoutError
vor Python 3.11 war (Exception-Unterklasse, KEIN OSError) oder wie sie bei
einem Abbruch waehrend des Key-Exchange auftreten kann (z.B. ein ValueError
aus der Paketdekodierung). So ein Fehler ritt bislang unbehandelt durch bis
zu FastAPI -> HTTP 500 ohne jede Meldung, obwohl es sich in der Sache um
exakt denselben Fall handelt wie ein OSError (Ziel nicht erreichbar/
Protokollfehler waehrend der Ermittlung). Jetzt wird deshalb bewusst JEDE
Ausnahme aus diesem einzelnen, klar abgegrenzten externen Aufruf abgefangen
(asyncio.CancelledError ist als BaseException davon ohnehin nicht
betroffen -- dieselbe Ueberlegung wie beim Exception-Catch-all der
SSH/RDP-WS-Routen, siehe terminal_ws.py/ws_tunnel.py)."""
host = await load_host(conn, host_id)
if host["protocol"] != "ssh":
raise HostNotConfiguredError("Host-Key-Ermittlung ist nur fuer SSH-Ziele moeglich")
@ -535,7 +557,7 @@ async def discover_and_store_host_key(
key = await asyncssh.get_server_host_key(
host["address"], port=host["port"], connect_timeout=10
)
except (asyncssh.Error, OSError) as exc:
except Exception as exc:
logger.warning("Host-Key-Ermittlung fuer Host %s fehlgeschlagen: %s", host_id, exc)
raise HostKeyDiscoveryError(host_id, str(exc)) from exc
if key is None: