def test_intersect_rules(): r1 = [ Rule(src=ipset('1.0.0.0/24'), dst=ipset('0.0.0.0/0'), app='app', name='r1'), ] r2 = [ Rule(src=ipset('1.0.0.10', '1.0.0.14'), dst=ipset('0.0.0.0/0'), app='app', name='r2'), ] r3 = [ Rule(src=ipset('1.0.0.11', '1.0.0.14'), dst=ipset('0.0.0.0/0'), app='app', name='r3'), ] eq_( process.intersect_rules([r1, r2, r3], ipset('0.0.0.0/0'), ipset('2.0.0.0/8')), [ Rule(src=ipset('1.0.0.14'), dst=ipset('2.0.0.0/8'), app='app', name='r1+r2+r3'), ])
def test_rules_from_to_no_match_dst(): rules = [ Rule(src=ipset('1.0.0.0/8'), dst=ipset('3.0.0.0/24'), app='app', name='r'), ] eq_(process.rules_from_to(rules, ipset('1.0.0.0/8'), ipset('2.0.0.0/8')), [])
def test_limited_by_space(): lax_rules = {'app': [ ]} lga_rules = {'app': [ # /7 covers both lax and lga Rule(ipset('0.0.0.0/7'), ipset('2.0.0.0/8'), 'app', 'lga'), ]} ord_rules = {'app': [ Rule(ipset('0.0.0.0/7'), ipset('2.0.0.0/8'), 'app', 'ord'), ]} address_spaces = { 'lax': ipset('0.0.0.0/8'), 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } routes = { ('lax', 'lax'): ['fw1.lax'], ('lax', 'lga'): ['fw1.lga', 'fw1.lax'], ('lax', 'ord'): ['fw1.ord', 'fw1.lax'], ('lga', 'lax'): ['fw1.lax', 'fw1.lga'], ('lga', 'lga'): ['fw1.lga'], ('lga', 'ord'): ['fw1.ord', 'fw1.lga'], ('ord', 'lax'): ['fw1.ord', 'fw1.lax'], ('ord', 'lga'): ['fw1.ord', 'fw1.lga'], ('ord', 'ord'): ['fw1.ord'], } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules, 'fw1.lax': lax_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_(result, {'app': [ # only lga's address space is allowed Rule(ipset('1.0.0.0/8'), ipset('2.0.0.0/8'), 'app', 'lga+ord'), ]})
def test_one_address_space(): rules = {'app': [ Rule(ipset('1.2.3.4'), ipset('1.7.7.7'), 'app', 'p2p'), Rule(ipset('1.2.5.0/24'), ipset('1.7.7.7'), 'app', 'net'), ]} with no_simplify(): result = process.combine( {'nyc': ipset('1.0.0.0/8')}, {('nyc', 'nyc'): ['fw1.nyc']}, {'fw1.nyc': rules}) eq_(sorted(result), sorted(rules))
def test_make_diff(): eq_(sorted(diff.make_diff(FakeSource(LEFT), FakeSource(RIGHT))), sorted([ # expand stage from /25 to /24 ('+', 'db', ipset('10.20.20.128/25'), ipset('10.20.30.16')), ('+', 'http', ipset('0.0.0.0/0'), ipset('10.20.20.128/25')), ('+', 'ssh', ipset('10.2.1.1'), ipset('10.20.20.128/25')), # add production db server ('+', 'db', ipset('10.20.19.0/24'), ipset('10.20.30.28')), # remove ssh access to production ('-', 'ssh', ipset('10.2.1.1'), ipset('10.20.19.0/24', '10.20.30.15', '10.20.30.19')), ]))
def test_identical_rules(): rules = {'app': [ Rule(ipset('2.7.7.0/24'), ipset('1.7.7.0/24'), 'app', 'lga-ord'), ]} address_spaces = { 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } sources = {'fw1.ord': rules, 'fw1.lga': rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_(result, rules)
def test_one_address_space(): rules = { 'app': [ Rule(ipset('1.2.3.4'), ipset('1.7.7.7'), 'app', 'p2p'), Rule(ipset('1.2.5.0/24'), ipset('1.7.7.7'), 'app', 'net'), ] } with no_simplify(): result = process.combine({'nyc': ipset('1.0.0.0/8')}, {('nyc', 'nyc'): ['fw1.nyc']}, {'fw1.nyc': rules}) eq_(sorted(result), sorted(rules))
def test_identical_rules(): rules = { 'app': [ Rule(ipset('2.7.7.0/24'), ipset('1.7.7.0/24'), 'app', 'lga-ord'), ] } address_spaces = { 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } sources = {'fw1.ord': rules, 'fw1.lga': rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_(result, rules)
def test_overlapping_rules(): lga_rules = { 'app': [ Rule(ipset('1.1.0.0/16'), ipset('2.0.0.0/8'), 'app', 'lga'), ] } ord_rules = { 'app': [ Rule(ipset('1.0.0.0/8'), ipset('2.1.0.0/16'), 'app', 'ord'), ] } address_spaces = { 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_( result, { 'app': [ # takes the intersection of both rules: Rule(ipset('1.1.0.0/16'), ipset('2.1.0.0/16'), 'app', 'lga+ord'), ] })
def test_intersect_rules(): r1 = [ Rule(src=ipset('1.0.0.0/24'), dst=ipset('0.0.0.0/0'), app='app', name='r1'), ] r2 = [ Rule(src=ipset('1.0.0.10', '1.0.0.14'), dst=ipset('0.0.0.0/0'), app='app', name='r2'), ] r3 = [ Rule(src=ipset('1.0.0.11', '1.0.0.14'), dst=ipset('0.0.0.0/0'), app='app', name='r3'), ] eq_(process.intersect_rules([r1, r2, r3], ipset('0.0.0.0/0'), ipset('2.0.0.0/8')), [ Rule(src=ipset('1.0.0.14'), dst=ipset('2.0.0.0/8'), app='app', name='r1+r2+r3'), ])
def test_rules_from_to_intersection(): rules = [ Rule(src=ipset('0.0.0.0/7'), dst=ipset('2.0.1.0/24'), app='app', name='r'), ] eq_(process.rules_from_to(rules, ipset('1.0.0.0/8'), ipset('2.0.0.0/8')), [ Rule(src=ipset('1.0.0.0/8'), dst=ipset('2.0.1.0/24'), app='app', name='r'), ])
def test_limited_by_space(): lax_rules = {'app': []} lga_rules = { 'app': [ # /7 covers both lax and lga Rule(ipset('0.0.0.0/7'), ipset('2.0.0.0/8'), 'app', 'lga'), ] } ord_rules = { 'app': [ Rule(ipset('0.0.0.0/7'), ipset('2.0.0.0/8'), 'app', 'ord'), ] } address_spaces = { 'lax': ipset('0.0.0.0/8'), 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } routes = { ('lax', 'lax'): ['fw1.lax'], ('lax', 'lga'): ['fw1.lga', 'fw1.lax'], ('lax', 'ord'): ['fw1.ord', 'fw1.lax'], ('lga', 'lax'): ['fw1.lax', 'fw1.lga'], ('lga', 'lga'): ['fw1.lga'], ('lga', 'ord'): ['fw1.ord', 'fw1.lga'], ('ord', 'lax'): ['fw1.ord', 'fw1.lax'], ('ord', 'lga'): ['fw1.ord', 'fw1.lga'], ('ord', 'ord'): ['fw1.ord'], } sources = { 'fw1.ord': ord_rules, 'fw1.lga': lga_rules, 'fw1.lax': lax_rules } with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_( result, { 'app': [ # only lga's address space is allowed Rule(ipset('1.0.0.0/8'), ipset('2.0.0.0/8'), 'app', 'lga+ord'), ] })
def test_overlapping_rules(): lga_rules = {'app': [ Rule(ipset('1.1.0.0/16'), ipset('2.0.0.0/8'), 'app', 'lga'), ]} ord_rules = {'app': [ Rule(ipset('1.0.0.0/8'), ipset('2.1.0.0/16'), 'app', 'ord'), ]} address_spaces = { 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_(result, {'app': [ # takes the intersection of both rules: Rule(ipset('1.1.0.0/16'), ipset('2.1.0.0/16'), 'app', 'lga+ord'), ]})
def test_nonoverlapping_rules(): lga_rules = {'app': [ Rule(ipset('1.2.5.0/24'), ipset('2.2.5.0/24'), 'app', 'lga'), ]} ord_rules = {'app': [ Rule(ipset('2.7.7.0/24'), ipset('1.7.7.0/24'), 'app', 'ord'), ]} address_spaces = { 'ord': ipset('2.0.0.0/8'), 'lga': ipset('1.0.0.0/8'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_(result, {})
def test_process_global_priority(): # test the relative priority of "regular" (per-zone) and global policies policies = [ mkpol(name='ok', from_zone='pvt', to_zone='pub', src_addrs=ipset('192.168.1.2/31'), dst_addrs=ipset('0.0.0.0/0'), applications=['junos-ssh'], sequence=100), mkpol(name='deny-all-global', from_zone=None, to_zone=None, src_addrs=ipset('0.0.0.0/0'), dst_addrs=ipset('0.0.0.0/0'), applications=['junos-ssh'], sequence=3, action='deny'), mkpol(name='ok-global', from_zone=None, to_zone=None, src_addrs=ipset('192.168.1.128/32'), dst_addrs=ipset('128.135.0.0/16'), applications=['junos-ssh'], sequence=1), ] res = call_process_rules(APP_MAP, policies, ZONE_NETS) exp = { 'junos-ssh': [ Rule(src=ipset('192.168.1.128/32', '192.168.1.2/31'), dst=ipset('128.135.0.0/16'), app='junos-ssh', name='ok+ok-global'), ], } [ruleset.sort() for ruleset in exp.itervalues()] eq_(res, exp)
def test_nonoverlapping_rules(): lga_rules = { 'app': [ Rule(ipset('1.2.5.0/24'), ipset('2.2.5.0/24'), 'app', 'lga'), ] } ord_rules = { 'app': [ Rule(ipset('2.7.7.0/24'), ipset('1.7.7.0/24'), 'app', 'ord'), ] } address_spaces = { 'ord': ipset('2.0.0.0/8'), 'lga': ipset('1.0.0.0/8'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_(result, {})
def test_process_interface_ips(): routes = [ # reth2 is the route to the Internet mkroute(destination="0.0.0.0/0", interface='reth2'), # reth1 is the gateway to the rest of the private space mkroute(destination="10.0.0.0/8", interface='reth1'), # reth7 is the peer link to some other private /16's mkroute(destination="10.128.0.0/16", interface='reth7'), mkroute(destination="10.130.0.0/15", interface='reth7'), # 10.129.0.0/16 is ours, but has only one active subnet, # with the rest blackholed mkroute(destination="10.129.0.0/16", reject=True), mkroute(destination="10.129.210.0/24", interface='reth0.210', is_local=True), ] interface_ips = process.process_interface_ips(routes) exp = { 'reth0.210': ipset('10.129.210.0/24'), 'reth1': ipset('10.0.0.0/8') - ipset('10.128.0.0/14'), # 10.{128-131} 'reth2': ipset('0.0.0.0/0') - ipset('10.0.0.0/8'), 'reth7': ipset('10.128.0.0/16') + ipset('10.130.0.0/15'), } eq_(interface_ips, exp)
'fw.nyc': { 'output': 'fw.nyc.json' }, 'enterprise': { 'address_spaces': { 'ord': '100.0.0.0/8', 'lax': '200.0.0.0/8', 'nyc': '240.0.0.0/8', }, 'routes': {}, }, } exp_address_spaces = { 'ord': ipset('100.0.0.0/8'), 'lax': ipset('200.0.0.0/8'), 'nyc': ipset('240.0.0.0/8'), 'unmanaged': ipset('0.0.0.0/0') - ipset('100.0.0.0/8') - ipset('200.0.0.0/8') - ipset('240.0.0.0/8'), } empty_exp_routes = {(s, d): set() for s in exp_address_spaces for d in exp_address_spaces} def exp_sources(*srcs): return {s: "rules for " + s for s in srcs}
def test_sourcesFor_unknown_app(): eq_(rules.sourcesFor('10.1.1.1', 'somerandomapp'), ipset('1.2.3.4'))
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from nose.tools import eq_ from fwunit.srx import parse from fwunit.srx import process from fwunit.common import ApplicationMap from fwunit.test.util import ipset from fwunit.types import Rule from fwunit import IP APP_MAP = ApplicationMap(dict(application_map={'junos-ssh': 'ssh'})) ZONE_NETS = { 'pvt': ipset('192.168.0.0/16'), 'dmz': ipset('10.0.0.0/8'), 'pub': ipset('128.135.0.00/16'), } def mkpol(**kwargs): kwargs.setdefault('action', 'permit') kwargs.setdefault('enabled', True) kwargs.setdefault('sequence', 1) kwargs['source_addresses'] = kwargs.pop('src_addrs') kwargs['destination_addresses'] = kwargs.pop('dst_addrs') pol = parse.Policy() for k, v in kwargs.iteritems(): setattr(pol, k, v) return pol
def test_process_rules_any_app(): # test basic functionality + the "any" app policies = [ mkpol(name='dbssh', from_zone='pvt', to_zone='pvt', src_addrs=ipset('192.168.1.2/31'), dst_addrs=ipset('0.0.0.0/0'), applications=['junos-ssh', 'junos-ping'], sequence=1), mkpol(name='admin', from_zone='pvt', to_zone='pvt', src_addrs=ipset('192.168.1.128/32'), dst_addrs=ipset('0.0.0.0/0'), applications=['any'], sequence=2), mkpol(name='admin', from_zone='pvt', to_zone='dmz', src_addrs=ipset('192.168.1.128/32'), dst_addrs=ipset('0.0.0.0/0'), applications=['any']), mkpol(name='admin', from_zone='pvt', to_zone='pub', src_addrs=ipset('192.168.1.128/32'), dst_addrs=ipset('0.0.0.0/0'), applications=['any']), mkpol(name='http', from_zone='pub', to_zone='dmz', src_addrs=ipset('0.0.0.0/0'), dst_addrs=ipset('10.1.10.0/24'), applications=['web']), mkpol(name='db', from_zone='dmz', to_zone='pvt', src_addrs=ipset('10.1.10.0/24'), dst_addrs=ipset('192.168.1.2/31'), applications=['db']), ] res = call_process_rules(APP_MAP, policies, ZONE_NETS) exp = { 'junos-ping': [ Rule(src=ipset('192.168.1.128'), dst=ipset('10.0.0.0/8', '128.135.0.0/16', '192.168.0.0/16'), app='junos-ping', name='admin'), Rule(src=ipset('192.168.1.2/31'), dst=ipset('192.168.0.0/16'), app='junos-ping', name='dbssh'), ], 'web': [ Rule(src=ipset('192.168.1.128'), dst=ipset('10.0.0.0/8', '128.135.0.0/16', '192.168.0.0/16'), app='web', name='admin'), Rule(src=ipset('128.135.0.0/16'), dst=ipset('10.1.10.0/24'), app='web', name='http'), ], 'db': [ Rule(src=ipset('192.168.1.128'), dst=ipset('10.0.0.0/8', '128.135.0.0/16', '192.168.0.0/16'), app='db', name='admin'), Rule(src=ipset('10.1.10.0/24'), dst=ipset('192.168.1.2/31'), app='db', name='db'), ], 'junos-ssh': [ Rule(src=ipset('192.168.1.128'), dst=ipset('10.0.0.0/8', '128.135.0.0/16', '192.168.0.0/16'), app='junos-ssh', name='admin'), Rule(src=ipset('192.168.1.2/31'), dst=ipset('192.168.0.0/16'), app='junos-ssh', name='dbssh'), ], '@@other': [ Rule(src=ipset('192.168.1.128'), dst=ipset('10.0.0.0/8', '128.135.0.0/16', '192.168.0.0/16'), app='@@other', name='admin'), ], } [ruleset.sort() for ruleset in exp.itervalues()] eq_(res, exp)
def test_rules_from_to_empty(): eq_(process.rules_from_to([], ipset('1.0.0.0/8'), ipset('2.0.0.0/8')), [])
def test_combine(): address_spaces = { 'ten': ipset('10.0.0.0/8'), 'twenty': ipset('20.0.0.0/8'), 'unmanaged': ipset('0.0.0.0/0') - ipset('10.0.0.0/8') - ipset('20.0.0.0/8'), } routes = { ('ten', 'ten'): ['fw1.ten'], ('ten', 'twenty'): ['fw1.ten', 'fw1.twenty'], ('ten', 'unmanaged'): ['fw1.ten'], ('twenty', 'ten'): ['fw1.ten', 'fw1.twenty'], ('twenty', 'twenty'): ['fw1.twenty'], ('twenty', 'unmanaged'): ['fw1.twenty'], ('unmanaged', 'ten'): ['fw1.ten'], ('unmanaged', 'twenty'): ['fw1.twenty'], ('unmanaged', 'unmanaged'): [], } sources = { 'fw1.ten': RULES_10, 'fw1.twenty': RULES_20, } res = process.combine(address_spaces, routes, sources) res['http'].sort() eq_(res, { 'http': sorted([ Rule(src=ipset('10.10.0.0/16'), dst=ipset('10.20.0.0/16', '30.20.0.0/16'), app='http', name='10->10+10->30'), Rule(src=ipset('20.10.0.0/16'), dst=ipset('20.20.0.0/16', '30.20.0.0/16'), app='http', name='20->20+20->30'), Rule(src=ipset('30.10.0.0/16'), dst=ipset('10.20.0.0/16', '20.20.0.0/16'), app='http', name='30->10+30->20'), # note that only the intersection of these flows makes it through Rule(src=ipset('10.20.0.0/16'), dst=ipset('20.20.0.0/16'), app='http', name='10->20'), Rule(src=ipset('20.20.0.0/16'), dst=ipset('10.20.0.0/16'), app='http', name='20->10'), ]), })
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from nose.tools import eq_ from fwunit.srx import parse from fwunit.srx import process from fwunit.common import ApplicationMap from fwunit.test.util import ipset from fwunit.types import Rule from fwunit import IP APP_MAP = ApplicationMap(dict(application_map={'junos-ssh': 'ssh'})) ZONE_NETS = { 'pvt': ipset('192.168.0.0/16'), 'dmz': ipset('10.0.0.0/8'), 'pub': ipset('128.135.0.00/16'), } def mkpol(**kwargs): kwargs.setdefault('action', 'permit') kwargs.setdefault('enabled', True) kwargs.setdefault('sequence', 1) pol = parse.Policy() for k, v in kwargs.iteritems(): setattr(pol, k, v) return pol def call_process_rules(app_map, policies, zone_nets): # calculate a few of the extra inputs policies_by_zone_pair = {}
def test_multiple_matches(): lga_rules = {'app': [ Rule(ipset('1.1.1.1'), ipset('2.0.0.0/8'), 'app', 'one'), Rule(ipset('1.1.1.2'), ipset('2.0.0.0/8'), 'app', 'two'), Rule(ipset('1.1.1.3'), ipset('2.0.0.0/8'), 'app', 'three'), ]} ord_rules = {'app': [ Rule(ipset('1.0.0.0/8'), ipset('2.7.8.8'), 'app', 'eight'), Rule(ipset('1.0.0.0/8'), ipset('2.7.8.9'), 'app', 'nine'), ]} address_spaces = { 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_(sorted(result['app']), sorted([ # takes the intersection of all rules: Rule(src=ipset('1.1.1.1'), dst=ipset('2.7.8.8'), app='app', name='eight+one'), Rule(src=ipset('1.1.1.1'), dst=ipset('2.7.8.9'), app='app', name='nine+one'), Rule(src=ipset('1.1.1.2'), dst=ipset('2.7.8.8'), app='app', name='eight+two'), Rule(src=ipset('1.1.1.2'), dst=ipset('2.7.8.9'), app='app', name='nine+two'), Rule(src=ipset('1.1.1.3'), dst=ipset('2.7.8.8'), app='app', name='eight+three'), Rule(src=ipset('1.1.1.3'), dst=ipset('2.7.8.9'), app='app', name='nine+three') ]))
def test_multiple_matches(): lga_rules = { 'app': [ Rule(ipset('1.1.1.1'), ipset('2.0.0.0/8'), 'app', 'one'), Rule(ipset('1.1.1.2'), ipset('2.0.0.0/8'), 'app', 'two'), Rule(ipset('1.1.1.3'), ipset('2.0.0.0/8'), 'app', 'three'), ] } ord_rules = { 'app': [ Rule(ipset('1.0.0.0/8'), ipset('2.7.8.8'), 'app', 'eight'), Rule(ipset('1.0.0.0/8'), ipset('2.7.8.9'), 'app', 'nine'), ] } address_spaces = { 'lga': ipset('1.0.0.0/8'), 'ord': ipset('2.0.0.0/8'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) eq_( sorted(result['app']), sorted([ # takes the intersection of all rules: Rule(src=ipset('1.1.1.1'), dst=ipset('2.7.8.8'), app='app', name='eight+one'), Rule(src=ipset('1.1.1.1'), dst=ipset('2.7.8.9'), app='app', name='nine+one'), Rule(src=ipset('1.1.1.2'), dst=ipset('2.7.8.8'), app='app', name='eight+two'), Rule(src=ipset('1.1.1.2'), dst=ipset('2.7.8.9'), app='app', name='nine+two'), Rule(src=ipset('1.1.1.3'), dst=ipset('2.7.8.8'), app='app', name='eight+three'), Rule(src=ipset('1.1.1.3'), dst=ipset('2.7.8.9'), app='app', name='nine+three') ]))
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. import mock import re from nose.tools import eq_ from fwunit.types import Rule from fwunit.analysis import sources from fwunit.test.util import ipset from fwunit import diff TEN = ipset('10.10.0.0/16') TEN_0 = ipset('10.10.0.0/17') TEN_128 = ipset('10.10.128.0/17') TWENTY = ipset('10.20.0.0/16') TWENTY_0 = ipset('10.20.0.0/17') TWENTY_128 = ipset('10.20.128.0/17') LEFT = { 'http': [ Rule(src=ipset('0.0.0.0/0'), dst=ipset('10.20.19.0/24'), app='http', name='web access'), Rule(src=ipset('0.0.0.0/0'), dst=ipset('10.20.20.0/25'), app='http', name='stage web access'), ], 'https': [ Rule(src=ipset('0.0.0.0/0'), dst=ipset('10.20.19.0/24'), app='https', name='https web access'), ], 'db': [ Rule(src=ipset('10.20.19.0/24'), dst=ipset('10.20.30.15', '10.20.30.19'), app='db', name='db'), Rule(src=ipset('10.20.20.0/25'), dst=ipset('10.20.30.16'), app='db', name='stage db'),
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from nose.tools import eq_ from fwunit.types import Rule from fwunit.combine import process from fwunit.test.util import ipset RULES_10 = { 'http': [ # within this ip space Rule(src=ipset('10.10.0.0/16'), dst=ipset('10.20.0.0/16'), app='http', name='10->10'), # from and to "unmanaged" space Rule(src=ipset('30.10.0.0/16'), dst=ipset('10.20.0.0/16'), app='http', name='30->10'), Rule(src=ipset('10.10.0.0/16'), dst=ipset('30.20.0.0/16'), app='http', name='10->30'), # from and to the 20/8 space Rule(src=ipset('20.20.0.0/16', '20.30.0.0/16'), dst=ipset('10.20.0.0/16', '10.30.0.0/16'), app='http', name='20->10'), Rule(src=ipset('10.10.0.0/16', '10.20.0.0/16'), dst=ipset('20.10.0.0/16', '20.20.0.0/16'), app='http', name='10->20'), ], } RULES_20 = { 'http': [ # within this ip space Rule(src=ipset('20.10.0.0/16'), dst=ipset('20.20.0.0/16'), app='http', name='20->20'), # from and to "unmanaged" space
# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. from fwunit.types import Rule from fwunit.test.util import ipset TEST_RULES = { 'ping': [ Rule(src=ipset('0.0.0.0/0') - ipset('10.0.0.0/8'), dst=ipset('10.1.0.0/16') - ipset('10.1.99.99'), app='ping', name='ping'), ], 'puppet': [ Rule(src=ipset('10.0.0.0/8'), dst=ipset('10.0.9.2'), app='puppet', name='puppet'), ], 'ssh': [ Rule(src=ipset('9.0.9.2'), dst=ipset('10.0.9.2'), app='ssh', name='admin'), Rule(src=ipset('10.0.0.0/8'), dst=ipset('0.0.0.0/0'), app='ssh', name='ssh--any+ssh-untrust'), ], '@@other': [ Rule(src=ipset('1.2.3.4/32'), dst=ipset('0.0.0.0/0'), app='@@other', name='admin-access') ], }
from fwunit import TestContext from fwunit import types from fwunit import scripts from fwunit.test.util import ipset FWUNIT_YAML = { 'rules': { 'type': 'anything', 'output': 'rules.json', } } RULES = { 'http': [ # within this ip space types.Rule(src=ipset('10.10.0.0/16'), dst=ipset('10.20.0.0/16'), app='http', name='10->10'), # from and to "unmanaged" space types.Rule(src=ipset('30.10.0.0/16'), dst=ipset('10.20.0.0/16'), app='http', name='30->10'), types.Rule(src=ipset('10.10.0.0/16'), dst=ipset('30.20.0.0/16'), app='http', name='10->30'), # from and to the 20/8 space types.Rule(src=ipset('20.20.0.0/16', '20.30.0.0/16'), dst=ipset('10.20.0.0/16', '10.30.0.0/16'),
def test_combine(): address_spaces = { 'ten': ipset('10.0.0.0/8'), 'twenty': ipset('20.0.0.0/8'), 'unmanaged': ipset('0.0.0.0/0') - ipset('10.0.0.0/8') - ipset('20.0.0.0/8'), } routes = { ('ten', 'ten'): ['fw1.ten'], ('ten', 'twenty'): ['fw1.ten', 'fw1.twenty'], ('ten', 'unmanaged'): ['fw1.ten'], ('twenty', 'ten'): ['fw1.ten', 'fw1.twenty'], ('twenty', 'twenty'): ['fw1.twenty'], ('twenty', 'unmanaged'): ['fw1.twenty'], ('unmanaged', 'ten'): ['fw1.ten'], ('unmanaged', 'twenty'): ['fw1.twenty'], ('unmanaged', 'unmanaged'): [], } sources = { 'fw1.ten': RULES_10, 'fw1.twenty': RULES_20, } res = process.combine(address_spaces, routes, sources) res['http'].sort() eq_( res, { 'http': sorted([ Rule(src=ipset('10.10.0.0/16'), dst=ipset('10.20.0.0/16', '30.20.0.0/16'), app='http', name='10->10+10->30'), Rule(src=ipset('20.10.0.0/16'), dst=ipset('20.20.0.0/16', '30.20.0.0/16'), app='http', name='20->20+20->30'), Rule(src=ipset('30.10.0.0/16'), dst=ipset('10.20.0.0/16', '20.20.0.0/16'), app='http', name='30->10+30->20'), # note that only the intersection of these flows makes it through Rule(src=ipset('10.20.0.0/16'), dst=ipset('20.20.0.0/16'), app='http', name='10->20'), Rule(src=ipset('20.20.0.0/16'), dst=ipset('10.20.0.0/16'), app='http', name='20->10'), ]), })
def test_other_app(): ord_rules = { 'ordonly': [ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), 'ordonly', 'ordonly'), ], 'inboth': [ Rule(ipset('1.1.8.8'), ipset('1.1.9.9'), 'inboth', 'inboth_ord'), ], '@@other': [ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), '@@other', 'ordother'), ], } lga_rules = { 'lgaonly': [ Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), 'lgaonly', 'lgaonly'), ], 'inboth': [ Rule(ipset('65.1.8.8'), ipset('65.1.9.9'), 'inboth', 'inboth_lga'), ], '@@other': [ Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), '@@other', 'lgaother'), ], } address_spaces = { 'ord': ipset('0.0.0.0/2'), 'lga': ipset('64.0.0.0/2'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) for apprules in result.itervalues(): apprules.sort() eq_( result, { 'ordonly': sorted([ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), 'ordonly', 'ordonly'), Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), 'ordonly', 'lgaother'), ]), 'lgaonly': sorted([ Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), 'lgaonly', 'lgaonly'), Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), 'lgaonly', 'ordother'), ]), 'inboth': sorted([ Rule(ipset('1.1.8.8'), ipset('1.1.9.9'), 'inboth', 'inboth_ord'), Rule(ipset('65.1.8.8'), ipset('65.1.9.9'), 'inboth', 'inboth_lga'), ]), '@@other': sorted([ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), '@@other', 'ordother'), Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), '@@other', 'lgaother'), ]), })
def test_sourcesFor(): eq_(rules.sourcesFor('10.1.1.1', 'ssh'), ipset('10.0.0.0/8'))
'fw.ord': {'output': 'fw.ord.json'}, 'fw.lax': {'output': 'fw.lax.json'}, 'fw.nyc': {'output': 'fw.nyc.json'}, 'enterprise': { 'address_spaces': { 'ord': '100.0.0.0/8', 'lax': '200.0.0.0/8', 'nyc': '240.0.0.0/8', }, 'routes': { }, }, } exp_address_spaces = { 'ord': ipset('100.0.0.0/8'), 'lax': ipset('200.0.0.0/8'), 'nyc': ipset('240.0.0.0/8'), 'unmanaged': ipset('0.0.0.0/0') - ipset('100.0.0.0/8') - ipset('200.0.0.0/8') - ipset('240.0.0.0/8'), } empty_exp_routes = { (s, d): set() for s in exp_address_spaces for d in exp_address_spaces } def exp_sources(*srcs): return {s: "rules for " + s for s in srcs}
def test_other_app(): ord_rules = { 'ordonly': [ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), 'ordonly', 'ordonly'), ], 'inboth': [ Rule(ipset('1.1.8.8'), ipset('1.1.9.9'), 'inboth', 'inboth_ord'), ], '@@other': [ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), '@@other', 'ordother'), ], } lga_rules = { 'lgaonly': [ Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), 'lgaonly', 'lgaonly'), ], 'inboth': [ Rule(ipset('65.1.8.8'), ipset('65.1.9.9'), 'inboth', 'inboth_lga'), ], '@@other': [ Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), '@@other', 'lgaother'), ], } address_spaces = { 'ord': ipset('0.0.0.0/2'), 'lga': ipset('64.0.0.0/2'), } sources = {'fw1.ord': ord_rules, 'fw1.lga': lga_rules} with no_simplify(): result = process.combine(address_spaces, routes, sources) for apprules in result.itervalues(): apprules.sort() eq_(result, { 'ordonly': sorted([ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), 'ordonly', 'ordonly'), Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), 'ordonly', 'lgaother'), ]), 'lgaonly': sorted([ Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), 'lgaonly', 'lgaonly'), Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), 'lgaonly', 'ordother'), ]), 'inboth': sorted([ Rule(ipset('1.1.8.8'), ipset('1.1.9.9'), 'inboth', 'inboth_ord'), Rule(ipset('65.1.8.8'), ipset('65.1.9.9'), 'inboth', 'inboth_lga'), ]), '@@other': sorted([ Rule(ipset('1.1.0.0'), ipset('1.1.9.9'), '@@other', 'ordother'), Rule(ipset('65.1.0.0'), ipset('65.1.9.9'), '@@other', 'lgaother'), ]), })