fix(ssh): verify the host key netOrk expects, report the one seen (NetOrk/netork#1167)
Tests / Test (Python 3.10) (pull_request) Successful in 28s
Tests / Test (Python 3.11) (pull_request) Successful in 56s
Tests / Test (Python 3.12) (pull_request) Successful in 34s

The driver accepted any SSH host key. It now verifies through
napalm-device-types' HostKeyCheck (>= 4.19.0): with a known key in
optional_args["ssh_host_keys"] any other key is refused before login, and
every key seen is reported to optional_args["ssh_host_key_observer"].
Without either argument it connects as before (first use).
This commit is contained in:
Christian Manivong committed 2026-10-18 21:23:42 +02:00
1 parent 03300b7954
commit e4f57d3c3a
3 files changed
+101 -10

No files matched your search

+15 -8
View File
@@ -38,6 +38,7 @@ from napalm.base.exceptions import (
ReplaceConfigException,
)
from napalm.base.netmiko_helpers import netmiko_args
from napalm_device_types.ssh_host_keys import HostKeyCheck, SshHostKeyMismatch
import napalm.base.constants as C
@@ -99,6 +100,8 @@ class TPLinkJetstreamDriver(ConfigLifecycleMixin, SnmpAgentMixin, SwitchDriver):
self.port = optional_args.get("port", 22)
self.use_canonical_interface = optional_args.get("canonical_int_fmt", False)
self.netmiko_optional_args = netmiko_args(optional_args)
# The host key to expect, and where the one seen is reported (netork#1167).
self._host_key = HostKeyCheck(optional_args, hostname, self.port)
# Config management state
self._candidate_config: str | None = None
@@ -112,16 +115,20 @@ class TPLinkJetstreamDriver(ConfigLifecycleMixin, SnmpAgentMixin, SwitchDriver):
def open(self) -> None:
"""Open an SSH connection to the device."""
try:
self.device = ConnectHandler(
device_type=self.NETMIKO_DEVICE_TYPE,
host=self.hostname,
username=self.username,
password=self.password,
timeout=self.timeout,
**self.netmiko_optional_args,
)
with self._host_key.netmiko(self.netmiko_optional_args) as netmiko_kwargs:
self.device = ConnectHandler(
device_type=self.NETMIKO_DEVICE_TYPE,
host=self.hostname,
username=self.username,
password=self.password,
timeout=self.timeout,
**netmiko_kwargs,
)
self._host_key.observe(self.device.remote_conn_pre.get_transport())
if not self.force_no_enable:
self.device.enable()
except SshHostKeyMismatch:
raise # refused before the login; nothing was sent
except NetmikoTimeoutException as exc:
raise ConnectionException(
f"Cannot connect to {self.hostname}: {exc}"