diff --git a/napalm_linux/linux.py b/napalm_linux/linux.py index 859e61e..43e8551 100644 --- a/napalm_linux/linux.py +++ b/napalm_linux/linux.py @@ -41,6 +41,7 @@ from napalm_device_types import ( HostStatusMixin, KernelFactsMixin, ListeningSocketsMixin, + OpenSshServerMixin, OSDriver, SystemdServicesMixin, SystemdUnavailable, @@ -208,6 +209,7 @@ class LinuxDriver( KernelFactsMixin, ListeningSocketsMixin, VirtualIpsMixin, + OpenSshServerMixin, SystemdServicesMixin, HostStatusMixin, ContainerEngineMixin, diff --git a/pyproject.toml b/pyproject.toml index c1a878b..a9ee1e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "napalm-linux" -version = "0.4.0" +version = "0.5.0" description = "NAPALM driver for generic Linux systems via SSH" readme = "README.md" requires-python = ">=3.9" @@ -37,7 +37,7 @@ classifiers = [ ] dependencies = [ "napalm>=4.0", - "napalm-device-types>=4.2.0", + "napalm-device-types>=4.5.0", "netmiko>=4.0.0", "paramiko>=5.0.0", # CVE-2026-44405 ] diff --git a/tests/test_linux.py b/tests/test_linux.py index 2122c1b..cbb6053 100644 --- a/tests/test_linux.py +++ b/tests/test_linux.py @@ -1673,3 +1673,23 @@ class TestGetVirtualIps: privileged, plain = (c.command for c in channels) assert privileged.startswith("sudo -n sh -c 'sh -c '") assert plain.startswith("sh -c '") + + +class TestHardensItsSshServer: + """A stock Linux host runs a stock OpenSSH: the hardening netOrk offers for + ssh-audit findings comes from napalm-device-types, carried over run_command + (NetOrk/netork#1027).""" + + def test_mixes_in_the_openssh_hardening(self): + from napalm_device_types import OpenSshServerMixin + + assert issubclass(LinuxDriver, OpenSshServerMixin) + assert callable(getattr(LinuxDriver, "harden_ssh_server", None)) + + def test_reads_the_algorithms_as_root_over_the_command_channel(self, driver): + from napalm_device_types import CommandResult + + out = "kexalgorithms a\nhostkeyalgorithms b\nciphers c\nmacs d\n" + with patch.object(driver, "run_command", return_value=CommandResult(out, "", 0)) as run: + assert driver.get_ssh_server_algorithms()["mac"] == ["d"] + assert run.call_args.kwargs["privileged"] is True