An `amt` driver (napalm_amt.AmtDriver), a ManagementControllerDriver for the management controller of Intel vPro machines, with its own lean WS-Management client (requests + ElementTree, HTTP Digest, ports 16992/16993). It reads the machine's identity, hardware with the SMBIOS system UUID, firmware (AMT with build, BIOS), power state and the hardware event log, reports what AMT listens on (plain HTTP or TLS, KVM incl. port 5900, IDE-R), and switches the machine's power. AMT cannot be reset over WS-Management, so there is no reboot_host. Discovery recognises AMT by its ports and its Server header. Tested against Intel's published AMT 12 recordings (go-wsman-messages, Apache-2.0, see NOTICE). `python -m napalm_amt.record` records a real AMT read-only; the first test devices are two Lenovo ThinkCentre M910x.
98 lines
3.5 KiB
Python
98 lines
3.5 KiB
Python
"""What AMT listens on: plain HTTP or TLS, the KVM console and IDE/USB redirection."""
|
|
|
|
import pytest
|
|
|
|
from napalm_amt.parsers import parse_management_protocols
|
|
|
|
from ..conftest import instances
|
|
|
|
|
|
def _protocols(**overrides):
|
|
args = {
|
|
"tls_settings": instances("AMT_TLSSettingData.pull.xml"),
|
|
"redirection": instances("AMT_RedirectionService.get.xml")[0],
|
|
"kvm_settings": instances("IPS_KVMRedirectionSettingData.get.xml")[0],
|
|
"kvm_saps": instances("CIM_KVMRedirectionSAP.pull.xml"),
|
|
}
|
|
args.update(overrides)
|
|
return parse_management_protocols(**args)
|
|
|
|
|
|
def test_amt_without_tls_listens_on_plain_http():
|
|
assert _protocols() == {
|
|
"ipmi": {"enabled": False, "port": 623},
|
|
"ssh": {"enabled": False, "port": 22},
|
|
"http": {"enabled": True, "port": 16992},
|
|
"https": {"enabled": False, "port": 16993},
|
|
"snmp": {"enabled": False, "port": 161},
|
|
# KVM is enabled (MEBx), offline until someone connects; over the redirection
|
|
# port, as the standard VNC port 5900 is off.
|
|
"kvm": {"enabled": True, "port": 16994},
|
|
# IDE-R/USB-R and SOL are both on (EnabledState 32771).
|
|
"virtual_media": {"enabled": True, "port": 16994},
|
|
}
|
|
|
|
|
|
def test_amt_with_tls_listens_on_16993_and_redirects_over_tls():
|
|
tls = [
|
|
{
|
|
"InstanceID": "Intel(r) AMT 802.3 TLS Settings",
|
|
"Enabled": "true",
|
|
"AcceptNonSecureConnections": "false",
|
|
}
|
|
]
|
|
protocols = _protocols(tls_settings=tls)
|
|
assert protocols["https"] == {"enabled": True, "port": 16993}
|
|
assert protocols["http"] == {"enabled": False, "port": 16992}
|
|
assert protocols["kvm"]["port"] == 16995
|
|
assert protocols["virtual_media"]["port"] == 16995
|
|
|
|
|
|
def test_tls_that_still_accepts_plain_connections_keeps_http_open():
|
|
tls = [
|
|
{
|
|
"InstanceID": "Intel(r) AMT 802.3 TLS Settings",
|
|
"Enabled": "true",
|
|
"AcceptNonSecureConnections": "true",
|
|
}
|
|
]
|
|
assert _protocols(tls_settings=tls)["http"]["enabled"] is True
|
|
|
|
|
|
def test_the_lms_tls_setting_is_local_and_ignored():
|
|
tls = [{"InstanceID": "Intel(r) AMT LMS TLS Settings", "Enabled": "true"}]
|
|
assert _protocols(tls_settings=tls)["https"]["enabled"] is False
|
|
|
|
|
|
def test_kvm_on_the_standard_vnc_port():
|
|
kvm = {**instances("IPS_KVMRedirectionSettingData.get.xml")[0], "Is5900PortEnabled": "true"}
|
|
assert _protocols(kvm_settings=kvm)["kvm"] == {"enabled": True, "port": 5900}
|
|
|
|
|
|
@pytest.mark.parametrize("sap_state", ["3", "4"])
|
|
def test_kvm_disabled(sap_state):
|
|
saps = [{"EnabledState": sap_state}]
|
|
assert _protocols(kvm_saps=saps)["kvm"]["enabled"] is False
|
|
|
|
|
|
def test_kvm_disabled_in_mebx():
|
|
kvm = {**instances("IPS_KVMRedirectionSettingData.get.xml")[0], "EnabledByMEBx": "false"}
|
|
assert _protocols(kvm_settings=kvm)["kvm"]["enabled"] is False
|
|
|
|
|
|
def test_kvm_unknown_without_any_data():
|
|
assert _protocols(kvm_settings={}, kvm_saps=[])["kvm"]["enabled"] is False
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("state", "enabled"),
|
|
[("32768", False), ("32769", True), ("32770", False), ("32771", True), ("", False)],
|
|
)
|
|
def test_virtual_media_is_ide_redirection(state, enabled):
|
|
assert _protocols(redirection={"EnabledState": state})["virtual_media"]["enabled"] is enabled
|
|
|
|
|
|
def test_redirection_listener_off_closes_virtual_media():
|
|
redirection = {"EnabledState": "32771", "ListenerEnabled": "false"}
|
|
assert _protocols(redirection=redirection)["virtual_media"]["enabled"] is False
|