"""Gestion du fichier known_hosts local (cles d'hotes approuvees via TOFU). Avec des serveurs en IP dynamique (DHCP), une IP reattribuee a une autre machine fait apparaitre une "cle d'hote modifiee" lors de la connexion : ce module permet de retirer facilement l'ancienne entree, en masse ou au cas par cas, sans avoir a editer le fichier a la main. """ from __future__ import annotations from dataclasses import dataclass from pathlib import Path import paramiko from app.paths import DATA_DIR # noqa: E402 (chemins valables aussi en .exe) KNOWN_HOSTS_FILE = DATA_DIR / "known_hosts" @dataclass class KnownHostEntry: hostname: str key_type: str fingerprint: str class KnownHostsStore: def __init__(self, path: Path = KNOWN_HOSTS_FILE): self.path = path def _load(self) -> paramiko.HostKeys: hk = paramiko.HostKeys() if self.path.exists(): try: hk.load(str(self.path)) except Exception: pass return hk def list_entries(self) -> list[KnownHostEntry]: hk = self._load() entries: list[KnownHostEntry] = [] for hostname in hk.keys(): for key_type, key in hk[hostname].items(): entries.append(KnownHostEntry( hostname=hostname, key_type=key_type, fingerprint=key.get_fingerprint().hex(":"), )) entries.sort(key=lambda e: e.hostname) return entries def remove_host(self, hostname: str) -> None: hk = self._load() if hostname in hk: del hk[hostname] self._save(hk) def replace_host_key(self, hostname: str, key: paramiko.PKey) -> None: """Retire l'ancienne cle d'un hote et enregistre la nouvelle (cas d'une IP DHCP reattribuee).""" hk = self._load() if hostname in hk: del hk[hostname] hk.add(hostname, key.get_name(), key) self._save(hk) def clear_all(self) -> None: DATA_DIR.mkdir(parents=True, exist_ok=True) self.path.write_text("", encoding="utf-8") def _save(self, hk: paramiko.HostKeys) -> None: DATA_DIR.mkdir(parents=True, exist_ok=True) hk.save(str(self.path))