feat(firewall): implement apply_firewall_rule + commit_firewall_rules
CI / test (3.10) (push) Failing after 7s
CI / test (3.11) (push) Failing after 7s
CI / test (3.12) (push) Failing after 8s
CI / test (3.9) (push) Failing after 7s

OPNsense-specific half of the FirewallDriver diff/apply mechanism added
in napalm-device-types: translates the vendor-neutral rule dict into the
/api/firewall/filter/addRule or setRule/<uuid> payload (string "1"/"0"
booleans, empty interface = floating rule -- same shape as the existing
SNMP self-provisioning rule in _action_fix_snmp), and commit_firewall_rules
reloads the filter via /api/firewall/filter/apply. get_firewall_rules()
already returns compatible field names, no changes needed there.
This commit is contained in:
Christian Manivong
2026-07-20 15:05:53 +02:00
parent d6a0b21dc6
commit 8d3c443159
2 changed files with 129 additions and 0 deletions
+86
View File
@@ -1830,3 +1830,89 @@ class TestDeleteDhcpReservationAndLease:
with pytest.raises(RuntimeError, match="Kea DHCPv4 plugin unavailable"):
driver.delete_dhcp_reservation_and_lease(mac="02:aa:bb:cc:dd:ee", ip="172.22.8.253")
# ---------------------------------------------------------------------------
# apply_firewall_rule / commit_firewall_rules
# ---------------------------------------------------------------------------
class TestApplyFirewallRule:
def test_add_calls_addRule_with_translated_fields(self, driver):
calls = []
driver._post = lambda path, data=None: calls.append((path, data)) or {"result": "saved"}
rule = {
"description": "allow_mgmt_to_fw_gui",
"action": "pass",
"interface": "lan",
"direction": "in",
"protocol": "tcp",
"source_net": "MGMT_NET",
"source_port": "",
"destination_net": "(self)",
"destination_port": "https",
"enabled": True,
"quick": True,
"log": False,
}
driver.apply_firewall_rule(rule)
assert len(calls) == 1
path, payload = calls[0]
assert path == "/api/firewall/filter/addRule"
assert payload["rule"]["enabled"] == "1"
assert payload["rule"]["quick"] == "1"
assert payload["rule"]["log"] == "0"
assert payload["rule"]["action"] == "pass"
assert payload["rule"]["interface"] == "lan"
assert payload["rule"]["source_net"] == "MGMT_NET"
assert payload["rule"]["destination_net"] == "(self)"
assert payload["rule"]["destination_port"] == "https"
assert payload["rule"]["descr"] == "allow_mgmt_to_fw_gui"
assert payload["rule"]["floating"] == "no"
def test_update_calls_setRule_with_uuid(self, driver):
calls = []
driver._post = lambda path, data=None: calls.append((path, data)) or {"result": "saved"}
driver.apply_firewall_rule({"description": "x", "action": "pass"}, uuid="abc-123")
assert calls[0][0] == "/api/firewall/filter/setRule/abc-123"
def test_empty_interface_is_a_floating_rule(self, driver):
calls = []
driver._post = lambda path, data=None: calls.append((path, data)) or {"result": "saved"}
driver.apply_firewall_rule({"description": "x", "action": "pass", "interface": ""})
assert calls[0][1]["rule"]["floating"] == "yes"
def test_disabled_quick_log_flags_translate_to_zero(self, driver):
calls = []
driver._post = lambda path, data=None: calls.append((path, data)) or {"result": "saved"}
driver.apply_firewall_rule(
{
"description": "x",
"action": "block",
"enabled": False,
"quick": False,
"log": True,
}
)
rule = calls[0][1]["rule"]
assert rule["enabled"] == "0"
assert rule["quick"] == "0"
assert rule["log"] == "1"
class TestCommitFirewallRules:
def test_calls_filter_apply(self, driver):
calls = []
driver._post = lambda path, data=None: calls.append((path, data)) or {"status": "ok"}
result = driver.commit_firewall_rules()
assert calls == [("/api/firewall/filter/apply", {})]
assert result == {"status": "ok"}