Add SSH connection validation for settings

This commit is contained in:
2026-05-07 18:31:49 +02:00
parent 2219a5730f
commit 84dc2bd2f6
9 changed files with 235 additions and 5 deletions
@@ -48,7 +48,7 @@ class RemoteSSHClient:
private_key_passphrase: str | None = None,
password: str | None = None,
known_hosts_path: str | None = None,
timeout: int = 20,
timeout: int = 30,
):
if not host or not username:
raise ValueError("SSH host and username are required")
@@ -73,7 +73,19 @@ class RemoteSSHClient:
if self._client:
return self._client
if self.known_hosts_path:
ensure_known_host(self.host, self.port, Path(self.known_hosts_path), strict=True)
try:
ensure_known_host(self.host, self.port, Path(self.known_hosts_path), strict=True)
except Exception as exc:
message = str(exc).lower()
if "protocol banner" in message:
raise RuntimeError(
f"SSH banner not received from {self.host}:{self.port}. "
"The host key could not be recorded because the backend could not talk to SSH."
) from exc
raise RuntimeError(
f"SSH host key lookup failed for {self.host}:{self.port}. "
"Confirm the host and port are correct and that SSH is reachable."
) from exc
client = paramiko.SSHClient()
client.load_system_host_keys()
if self.known_hosts_path and Path(self.known_hosts_path).is_file():
@@ -85,12 +97,28 @@ class RemoteSSHClient:
"username": self.username,
"password": self.password,
"timeout": self.timeout,
"banner_timeout": self.timeout,
"auth_timeout": self.timeout,
}
if self.private_key:
connect_kwargs["pkey"] = self._load_private_key(self.private_key, self.private_key_passphrase)
else:
connect_kwargs["key_filename"] = self.key_filename
client.connect(**connect_kwargs)
try:
client.connect(**connect_kwargs)
except Exception as exc:
message = str(exc).lower()
if "protocol banner" in message:
raise RuntimeError(
f"SSH banner not received from {self.host}:{self.port}. "
"Confirm the host, port, and firewall; the backend could not complete the SSH handshake."
) from exc
if "no authentication methods available" in message or "authentication failed" in message:
raise RuntimeError(
f"SSH authentication failed for {self.host}:{self.port}. "
"Check the selected key, passphrase, username, or password."
) from exc
raise
self._client = client
return client