fixes and improvements
This commit is contained in:
@@ -20,6 +20,8 @@ from typing import Any
|
||||
|
||||
import paramiko
|
||||
|
||||
from media_library_viewer_api.services.known_hosts import has_known_host
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -64,17 +66,23 @@ class RemoteSSHClient:
|
||||
def connect(self) -> paramiko.SSHClient:
|
||||
"""Create or reuse the Paramiko connection.
|
||||
|
||||
Host keys are expected to be managed ahead of time by startup synthesis
|
||||
or explicit validation flows. Runtime connections only load the managed
|
||||
known_hosts file and then let Paramiko enforce strict checking.
|
||||
Host keys are trusted on first successful use when a managed
|
||||
known_hosts path is configured. Subsequent connections stay strict and
|
||||
reject host-key changes.
|
||||
"""
|
||||
if self._client:
|
||||
return self._client
|
||||
client = paramiko.SSHClient()
|
||||
client.load_system_host_keys()
|
||||
if self.known_hosts_path and Path(self.known_hosts_path).is_file():
|
||||
client.load_host_keys(self.known_hosts_path)
|
||||
client.set_missing_host_key_policy(paramiko.RejectPolicy())
|
||||
known_hosts_file = Path(self.known_hosts_path) if self.known_hosts_path else None
|
||||
trusted_before = bool(
|
||||
known_hosts_file and has_known_host(self.host, self.port, known_hosts_file)
|
||||
)
|
||||
if known_hosts_file and known_hosts_file.is_file():
|
||||
client.load_host_keys(str(known_hosts_file))
|
||||
client.set_missing_host_key_policy(
|
||||
paramiko.RejectPolicy() if trusted_before else paramiko.AutoAddPolicy()
|
||||
)
|
||||
connect_kwargs: dict[str, Any] = {
|
||||
"hostname": self.host,
|
||||
"port": self.port,
|
||||
@@ -103,6 +111,9 @@ class RemoteSSHClient:
|
||||
"Check the selected key, passphrase, username, or password."
|
||||
) from exc
|
||||
raise
|
||||
if known_hosts_file and not trusted_before:
|
||||
known_hosts_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
client.save_host_keys(str(known_hosts_file))
|
||||
self._client = client
|
||||
return client
|
||||
|
||||
|
||||
Reference in New Issue
Block a user