@@ -155,11 +155,10 @@ def test_17_update_chain(self):
155155 mock_a .assert_called_once_with ()
156156
157157
158- def test_18_add_chain (self ):
159- ''' Test add_chain function '''
158+ def test_18_add_chain_failure (self ):
159+ ''' Test add_chain handles catastrophic failure '''
160160 self .library .client_ip = '3.4.5.6'
161161
162- # First assume horrific failure:
163162 with mock .patch .object (self .library , 'chain_exists' , side_effect = [True , True ]), \
164163 mock .patch .object (self .library , 'del_chain' ) as mock_delchain , \
165164 mock .patch .object (self .library , 'send_event' ) as mock_logger :
@@ -168,7 +167,11 @@ def test_18_add_chain(self):
168167 mock_delchain .assert_called_once_with ()
169168 self .assertEqual (mock_logger .call_count , 2 , 'Unremovable chain fails twice' )
170169
171- # Now, assume simple success:
170+
171+ def test_18_add_chain_simple_add_4 (self ):
172+ ''' Test add_chain function, assume simple success in v4 '''
173+ self .library .client_ip = '3.4.5.6'
174+
172175 with mock .patch .object (self .library , 'chain_exists' , return_value = False ), \
173176 mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft , \
174177 mock .patch .object (self .library , 'get_acls_for_user' ,
@@ -198,7 +201,11 @@ def test_18_add_chain(self):
198201 {'jump' : {'target' : '3.4.5.6' }}]}}},
199202 ]})
200203
201- # Now, copy all that again but assume that we had to do housekeeping:
204+
205+ def test_18_add_chain_with_housekeeping_4 (self ):
206+ ''' Test add_chain function, assume that we had to do housekeeping in v4 '''
207+ self .library .client_ip = '3.4.5.6'
208+
202209 with mock .patch .object (self .library , 'chain_exists' , side_effect = [True , False ]), \
203210 mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft , \
204211 mock .patch .object (self .library , 'del_chain' ) as mock_delchain , \
@@ -219,6 +226,11 @@ def test_18_add_chain(self):
219226 mock_nft .assert_called_once ()
220227 mock_block .assert_called_once_with ()
221228
229+
230+ def test_18_add_chain_with_failed_add_4 (self ):
231+ ''' Test add_chain function with a failed add in v4'''
232+ self .library .client_ip = '3.4.5.6'
233+
222234 # One last time, but fail the add:
223235 with mock .patch .object (self .library , 'chain_exists' , return_value = False ), \
224236 mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft , \
@@ -241,7 +253,7 @@ def test_18_add_chain(self):
241253 # a weird situation and if you ever stumble over this, look at it closely.
242254
243255
244- def test_19_del_chain (self ):
256+ def test_19_del_chain_4 (self ):
245257 ''' Test del_chain function '''
246258 self .library .client_ip = '2.3.4.5'
247259
@@ -332,19 +344,19 @@ def test_19_del_chain(self):
332344 # or built tests for, because we've not seen them/thought of them.
333345
334346
335- def test_30_build_fw_rule (self ):
347+ def test_30_build_fw_rule_4 (self ):
336348 ''' Test _build_firewall_rule_nftables function '''
337349 self .library .username_is = 'bob'
338350
339351 in_acl1 = iamvpnlibrary .iamvpnbase .ParsedACL (
340352 rule = '' , address = IPNetwork ('5.6.7.8' ), portstring = '80' , description = '' )
341353 with mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft :
342354 mock_nft .return_value = (0 , '' , '' )
343- self .library ._build_firewall_rule_nftables ('chain1 ' , '1.2.3.4' , 'tcp' , in_acl1 )
355+ self .library ._build_firewall_rule_nftables ('10.20.30.1 ' , '1.2.3.4' , 'tcp' , in_acl1 )
344356 mock_nft .assert_called_once_with ({'nftables' : [
345357 {'add' : {'rule' : {'family' : 'inet' ,
346358 'table' : 'openvpn_netfilter' ,
347- 'chain' : 'chain1 ' ,
359+ 'chain' : '10.20.30.1 ' ,
348360 'comment' : None ,
349361 'expr' : [{'match' : {
350362 'op' : '==' ,
@@ -363,17 +375,17 @@ def test_30_build_fw_rule(self):
363375 mock_nft .return_value = (- 1 , '' , 'someerror' )
364376 with self .assertRaises (NftablesFailure ,
365377 msg = '_build_firewall_rule_nftables raises when a rule add fails' ):
366- self .library ._build_firewall_rule_nftables ('chain1 ' , '1.2.3.4' , 'tcp' , in_acl1 )
378+ self .library ._build_firewall_rule_nftables ('10.20.30.1 ' , '1.2.3.4' , 'tcp' , in_acl1 )
367379
368380 in_acl2 = iamvpnlibrary .iamvpnbase .ParsedACL (
369381 rule = 'rule2' , address = IPNetwork ('5.6.7.9' ), portstring = '80' , description = 'I HAZ COMMENT' )
370382 with mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft :
371383 mock_nft .return_value = (0 , '' , '' )
372- self .library ._build_firewall_rule_nftables ('chain2 ' , '1.2.3.4' , 'tcp' , in_acl2 )
384+ self .library ._build_firewall_rule_nftables ('10.20.30.2 ' , '1.2.3.4' , 'tcp' , in_acl2 )
373385 mock_nft .assert_called_once_with ({'nftables' : [
374386 {'add' : {'rule' : {'family' : 'inet' ,
375387 'table' : 'openvpn_netfilter' ,
376- 'chain' : 'chain2 ' ,
388+ 'chain' : '10.20.30.2 ' ,
377389 'comment' : 'bob:rule2 ACL I HAZ COMMENT' ,
378390 'expr' : [{'match' : {
379391 'op' : '==' ,
@@ -393,11 +405,11 @@ def test_30_build_fw_rule(self):
393405 rule = '' , address = IPNetwork ('5.6.7.0/24' ), portstring = '' , description = '' )
394406 with mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft :
395407 mock_nft .return_value = (0 , '' , '' )
396- self .library ._build_firewall_rule_nftables ('chain3 ' , '1.2.3.4' , '' , ip_set_acl1 )
408+ self .library ._build_firewall_rule_nftables ('10.20.30.3 ' , '1.2.3.4' , '' , ip_set_acl1 )
397409 mock_nft .assert_called_once_with ({'nftables' : [
398410 {'add' : {'element' : {'family' : 'inet' ,
399411 'table' : 'openvpn_netfilter' ,
400- 'name' : 'chain3 ' ,
412+ 'name' : '10.20.30.3 ' ,
401413 'elem' : [ { 'prefix' : {
402414 'addr' : '5.6.7.0' ,
403415 'len' : 24 } }
@@ -407,30 +419,43 @@ def test_30_build_fw_rule(self):
407419 mock_nft .return_value = (- 1 , '' , 'someerror' )
408420 with self .assertRaises (NftablesFailure ,
409421 msg = '_build_firewall_rule_nftables raises when a set-element add fails' ):
410- self .library ._build_firewall_rule_nftables ('chain3 ' , '1.2.3.4' , '' , ip_set_acl1 )
422+ self .library ._build_firewall_rule_nftables ('10.20.30.3 ' , '1.2.3.4' , '' , ip_set_acl1 )
411423
412424 # comments don't work in nftables sets, so "the output here is the same"
413425 ip_set_acl2 = iamvpnlibrary .iamvpnbase .ParsedACL (
414426 rule = 'rule4' , address = IPNetwork ('5.6.7.11' ), portstring = '' , description = 'IPSET SET SET' )
415427 with mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft :
416428 mock_nft .return_value = (0 , '' , '' )
417- self .library ._build_firewall_rule_nftables ('chain4 ' , '1.2.3.4' , '' , ip_set_acl2 )
429+ self .library ._build_firewall_rule_nftables ('10.20.30.4 ' , '1.2.3.4' , '' , ip_set_acl2 )
418430 mock_nft .assert_called_once_with ({'nftables' : [
419431 {'add' : {'element' : {'family' : 'inet' ,
420432 'table' : 'openvpn_netfilter' ,
421- 'name' : 'chain4 ' ,
433+ 'name' : '10.20.30.4 ' ,
422434 'elem' : ['5.6.7.11' ] }}}]})
423435
436+ # Don't let v6 ACLs into v4 chains
437+ ip_set_acl3 = iamvpnlibrary .iamvpnbase .ParsedACL (
438+ rule = 'rule8' , address = IPNetwork ('2001:db8:1:2:3:4:5:8' ), portstring = '' , description = 'SOME SET' )
439+ with mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft :
440+ mock_nft .return_value = (0 , '' , '' )
441+ self .library ._build_firewall_rule_nftables ('10.20.30.4' , '1.2.3.4' , '' , ip_set_acl3 )
442+ mock_nft .assert_not_called ()
443+
424444
425- def test_31_create_rules (self ):
426- ''' Test create_user_rules function '''
445+ def test_31_create_rules_4 (self ):
446+ ''' Test create_user_rules function in v4 '''
427447 self .library .username_is = 'larry'
428448 self .library .client_ip = '2.3.4.5'
429449
430450 acl1 = iamvpnlibrary .iamvpnbase .ParsedACL (
431451 rule = 'rule2' , address = IPNetwork ('5.6.7.9' ), portstring = '80' , description = 'I HAZ COMMENT' )
432452 acl2 = iamvpnlibrary .iamvpnbase .ParsedACL (
433453 rule = 'rule4' , address = IPNetwork ('5.6.7.11' ), portstring = '' , description = 'IPSET SET SET' )
454+ # Send in v6 ACLs, but since we're v4 they won't appear at the exit
455+ acl3 = iamvpnlibrary .iamvpnbase .ParsedACL (
456+ rule = 'rule6' , address = IPNetwork ('2001:db8:1:2:3:4:5:6' ), portstring = '80' , description = 'MOAR COMMENTS' )
457+ acl4 = iamvpnlibrary .iamvpnbase .ParsedACL (
458+ rule = 'rule8' , address = IPNetwork ('2001:db8:1:2:3:4:5:8' ), portstring = '' , description = 'SOME SET' )
434459
435460 # Before we get too far into this, let's do the bad cases.
436461 # What if we can't make a chain/set for this person?
@@ -439,7 +464,7 @@ def test_31_create_rules(self):
439464 mock_nft .return_value = (- 1 , '' , '' )
440465 with self .assertRaises (NftablesFailure ,
441466 msg = 'create_user_rules raises when creation fails early' ):
442- self .library .create_user_rules ([acl1 , acl2 ])
467+ self .library .create_user_rules ([acl1 , acl2 , acl3 , acl4 ])
443468
444469 # What if we can make a chain/set for this person but then populating it fails?
445470 # skip going to _build_firewall_rule_nftables.. this failure check is to make sure
@@ -451,13 +476,13 @@ def test_31_create_rules(self):
451476 (- 1 , '' , '' )]
452477 with self .assertRaises (NftablesFailure ,
453478 msg = 'create_user_rules raises when creation fails in the second phase' ):
454- self .library .create_user_rules ([acl1 , acl2 ])
479+ self .library .create_user_rules ([acl1 , acl2 , acl3 , acl4 ])
455480
456481 # and now, the very complicated success route:
457482 with mock .patch .object (self .library .nft , 'json_cmd' ) as mock_nft , \
458483 mock .patch .object (self .library , '_ensure_nftables_framework' ) as mock_framework :
459484 mock_nft .return_value = (0 , '' , '' )
460- self .library .create_user_rules ([acl1 , acl2 ])
485+ self .library .create_user_rules ([acl1 , acl2 , acl3 , acl4 ])
461486 mock_framework .assert_called_once ()
462487 # A lot just happened. Time to check that nftables did the right things.
463488 # This is not necessarily written not in the order they were invoked.
@@ -657,8 +682,8 @@ def test_32_ensure_nftables_framework(self):
657682 # IMPROVEME: needs bad tests
658683
659684
660- def test_add_safety (self ):
661- ''' Test add_safety_block function '''
685+ def test_add_safety_4 (self ):
686+ ''' Test add_safety_block function in v4 '''
662687 self .library .client_ip = '10.20.30.40'
663688
664689 # Assume an add works:
@@ -685,8 +710,8 @@ def test_add_safety(self):
685710 self .library .add_safety_block ()
686711
687712
688- def test_del_safety (self ):
689- ''' Test add_safety_block function '''
713+ def test_del_safety_4 (self ):
714+ ''' Test add_safety_block function in v4 '''
690715 self .library .client_ip = '20.30.40.50'
691716
692717 good_rule_to_delete = {
0 commit comments