fix(ssh): verify the host key netOrk expects, report the one seen (NetOrk/netork#1167)
CI / test (3.10) (push) Successful in 34s
CI / test (3.11) (push) Successful in 40s
CI / test (3.12) (push) Successful in 34s
CI / test (3.10) (pull_request) Successful in 36s
CI / test (3.11) (pull_request) Successful in 29s
CI / test (3.12) (pull_request) Successful in 27s
CI / test (3.10) (push) Successful in 34s
CI / test (3.11) (push) Successful in 40s
CI / test (3.12) (push) Successful in 34s
CI / test (3.10) (pull_request) Successful in 36s
CI / test (3.11) (pull_request) Successful in 29s
CI / test (3.12) (pull_request) Successful in 27s
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:
1 parent
fddb5c6772
commit
cb14f1f00f
3 files changed
+102
-11
No files matched your search
@@ -42,6 +42,7 @@ from napalm.base.exceptions import (
|
||||
ConnectionClosedException,
|
||||
)
|
||||
from napalm.base.netmiko_helpers import netmiko_args
|
||||
from napalm_device_types.ssh_host_keys import HostKeyCheck, SshHostKeyMismatch
|
||||
|
||||
from napalm_openwrt.interfaces_mixin import OpenWrtInterfaceMixin
|
||||
from napalm_openwrt.wireless_mixin import OpenWrtWirelessMixin
|
||||
@@ -117,6 +118,8 @@ class OpenWrtDriver(
|
||||
|
||||
self.port = optional_args.pop("port", 22)
|
||||
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
|
||||
@@ -130,15 +133,18 @@ class OpenWrtDriver(
|
||||
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,
|
||||
port=self.port,
|
||||
**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,
|
||||
port=self.port,
|
||||
**netmiko_kwargs,
|
||||
)
|
||||
except SshHostKeyMismatch:
|
||||
raise # refused before the login; nothing was sent
|
||||
except NetmikoTimeoutException as exc:
|
||||
raise ConnectionException(
|
||||
f"Cannot connect to {self.hostname}: {exc}"
|
||||
@@ -147,6 +153,7 @@ class OpenWrtDriver(
|
||||
raise ConnectionException(
|
||||
f"Authentication failed for {self.hostname}: {exc}"
|
||||
) from exc
|
||||
self._host_key.observe(self.device.remote_conn_pre.get_transport())
|
||||
|
||||
def close(self) -> None:
|
||||
"""Close the SSH connection."""
|
||||
|
||||
Reference in new issue
Block a user