Skip to content

Commit 6d09ae8

Browse files
Add firewall zone handling and tests
1 parent f792d6a commit 6d09ae8

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

netjsonconfig/backends/openwrt/converters/firewall.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ def __intermediate_zones(self, zones):
6464
resultdict = OrderedDict(
6565
((".name", self.__get_auto_name_zone(zone)), (".type", "zone"))
6666
)
67+
# If network contains only a single value, force the use of a UCI "option"
68+
# rather than "list"".
69+
network = zone["network"]
70+
if len(network) == 1:
71+
zone["network"] = network[0]
6772
resultdict.update(zone)
6873
result.append(resultdict)
6974
return result
@@ -109,6 +114,10 @@ def to_netjson_loop(self, block, result, index):
109114
rule = self.__netjson_rule(block)
110115
result["firewall"].setdefault("rules", [])
111116
result["firewall"]["rules"].append(rule)
117+
if _type == "zone":
118+
zone = self.__netjson_zone(block)
119+
result["firewall"].setdefault("zones", [])
120+
result["firewall"]["zones"].append(zone)
112121

113122
return self.type_cast(result)
114123

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

126135
return self.type_cast(rule)
136+
137+
def __netjson_zone(self, zone):
138+
network = zone["network"]
139+
# network may be specified as a list in a single string e.g.
140+
# option network 'wan wan6'
141+
# Here we ensure that network is always a list.
142+
if not isinstance(network, list):
143+
zone["network"] = network.split()
144+
145+
if "mtu_fix" in zone:
146+
zone["mtu_fix"] = zone.pop("mtu_fix") == "1"
147+
148+
if "masq" in zone:
149+
zone["masq"] = zone.pop("masq") == "1"
150+
151+
return self.type_cast(zone)

tests/openwrt/test_firewall.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,109 @@ def test_render_rule_4(self):
176176
def test_parse_rule_4(self):
177177
o = OpenWrt(native=self._rule_4_uci)
178178
self.assertEqual(o.config, self._rule_4_netjson)
179+
180+
_zone_1_netjson = {
181+
"firewall": {
182+
"zones": [
183+
{
184+
"name": "lan",
185+
"input": "ACCEPT",
186+
"output": "ACCEPT",
187+
"forward": "ACCEPT",
188+
"network": ["lan"],
189+
"mtu_fix": True,
190+
}
191+
]
192+
}
193+
}
194+
195+
_zone_1_uci = textwrap.dedent(
196+
"""\
197+
package firewall
198+
199+
config defaults 'defaults'
200+
201+
config zone 'zone_lan'
202+
option name 'lan'
203+
option input 'ACCEPT'
204+
option output 'ACCEPT'
205+
option forward 'ACCEPT'
206+
option network 'lan'
207+
option mtu_fix '1'
208+
"""
209+
)
210+
211+
def test_render_zone_1(self):
212+
o = OpenWrt(self._zone_1_netjson)
213+
expected = self._tabs(self._zone_1_uci)
214+
self.assertEqual(o.render(), expected)
215+
216+
def test_parse_zone_1(self):
217+
o = OpenWrt(native=self._zone_1_uci)
218+
self.assertEqual(o.config, self._zone_1_netjson)
219+
220+
_zone_2_netjson = {
221+
"firewall": {
222+
"zones": [
223+
{
224+
"name": "wan",
225+
"input": "DROP",
226+
"output": "ACCEPT",
227+
"forward": "DROP",
228+
"network": ["wan", "wan6"],
229+
"mtu_fix": True,
230+
"masq": True,
231+
}
232+
]
233+
}
234+
}
235+
236+
_zone_2_uci = textwrap.dedent(
237+
"""\
238+
package firewall
239+
240+
config defaults 'defaults'
241+
242+
config zone 'zone_wan'
243+
option name 'wan'
244+
option input 'DROP'
245+
option output 'ACCEPT'
246+
option forward 'DROP'
247+
list network 'wan'
248+
list network 'wan6'
249+
option mtu_fix '1'
250+
option masq '1'
251+
"""
252+
)
253+
254+
# This one is the same as _zone_2_uci with the exception that the "network"
255+
# parameter is specified as a single string.
256+
_zone_3_uci = textwrap.dedent(
257+
"""\
258+
package firewall
259+
260+
config defaults 'defaults'
261+
262+
config zone 'zone_wan'
263+
option name 'wan'
264+
option input 'DROP'
265+
option output 'ACCEPT'
266+
option forward 'DROP'
267+
option network 'wan wan6'
268+
option mtu_fix '1'
269+
option masq '1'
270+
"""
271+
)
272+
273+
def test_render_zone_2(self):
274+
o = OpenWrt(self._zone_2_netjson)
275+
expected = self._tabs(self._zone_2_uci)
276+
self.assertEqual(o.render(), expected)
277+
278+
def test_parse_zone_2(self):
279+
o = OpenWrt(native=self._zone_2_uci)
280+
self.assertEqual(o.config, self._zone_2_netjson)
281+
282+
def test_parse_zone_3(self):
283+
o = OpenWrt(native=self._zone_3_uci)
284+
self.assertEqual(o.config, self._zone_2_netjson)

0 commit comments

Comments
 (0)