Skip to content

Commit

Permalink
Add firewall zone handling and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanunderwood committed Jul 28, 2020
1 parent f792d6a commit 6d09ae8
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
25 changes: 25 additions & 0 deletions netjsonconfig/backends/openwrt/converters/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ def __intermediate_zones(self, zones):
resultdict = OrderedDict(
((".name", self.__get_auto_name_zone(zone)), (".type", "zone"))
)
# If network contains only a single value, force the use of a UCI "option"
# rather than "list"".
network = zone["network"]
if len(network) == 1:
zone["network"] = network[0]
resultdict.update(zone)
result.append(resultdict)
return result
Expand Down Expand Up @@ -109,6 +114,10 @@ def to_netjson_loop(self, block, result, index):
rule = self.__netjson_rule(block)
result["firewall"].setdefault("rules", [])
result["firewall"]["rules"].append(rule)
if _type == "zone":
zone = self.__netjson_zone(block)
result["firewall"].setdefault("zones", [])
result["firewall"]["zones"].append(zone)

return self.type_cast(result)

Expand All @@ -124,3 +133,19 @@ def __netjson_rule(self, rule):
rule["proto"] = [proto]

return self.type_cast(rule)

def __netjson_zone(self, zone):
network = zone["network"]
# network may be specified as a list in a single string e.g.
# option network 'wan wan6'
# Here we ensure that network is always a list.
if not isinstance(network, list):
zone["network"] = network.split()

if "mtu_fix" in zone:
zone["mtu_fix"] = zone.pop("mtu_fix") == "1"

if "masq" in zone:
zone["masq"] = zone.pop("masq") == "1"

return self.type_cast(zone)
106 changes: 106 additions & 0 deletions tests/openwrt/test_firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,109 @@ def test_render_rule_4(self):
def test_parse_rule_4(self):
o = OpenWrt(native=self._rule_4_uci)
self.assertEqual(o.config, self._rule_4_netjson)

_zone_1_netjson = {
"firewall": {
"zones": [
{
"name": "lan",
"input": "ACCEPT",
"output": "ACCEPT",
"forward": "ACCEPT",
"network": ["lan"],
"mtu_fix": True,
}
]
}
}

_zone_1_uci = textwrap.dedent(
"""\
package firewall
config defaults 'defaults'
config zone 'zone_lan'
option name 'lan'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
option network 'lan'
option mtu_fix '1'
"""
)

def test_render_zone_1(self):
o = OpenWrt(self._zone_1_netjson)
expected = self._tabs(self._zone_1_uci)
self.assertEqual(o.render(), expected)

def test_parse_zone_1(self):
o = OpenWrt(native=self._zone_1_uci)
self.assertEqual(o.config, self._zone_1_netjson)

_zone_2_netjson = {
"firewall": {
"zones": [
{
"name": "wan",
"input": "DROP",
"output": "ACCEPT",
"forward": "DROP",
"network": ["wan", "wan6"],
"mtu_fix": True,
"masq": True,
}
]
}
}

_zone_2_uci = textwrap.dedent(
"""\
package firewall
config defaults 'defaults'
config zone 'zone_wan'
option name 'wan'
option input 'DROP'
option output 'ACCEPT'
option forward 'DROP'
list network 'wan'
list network 'wan6'
option mtu_fix '1'
option masq '1'
"""
)

# This one is the same as _zone_2_uci with the exception that the "network"
# parameter is specified as a single string.
_zone_3_uci = textwrap.dedent(
"""\
package firewall
config defaults 'defaults'
config zone 'zone_wan'
option name 'wan'
option input 'DROP'
option output 'ACCEPT'
option forward 'DROP'
option network 'wan wan6'
option mtu_fix '1'
option masq '1'
"""
)

def test_render_zone_2(self):
o = OpenWrt(self._zone_2_netjson)
expected = self._tabs(self._zone_2_uci)
self.assertEqual(o.render(), expected)

def test_parse_zone_2(self):
o = OpenWrt(native=self._zone_2_uci)
self.assertEqual(o.config, self._zone_2_netjson)

def test_parse_zone_3(self):
o = OpenWrt(native=self._zone_3_uci)
self.assertEqual(o.config, self._zone_2_netjson)

0 comments on commit 6d09ae8

Please sign in to comment.