feat: get_ssids() macfilter/maclist parsing + push_mac_acl()
Adds MAC ACL (whitelist/blacklist) read+write support for wireless SSIDs, mirroring push_radio_channel's UCI write style. Backs the new Global MAC ACL feature in netOrk.
This commit is contained in:
@@ -1099,3 +1099,138 @@ class TestPushRadioChannel:
|
||||
commit_idx = next(i for i, c in enumerate(issued) if "commit" in c)
|
||||
wifi_idx = next(i for i, c in enumerate(issued) if c.strip() == "wifi")
|
||||
assert commit_idx < wifi_idx
|
||||
|
||||
|
||||
UCI_WIRELESS_ACL = """\
|
||||
wireless.radio0=wifi-device
|
||||
wireless.radio0.band='2g'
|
||||
wireless.radio1=wifi-device
|
||||
wireless.radio1.band='5g'
|
||||
wireless.@wifi-iface[0]=wifi-iface
|
||||
wireless.@wifi-iface[0].device='radio0'
|
||||
wireless.@wifi-iface[0].ssid='CorpWiFi'
|
||||
wireless.@wifi-iface[0].encryption='psk2'
|
||||
wireless.@wifi-iface[0].macfilter='allow'
|
||||
wireless.@wifi-iface[0].maclist='AA:BB:CC:DD:EE:01'
|
||||
wireless.@wifi-iface[0].maclist='AA:BB:CC:DD:EE:02'
|
||||
wireless.@wifi-iface[1]=wifi-iface
|
||||
wireless.@wifi-iface[1].device='radio1'
|
||||
wireless.@wifi-iface[1].ssid='CorpWiFi'
|
||||
wireless.@wifi-iface[1].encryption='psk2'
|
||||
wireless.@wifi-iface[2]=wifi-iface
|
||||
wireless.@wifi-iface[2].device='radio0'
|
||||
wireless.@wifi-iface[2].ssid='GuestNet'
|
||||
wireless.@wifi-iface[2].encryption='none'
|
||||
"""
|
||||
|
||||
|
||||
class TestGetSsidsAcl:
|
||||
"""Tests for the macfilter/maclist parsing in OpenWrtWirelessMixin.get_ssids()."""
|
||||
|
||||
def _send(self, cmd, **kw):
|
||||
if cmd.strip() == "uci show wireless":
|
||||
return UCI_WIRELESS_ACL
|
||||
return ""
|
||||
|
||||
def test_whitelist_mode_parsed(self, driver):
|
||||
driver._send_command = self._send
|
||||
result = driver.get_ssids()
|
||||
assert result["CorpWiFi"]["acl_mode"] == "whitelist"
|
||||
|
||||
def test_maclist_multiple_entries_parsed(self, driver):
|
||||
"""UCI list values repeat the same key across lines — must not overwrite."""
|
||||
driver._send_command = self._send
|
||||
result = driver.get_ssids()
|
||||
assert result["CorpWiFi"]["mac_list"] == ["AA:BB:CC:DD:EE:01", "AA:BB:CC:DD:EE:02"]
|
||||
|
||||
def test_acl_mode_merged_across_radios(self, driver):
|
||||
"""Only wifi-iface[0] has macfilter set; wifi-iface[1] (same SSID) must inherit it."""
|
||||
driver._send_command = self._send
|
||||
result = driver.get_ssids()
|
||||
# Both wifi-iface sections belong to CorpWiFi — the merged result carries one acl_mode.
|
||||
assert result["CorpWiFi"]["acl_mode"] == "whitelist"
|
||||
assert result["CorpWiFi"]["mac_list"] == ["AA:BB:CC:DD:EE:01", "AA:BB:CC:DD:EE:02"]
|
||||
|
||||
def test_no_macfilter_defaults_to_off(self, driver):
|
||||
driver._send_command = self._send
|
||||
result = driver.get_ssids()
|
||||
assert result["GuestNet"]["acl_mode"] == "off"
|
||||
assert result["GuestNet"]["mac_list"] == []
|
||||
|
||||
def test_deny_maps_to_blacklist(self, driver):
|
||||
deny_uci = UCI_WIRELESS_ACL.replace("macfilter='allow'", "macfilter='deny'")
|
||||
driver._send_command = lambda cmd, **kw: deny_uci if cmd.strip() == "uci show wireless" else ""
|
||||
result = driver.get_ssids()
|
||||
assert result["CorpWiFi"]["acl_mode"] == "blacklist"
|
||||
|
||||
|
||||
class TestPushMacAcl:
|
||||
"""Tests for OpenWrtWirelessMixin.push_mac_acl()."""
|
||||
|
||||
def _make_send(self, sections="wireless.@wifi-iface[0]\nwireless.@wifi-iface[1]", ssid_by_section=None):
|
||||
ssid_by_section = ssid_by_section or {
|
||||
"wireless.@wifi-iface[0]": "CorpWiFi",
|
||||
"wireless.@wifi-iface[1]": "GuestNet",
|
||||
}
|
||||
issued: list[str] = []
|
||||
|
||||
def _send(cmd, **kw):
|
||||
issued.append(cmd)
|
||||
if "grep -oE" in cmd and "sort -u" in cmd:
|
||||
return sections
|
||||
for sec, ssid in ssid_by_section.items():
|
||||
if f"uci -q get {sec}.ssid" in cmd:
|
||||
return ssid
|
||||
return ""
|
||||
|
||||
return _send, issued
|
||||
|
||||
def test_whitelist_sets_macfilter_allow(self, driver):
|
||||
send, issued = self._make_send()
|
||||
driver._send_command = send
|
||||
driver.push_mac_acl("CorpWiFi", "whitelist", ["AA:BB:CC:DD:EE:01"])
|
||||
assert any("wireless.@wifi-iface[0].macfilter='allow'" in c for c in issued)
|
||||
|
||||
def test_blacklist_sets_macfilter_deny(self, driver):
|
||||
send, issued = self._make_send()
|
||||
driver._send_command = send
|
||||
driver.push_mac_acl("CorpWiFi", "blacklist", ["AA:BB:CC:DD:EE:01"])
|
||||
assert any("wireless.@wifi-iface[0].macfilter='deny'" in c for c in issued)
|
||||
|
||||
def test_off_sets_macfilter_disable_and_clears_maclist(self, driver):
|
||||
send, issued = self._make_send()
|
||||
driver._send_command = send
|
||||
driver.push_mac_acl("CorpWiFi", "off", [])
|
||||
assert any("wireless.@wifi-iface[0].macfilter='disable'" in c for c in issued)
|
||||
assert any("delete wireless.@wifi-iface[0].maclist" in c for c in issued)
|
||||
assert not any("add_list wireless.@wifi-iface[0].maclist" in c for c in issued)
|
||||
|
||||
def test_maclist_entries_added(self, driver):
|
||||
send, issued = self._make_send()
|
||||
driver._send_command = send
|
||||
driver.push_mac_acl("CorpWiFi", "whitelist", ["AA:BB:CC:DD:EE:01", "AA:BB:CC:DD:EE:02"])
|
||||
assert any("add_list wireless.@wifi-iface[0].maclist='AA:BB:CC:DD:EE:01'" in c for c in issued)
|
||||
assert any("add_list wireless.@wifi-iface[0].maclist='AA:BB:CC:DD:EE:02'" in c for c in issued)
|
||||
|
||||
def test_maclist_cleared_before_readd(self, driver):
|
||||
"""Full-rebuild: existing maclist must be deleted before new entries are added."""
|
||||
send, issued = self._make_send()
|
||||
driver._send_command = send
|
||||
driver.push_mac_acl("CorpWiFi", "whitelist", ["AA:BB:CC:DD:EE:01"])
|
||||
delete_idx = next(i for i, c in enumerate(issued) if "delete wireless.@wifi-iface[0].maclist" in c)
|
||||
add_idx = next(i for i, c in enumerate(issued) if "add_list wireless.@wifi-iface[0].maclist" in c)
|
||||
assert delete_idx < add_idx
|
||||
|
||||
def test_only_matching_ssid_sections_touched(self, driver):
|
||||
"""GuestNet section must not be modified when pushing CorpWiFi's ACL."""
|
||||
send, issued = self._make_send()
|
||||
driver._send_command = send
|
||||
driver.push_mac_acl("CorpWiFi", "whitelist", ["AA:BB:CC:DD:EE:01"])
|
||||
assert not any("wireless.@wifi-iface[1].macfilter" in c for c in issued)
|
||||
|
||||
def test_issues_uci_commit_and_wifi_reload(self, driver):
|
||||
send, issued = self._make_send()
|
||||
driver._send_command = send
|
||||
driver.push_mac_acl("CorpWiFi", "whitelist", ["AA:BB:CC:DD:EE:01"])
|
||||
assert any("uci commit wireless" in c for c in issued)
|
||||
assert any(c.strip() == "wifi reload" for c in issued)
|
||||
|
||||
Reference in New Issue
Block a user