def test_delete_already_deleted_host(self): # Verify a stale href that was deleted gives expected error Host.create('tyler', '1.1.1.1') host = Host('tyler').href Host('tyler').delete() result = SMCRequest(href=host).delete() self.assertIsNotNone(result.msg)
def tearDown(self): try: Host('test-common-api-user').delete() Host('test-api-user').delete() session.logout() except SystemExit: pass
def test_update_or_create(self): host = Host.update_or_create(name='autohost', address='1.1.1.1') self.assertEqual(host.name, 'autohost') self.assertEqual(host.address, '1.1.1.1') host = Host.update_or_create(name='autohost', address='2.2.2.2') self.assertEqual(host.name, 'autohost') self.assertEqual(host.address, '2.2.2.2') host.delete() network = Network.update_or_create( filter_key={'ipv4_network': '192.168.10.0/24'}, name='somenetwork', ipv4_network='192.168.10.0/24') self.assertEqual(network.name, 'somenetwork') self.assertEqual(network.ipv4_network, '192.168.10.0/24') network = Network.update_or_create( filter_key={'ipv4_network': '192.168.10.0/24'}, name='someothernetwork', ipv4_network='192.168.11.0/24') self.assertEqual(network.name, 'someothernetwork') self.assertEqual(network.ipv4_network, '192.168.11.0/24') network.delete()
def test_ospf_unicast(self): for profile in list(Search('ospfv2_interface_settings').objects.all()): if profile.name.startswith('Default OSPF'): interface_profile = profile.href area = OSPFArea.create(name='smcpython-area', interface_settings_ref=interface_profile, area_id=0) self.assertTrue(area.href.startswith('http')) area = OSPFArea('smcpython-area') engine = Layer3Firewall.create(name='smcpython-ospf', mgmt_ip='172.18.1.30', mgmt_network='172.18.1.0/24', domain_server_address=['8.8.8.8'], enable_ospf=True) self.assertIsInstance(engine, Engine) host = Host.create(name='smcpython-ospf-user', address='23.23.23.23') # Get routing resources for interface in engine.routing.all(): if interface.name == 'Interface 0': result = interface.add_ospf_area(area, communication_mode='unicast', unicast_ref=host) self.assertIsNone(result) engine.delete() area.delete() Host('smcpython-ospf-user').delete()
def test_dynamic_source_nat(self): options = LogOptions() rule_values = {} nat = DynamicSourceNAT(options.data) nat.translated_value = '12.12.12.12' nat.translated_ports = (2000, 60000) rule_values.update(options=nat.data) self.assertEqual(nat.translated_value, '12.12.12.12') self.assertEqual(nat.translated_ports, (2000, 60000)) nat.translated_value = '13.13.13.13' nat.translated_ports = (1000, 10001) self.assertEqual(nat.translated_value, '13.13.13.13') self.assertEqual(nat.translated_ports, (1000, 10001)) self.assertIsNone(nat.original_value) options = LogOptions() host = Host('test', href='http://1.1.1.1') nat = DynamicSourceNAT(options.data) nat.translated_ports = (6000, 10000) nat.translated_value = host self.assertEqual(nat.translated_ports, (6000, 10000)) self.assertEqual(nat.translated_value, 'http://1.1.1.1') # Add bad host, translated value should not change with patch('smc.base.model.Element.href', new_callable=PropertyMock) as foo: foo.side_effect = ElementNotFound nat.translated_value = Host('foo') # Still original value self.assertEqual(nat.translated_value, 'http://1.1.1.1')
def test_element_resolver(self): host = Host.create('hostelement', address='1.1.1.1') resolved = element_resolver([Host('hostelement'), 'http://2.2.2.2']) for r in resolved: self.assertIn(r, [host.href, 'http://2.2.2.2']) # Catches ElementNotFound in list with self.assertRaises(ElementNotFound): element_resolver(elements=[Host('foobarblah')])
def test_ipv6host(self): result = Host.create(name='mixedhost', ipv6_address='2001:cdba::3257:9652') self.assertTrue(result.href.startswith('http')) host = Host('mixedhost') self.assertEqual(host.ipv6_address, '2001:cdba::3257:9652') host.delete()
def test_modify_non_system_element(self): # Non system elements can be modified result = Host.create('api-test', '2.3.4.5') self.assertTrue(result.href.startswith('http')) host = Host('api-test') result = host.modify_attribute(name='newapi-test') self.assertTrue(result.startswith('http')) Host('newapi-test').delete()
def test_category_tag(self): category = Category.create('foo', comment='mycomment') self.assertTrue(category.href.startswith('http')) category = Category('foo') host = Host.create(name='categoryelement', address='1.1.1.1') # Add category tag by HREF result = category.add_element(host) self.assertIsNone(result) # Search result result = category.search_elements() self.assertTrue(result) # Not [] self.assertTrue(result[0].name == 'categoryelement') # Find the category tag from the element result = Host('categoryelement').categories self.assertTrue(result) self.assertTrue(result[0].name == 'foo') # Remove category result = category.remove_element(host) self.assertIsNone(result) # Add by smc.base.model.Element result = category.add_element(Host('categoryelement')) self.assertIsNone(result) # Search result result = category.search_elements() self.assertTrue(result) # Not [] self.assertTrue(result[0].name == 'categoryelement') # Delete result by smc.base.model.Element result = category.remove_element(Host('categoryelement')) self.assertIsNone(result) category_tag = CategoryTag.create(name='footag') category.add_category_tag([category_tag.href]) for tag in category.categories: self.assertEqual(tag.name, 'footag') with self.assertRaises(DeleteElementFailed): Category('foo').delete() #Dependencies category_tag = Element.from_href(category_tag.href) for category in category_tag.child_categories: self.assertTrue(category.name, 'foo') self.assertFalse(category_tag.parent_categories) # Throwing when __setattr__ set category_tag.remove_category([Category('foo')]) Host('categoryelement').delete() Category('foo').delete()
def test_update_no_etag(self): # Failed PUT request Host.create('tyler', '1.1.1.1') a = Host('tyler') element = a.data element.update(name='newtyler') result = SMCRequest(href=a.href, json=element).update() self.assertIsNotNone(result.msg) Host('tyler').delete()
def test_ipv6_address_with_secondary_ipv4(self): result = Host.create(name='mixedhost', ipv6_address='2001:cdba::3257:9652', secondary=['1.1.1.1']) self.assertTrue(result.href.startswith('http')) host = Host('mixedhost') self.assertEqual(host.ipv6_address, '2001:cdba::3257:9652') self.assertIn('1.1.1.1', host.secondary) host.delete()
def test_create_error_with_unicode(self): host = Host.create('Curaçao34', '22.22.22.22') self.assertTrue(host.href.startswith('http')) # fail because it already exists with self.assertRaises(CreateElementFailed): err = Host.create('Curaçao34', '22.22.22.22') import re myre = re.compile(r'.*Curaçao+') self.assertRegexpMatches(err, myre) Host('Curaçao34').delete()
def testReferencesByElement(self): system = System() Host.create('systemhost', '1.1.1.1') host = Host('systemhost') self.assertFalse(system.references_by_element(host.href)) # Add a group and the member to create a reference Group.create(name='systemgroup', members=[host.href]) for references in system.references_by_element(host.href): self.assertEqual(references.get('href'), Group('systemgroup').href) Group('systemgroup').delete() Host('systemhost').delete()
def test_search_known(self): host = Host.create('Réunion30', '30.30.30.30') self.assertTrue(host.href.startswith('http')) result = smc.actions.search.element_as_json('Réunion30') self.assertEqual(u'Réunion30', result.get('name'), result) for host in list(Search('host').objects.filter('Réunion30')): host.delete()
def test_export_element(self): # Test exporting a non-system element, should just return href result = Host.create('api-export-test', '2.3.4.5') self.assertTrue(result.href.startswith('http')) host = Host('api-export-test') self.assertIsInstance(host.export(), DownloadTask) with self.assertRaises(TaskRunFailed): host.export(filename='/foo').wait() host.delete()
def test_change_host_name_in_unicode(self): result = Host.create('Curaçao35', '12.12.12.12') self.assertTrue(result.href.startswith('http')) for host in list(Search('host').objects.filter('Curaçao35')): modified = host.modify_attribute(name='São Tomé Host35') self.assertTrue(modified.startswith('http')) for host in list(Search('host').objects.filter('São Tomé Host35')): host.delete()
def test_element_update_valid(self): host = Host.create(name='kali', address='1.1.1.1') self.assertEqual(host.address, '1.1.1.1') host.address = '34.34.34.34' host.comment = 'acomment' host.update() for attr in vars(host).keys(): self.assertNotEqual(attr, 'address') self.assertNotEqual(attr, 'comment') self.assertEqual(host.address, '34.34.34.34')
def test_element_update_invalid_attribute(self): host = Host.create(name='kali', address='1.1.1.1') host.address = '34.34.34.34' host.commento = 'testcomment' # Invalid attribute with self.assertRaises(UpdateElementFailed): host.update() # This should not remove instance attributes with self.assertRaises(AttributeError): host.commento self.assertEqual(host.address, '1.1.1.1') host.delete()
def test_host_using_callable_attribute(self): class Address: def __call__(self): return '123.123.123.123' host = Host.create('graciebear', address='1.1.1.1') self.assertEqual(host.address, '1.1.1.1') host.address = Address() host.update() self.assertEqual(host.address, '123.123.123.123') host.delete()
def test_FW_rule_with_outliers(self): policy = FirewallPolicy.create(name='myfoopolicy', template='Firewall Inspection Template') self.assertIsInstance(policy, FirewallPolicy) host = Host.create('asourcehost', '1.1.1.1') services = list(Search('tcp_service').objects.filter('HTTP')) policy.fw_ipv4_access_rules.create(name='myrule', sources=[host], services=services) # Rule with no sources policy.fw_ipv4_access_rules.create(name='myrule', sources=[host], services=services) policy.delete() Host('asourcehost').delete()
def test_get_resource_link_before_cache_called(self): Host.create(name='cachehost', address='1.1.1.1') h = Host('cachehost') self.assertFalse(vars(h).get('_cache')) h.data cache = vars(h).get('data') self.assertIsInstance(cache, SimpleElement) h.delete()
def test_static_src_nat(self): options = LogOptions() nat = StaticSourceNAT(options.data) self.assertIsNone(nat.translated_value) self.assertIsNone(nat.original_value) # Original value as an element host = Host('test', href='http://1.1.1.1') nat.original_value = host # as element href self.assertEqual(nat.original_value, 'http://1.1.1.1') # Translated address as element href nat.translated_value = host self.assertEqual(nat.translated_value, 'http://1.1.1.1') # Specify IP for translated address nat.translated_value = '2.2.2.2' self.assertEqual(nat.translated_value, '2.2.2.2') # Incorrect format, needs to be href or element nat.original_value = '10.10.10.10' # same as original self.assertEqual(nat.original_value, 'http://1.1.1.1') nat.original_value = 'http://2.2.2.2' self.assertEqual(nat.original_value, 'http://2.2.2.2') with patch('smc.base.model.Element.href', new_callable=PropertyMock) as foo: foo.side_effect = ElementNotFound self.assertEqual(nat.translated_value, '2.2.2.2') # Before nat.translated_value = Host('foo') # Invalid host self.assertEqual(nat.translated_value, '2.2.2.2') # After self.assertEqual(nat.original_value, 'http://2.2.2.2') # Before nat.original_value = Host('foo') # Invalid host self.assertEqual(nat.original_value, 'http://2.2.2.2') # After
def testGroup(self): # Member not href with self.assertRaises(CreateElementFailed): Group.create('foogroup', ['test'], 'comment') # Same as above with self.assertRaises(CreateElementFailed): Group.create('foogroup', ['172.18.1.80']) # Empty group group = Group.create('foogroup') self.assertTrue(group.href.startswith('http')) # Get context group = Group('foogroup') # Members Host.create('groupmember', '1.1.1.1') Network.create(name='anetwork', ipv4_network='1.1.1.0/24') self.assertIsNone(group.update_members(members=[Host('groupmember')])) # ETag in cache matches server after update etag = search.element_by_href_as_smcresult(group.href).etag self.assertEqual(group.etag, etag) # Get the members back and verify for member in group.obtain_members(): self.assertIn(member.name, ['groupmember']) # Check Host has a reference to group refs = Host('groupmember').referenced_by self.assertEqual(refs[0].name, 'foogroup') # Add second member and append group.update_members(members=[Network('anetwork')], append_lists=True) members = group.obtain_members() self.assertTrue(len(members) == 2) etag = search.element_by_href_as_smcresult(group.href).etag self.assertEqual(group.etag, etag) # Overwrite (test sending in as a href) group.update_members(members=[Host('groupmember').href], append_lists=False) members = group.obtain_members() self.assertTrue(len(members) == 1) self.assertEqual(members[0].name, 'groupmember') etag = search.element_by_href_as_smcresult(group.href).etag self.assertEqual(group.etag, etag) # Delete all members group.empty_members() self.assertTrue(len(group.obtain_members()) == 0) group.rename('group2') # Delete Host('groupmember').delete() group = Group('group2') group.delete()
def test_FW_validate_fw_rule_with_vpn(self): policy = FirewallPolicy.create(name='myfoopolicy', template='Firewall Inspection Template') self.assertIsInstance(policy, FirewallPolicy) vpn = VPNPolicy.create(name='foovpn') self.assertIsInstance(vpn, VPNPolicy) # Bad VPN Name with self.assertRaises(MissingRequiredInput): policy.fw_ipv4_access_rules.create(name='myvpnrule', sources='any', destinations='any', services='any', action='enforce_vpn', vpn_policy='foo') # Missing VPN Name with self.assertRaises(MissingRequiredInput): policy.fw_ipv4_access_rules.create(name='myvpnrule', sources='any', destinations='any', services='any', action='enforce_vpn') Host.create(name='mydest', address='1.1.1.1') dest = Host('mydest') policy.fw_ipv4_access_rules.create(name='myvpnrule', sources='any', destinations=[dest], services='any', action='enforce_vpn', vpn_policy='foovpn') for rule in policy.fw_ipv4_access_rules.all(): self.assertIsInstance(rule, IPv4Rule) self.assertEqual(rule.name, 'myvpnrule') rule.delete() # IPv6 Rules Host.create(name='myipv6', ipv6_address='2001:0db8:85a3:0000:0000:8a2e:0370:7334') policy.fw_ipv6_access_rules.create(name='myrule', sources=[Host('myipv6')], destinations='any', services='any', action='discard') policy.delete() Host('myipv6').delete() VPNPolicy('foovpn').delete()
def test_create_host_with_unicode(self): result = Host.create('Réunion33', '30.30.30.30') self.assertTrue(result.href.startswith('http')) for host in list(Search('host').objects.filter('Réunion33')): host.delete()
def test_str_and_unicode_conversion(self): element = Host('绝对路径加载/相对路径加载都') self.assertTrue(element.name == u'绝对路径加载/相对路径加载都')
def test_load_invalid_SMCElement(self): element = Host('Curaçao221234563234') self.assertRaises(ElementNotFound, lambda: element.data)
def test_modify_rules(self): policy = FirewallPolicy.create(name='myfoopolicy', template='Firewall Inspection Template') Host.create(name='foobar', address='1.1.1.1') host = Host('foobar') # No action, default to Allow, position set, but no rules so added # normally policy.fw_ipv4_access_rules.create(name='myrule', sources=[host], add_pos=10) for rule in policy.fw_ipv4_access_rules.all(): if rule.name == 'myrule': self.assertEqual(rule.action.action, 'allow') self.assertIsInstance(rule.authentication_options, AuthenticationOptions) self.assertIsInstance(rule.options, LogOptions) self.assertFalse(rule.is_disabled) self.assertEqual(rule.parent_policy.name, 'myfoopolicy') self.assertTrue(rule.destinations.is_none) self.assertTrue(rule.services.is_none) self.assertFalse(rule.services.all()) for source in rule.sources.all(): self.assertEqual(source.name, 'foobar') rule.disable() rule.comment = 'mycomment' rule.services.set_any() rule.save() self.assertEqual(rule.comment, 'mycomment') self.assertTrue(rule.is_disabled) rule.enable() rule.save() self.assertFalse(rule.is_disabled) self.assertTrue(rule.services.is_any) rule.delete() Host('foobar').delete() policy.fw_ipv4_access_rules.create(name='myrule', sources='any', destinations=[Host('badhost')], action=Action()) # Will be returned as type "Element" engine = Layer3Firewall.create(name='tmpfw', mgmt_ip='1.1.1.1', mgmt_network='1.1.1.0/24') Host.create(name='boo', address='12.12.12.12') for rule in policy.fw_ipv4_access_rules.all(): if rule.name == 'myrule': self.assertTrue(rule.destinations.is_none) self.assertTrue(rule.action.action == 'allow') self.assertTrue(rule.sources.is_any) # Host doesn't exist, destinations will remain none rule.destinations.add(Host('blah')) rule.save() self.assertTrue(rule.destinations.is_none) rule.destinations.add_many([Host('boo'), engine]) rule.save() dests = list(rule.destinations.all()) self.assertTrue(len(dests) == 2) for x in rule.destinations.all(): self.assertIsInstance(x, Element) self.assertIn(x.name, ['tmpfw', 'boo']) # Test Match Expression DomainName.create('lepages.net') Zone.create('MyExZone') match = MatchExpression.create(name='mymatch', network_element=Host('boo'), domain_name=DomainName('lepages.net'), zone=Zone('MyExZone')) policy.fw_ipv4_access_rules.create(name='matchex', sources=[match], destinations='any', services='any') rule = policy.search_rule('matchex')[0] self.assertTrue(len(rule.sources.all()[0].values()) == 3) for source in rule.sources.all(): for values in source.values(): self.assertIn(values.name, ['boo', 'lepages.net', 'MyExZone']) # Test after and before rule position options # Need rule tag for rule we are inserting around rule = policy.search_rule('matchex')[0] policy.fw_ipv4_access_rules.create(name='ruleafter', after=rule.tag) policy.fw_ipv4_access_rules.create(name='rulebefore', before=rule.tag) gen = policy.fw_ipv4_access_rules.all() for x in gen: if x.name == 'rulebefore': break matchex = next(gen) ruleafter = next(gen) self.assertEqual(matchex.name, 'matchex') self.assertEqual(ruleafter.name, 'ruleafter') # Add a jump rule with self.assertRaises(MissingRequiredInput): policy.fw_ipv4_access_rules.create( name='jumprule', action='jump', sub_policy=FirewallSubPolicy('blahblah')) FirewallSubPolicy.create('subfoo') policy.fw_ipv4_access_rules.create( name='jumprule', action='jump', sub_policy=FirewallSubPolicy('subfoo')) rule = policy.search_rule('jumprule')[0] self.assertEqual(rule.action.action, 'jump') self.assertEqual(rule.action.sub_policy.href, FirewallSubPolicy('subfoo').href) policy.delete() DomainName('lepages.net').delete() Zone('MyExZone').delete() Host('boo').delete() time.sleep(3) engine.delete()
def test_NATRules(self): policy = FirewallPolicy.create(name='apitestpolicy', template='Firewall Inspection Template') Host.create('nathost', address='1.1.1.1') Host.create('sourcenat', address='2.2.2.2') engine = Layer3Firewall.create(name='natfw', mgmt_ip='1.1.1.1', mgmt_network='1.1.1.0/24') # Source NAT using port restrictions policy.fw_ipv4_nat_rules.create(name='dynsrcnat', sources='any', destinations=[Host('nathost')], services='any', dynamic_src_nat='2.2.2.2', dynamic_src_nat_ports=(30000, 35000)) # Dest NAT by IP policy.fw_ipv4_nat_rules.create(name='dstnat', sources='any', destinations=[Host('nathost')], services='any', static_dst_nat='3.3.3.3') # Destination field cannot be any or none with dest NAT with self.assertRaises(InvalidRuleValue): policy.fw_ipv4_nat_rules.create(name='foo', sources='any', destinations='any', services='any', static_dst_nat='3.3.3.3') # Source and Dest NAT policy.fw_ipv4_nat_rules.create(name='dstandsrcnat', sources='any', destinations=[Host('sourcenat')], services='any', dynamic_src_nat='5.5.5.5', static_dst_nat='3.3.3.3', static_dst_nat_ports=(22, 2222)) policy.fw_ipv4_nat_rules.create(name='nonatrule', sources='any', destinations='any', services='any') # Static src NAT if is_min_required_smc_version('6.1.2'): policy.fw_ipv4_nat_rules.create(name='static_src_nat', sources=[Host('sourcenat')], destinations='any', static_src_nat='1.1.1.1') else: with self.assertRaises(CreateRuleFailed): policy.fw_ipv4_nat_rules.create(name='static_src_nat', sources=[Host('sourcenat')], destinations='any', static_src_nat='1.1.1.1') # Invalid rule with self.assertRaises(CreateRuleFailed): policy.fw_ipv4_nat_rules.create(name='foo', sources='any', destinations=['any'], services='any', static_dst_nat='1.1.1.1') for rule in policy.fw_ipv4_nat_rules.all(): self.assertIsInstance(rule, IPv4NATRule) if rule.name == 'dynsrcnat': self.assertEqual(rule.dynamic_src_nat.translated_value, '2.2.2.2') # Not valid for dyn src nat self.assertIsNone(rule.dynamic_src_nat.original_value) self.assertEqual(rule.dynamic_src_nat.translated_ports, (30000, 35000)) elif rule.name == 'dstnat': if is_min_required_smc_version('6.1.2'): self.assertEqual(rule.static_dst_nat.translated_value, '3.3.3.3') self.assertEqual(rule.static_dst_nat.original_value, '1.1.1.1') else: # Version 6.1.1 self.assertEqual(rule.static_dst_nat.translated_value, '3.3.3.3') self.assertEqual(rule.static_dst_nat.original_value, Host('nathost').href) elif rule.name == 'dstandsrcnat': self.assertEqual(rule.dynamic_src_nat.translated_ports, (1024, 65535)) self.assertEqual(rule.dynamic_src_nat.translated_value, '5.5.5.5') self.assertEqual(rule.static_dst_nat.translated_value, '3.3.3.3') source_port, dest_port = rule.static_dst_nat.translated_ports self.assertEqual(source_port, 22) self.assertEqual(dest_port, 2222) elif rule.name == 'nonatrule': self.assertFalse(rule.static_src_nat.has_nat) self.assertFalse(rule.dynamic_src_nat.has_nat) self.assertFalse(rule.static_dst_nat.has_nat) # Test unsed on attribute self.assertIsNone(rule.used_on) # Catch the ElementNotFound, no change rule.used_on = Host('nonexistanthost') self.assertIsNone(rule.used_on) rule.used_on = engine self.assertEqual(rule.used_on.name, 'natfw') # IPv6 NAT Host.create(name='myipv6', ipv6_address='2001:0db8:85a3:0000:0000:8a2e:0370:7334') policy.fw_ipv6_nat_rules.create(name='mynat', sources=[Host('myipv6')], destinations='any', services='any', dynamic_src_nat='2001:db8::2:1') rule_matches = policy.search_rule('nonatrule') self.assertIsInstance(rule_matches[0], IPv4NATRule) no_rule_match = policy.search_rule('blahblahfoo') self.assertTrue(len(no_rule_match) == 0) engine.delete() policy.delete() Host('nathost').delete() Host('sourcenat').delete() Host('myipv6').delete()
""" FirewallPolicy.create(name='smcpython', template='Firewall Inspection Template') """ Get an existing policy """ policy = FirewallPolicy('smcpython') """ Open the policy for editing, create a rule, and save the policy """ myservices = describe_tcp_service(name=['HTTP', 'HTTPS']) myservices = [service.href for service in myservices] host = Host.create(name='amazon-linux-host', address='192.168.1.5') mysources = [host.href] mydestinations = 'any' policy.fw_ipv4_access_rules.create(name='mynewrule', sources=mysources, destinations=mydestinations, services=myservices, action='permit') """ View a metadata version of each configured rule """ for rule in policy.fw_ipv4_access_rules.all(): print rule.name
def test_search_element_references_as_smcresult(self): host = Host('test-common-api-user').href result = smc.actions.search.element_references_as_smcresult(host) self.assertIsInstance(result, SMCResult)
# [smc] # smc_address=192.168.100.7 # smc_apikey=xxxxxxxxxxx # smc_port=8082 # smc_ssl=False # verify_ssl=False session.login() policy = FirewallPolicy.get('mynatpolicy1', raise_exc=False) if policy: policy.delete() policy = FirewallPolicy.create(name='mynatpolicy1', template='Firewall Inspection Template') kali_host = Host.get_or_create(name = 'kali', address='1.1.1.1') host3 = Host.get_or_create(name='host-3.3.3.3', address='3.3.3.3') # Example of creating a dynamic source NAT for host 'kali': policy.fw_ipv4_nat_rules.create(name='mynatrule-srcdyn', sources=[Host('kali')], destinations='any', services='any', dynamic_src_nat='1.1.1.1', dynamic_src_nat_ports=(1024,65535)) # Example of creating a static source NAT for host 'kali': policy.fw_ipv4_nat_rules.create(name='mynatrule-srcstat', sources=[kali_host],