def create_nat_rule(**kwargs): nat_rule = NatRule(name=kwargs['rule_name'], description=kwargs['description'], fromzone=kwargs['source_zone'], source=kwargs['source_ip'], tozone=kwargs['destination_zone'], destination=kwargs['destination_ip'], service=kwargs['service'], to_interface=kwargs['to_interface'], nat_type=kwargs['nat_type']) # Source translation: Static IP if kwargs['snat_type'] in ['static-ip'] and kwargs['snat_static_address']: nat_rule.source_translation_type = kwargs['snat_type'] nat_rule.source_translation_static_translated_address = kwargs[ 'snat_static_address'] # Bi-directional flag set? if kwargs['snat_bidirectional']: nat_rule.source_translation_static_bi_directional = kwargs[ 'snat_bidirectional'] # Source translation: Dynamic IP and port elif kwargs['snat_type'] in ['dynamic-ip-and-port']: nat_rule.source_translation_type = kwargs['snat_type'] nat_rule.source_translation_address_type = kwargs['snat_address_type'] # Interface address? if kwargs['snat_interface']: nat_rule.source_translation_interface = kwargs['snat_interface'] # Interface IP? if kwargs['snat_interface_address']: nat_rule.source_translation_ip_address = kwargs[ 'snat_interface_address'] else: nat_rule.source_translation_translated_addresses = kwargs[ 'snat_dynamic_address'] # Source translation: Dynamic IP elif kwargs['snat_type'] in ['dynamic-ip']: if kwargs['snat_dynamic_address']: nat_rule.source_translation_type = kwargs['snat_type'] nat_rule.source_translation_translated_addresses = kwargs[ 'snat_dynamic_address'] else: return False # Destination translation if kwargs['dnat_address']: nat_rule.destination_translated_address = kwargs['dnat_address'] if kwargs['dnat_port']: nat_rule.destination_translated_port = kwargs['dnat_port'] # Any tags? if 'tag_name' in kwargs: nat_rule.tag = kwargs['tag_name'] return nat_rule
def main(): argument_spec = dict( ip_address=dict(required=True), username=dict(default='admin'), password=dict(required=True, no_log=True), api_key=dict(no_log=True), operation=dict(choices=['add', 'update', 'delete', 'find', 'disable']), state=dict(default='present', choices=['present', 'absent']), rule_name=dict(required=True), description=dict(), nat_type=dict(default='ipv4', choices=['ipv4', 'nat64', 'nptv6']), tag_name=dict(), source_zone=dict(type='list'), source_ip=dict(type='list', default=['any']), destination_zone=dict(), destination_ip=dict(type='list', default=['any']), service=dict(default='any'), to_interface=dict(default='any'), snat_type=dict( choices=['static-ip', 'dynamic-ip-and-port', 'dynamic-ip']), snat_address_type=dict( choices=['interface-address', 'translated-address'], default='interface-address'), snat_static_address=dict(), snat_dynamic_address=dict(type='list'), snat_interface=dict(), snat_interface_address=dict(), snat_bidirectional=dict(type='bool', default=False), dnat_address=dict(), dnat_port=dict(), devicegroup=dict(default='shared'), rulebase=dict(default='pre-rulebase', choices=['pre-rulebase', 'post-rulebase']), vsys=dict(default='vsys1'), location=dict(default='bottom', choices=['top', 'bottom', 'before', 'after']), existing_rule=dict(), commit=dict(type='bool', default=True)) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['api_key', 'password']]) if not HAS_LIB: module.fail_json(msg='Missing required libraries.') elif not hasattr(NatRule, 'move'): module.fail_json(msg='Python library pandevice needs to be updated.') # Get firewall / Panorama auth. auth = [ module.params[x] for x in ('ip_address', 'username', 'password', 'api_key') ] # Get object params. rule_name = module.params['rule_name'] description = module.params['description'] tag_name = module.params['tag_name'] source_zone = module.params['source_zone'] source_ip = module.params['source_ip'] destination_zone = module.params['destination_zone'] destination_ip = module.params['destination_ip'] service = module.params['service'] to_interface = module.params['to_interface'] nat_type = module.params['nat_type'] snat_type = module.params['snat_type'] snat_address_type = module.params['snat_address_type'] snat_static_address = module.params['snat_static_address'] snat_dynamic_address = module.params['snat_dynamic_address'] snat_interface = module.params['snat_interface'] snat_interface_address = module.params['snat_interface_address'] snat_bidirectional = module.params['snat_bidirectional'] dnat_address = module.params['dnat_address'] dnat_port = module.params['dnat_port'] # Get other info. operation = module.params['operation'] state = module.params['state'] devicegroup = module.params['devicegroup'] vsys = module.params['vsys'] commit = module.params['commit'] location = module.params['location'] existing_rule = module.params['existing_rule'] # Sanity check the location / existing_rule params. if location in ('before', 'after') and not existing_rule: module.fail_json( msg= "'existing_rule' must be specified if location is 'before' or 'after'." ) # Create the device with the appropriate pandevice type con = PanDevice.create_from_device(*auth) # Set vsys if firewall, device group if Panorama, and set the rulebase. parent = con if hasattr(con, 'refresh_devices'): # Panorama if devicegroup not in (None, 'shared'): dev_group = get_devicegroup(con, devicegroup) if not dev_group: module.fail_json( msg= '\'%s\' device group not found in Panorama. Is the name correct?' % devicegroup) parent = dev_group if module.params['rulebase'] in (None, 'pre-rulebase'): rulebase = PreRulebase() parent.add(rulebase) parent = rulebase elif module.params['rulebase'] == 'post-rulebase': rulebase = PostRulebase() parent.add(rulebase) parent = rulebase else: # Firewall parent.vsys = vsys rulebase = Rulebase() parent.add(rulebase) parent = rulebase # Get the current NAT rules. try: rules = NatRule.refreshall(parent) except PanDeviceError as e: module.fail_json(msg='Failed NAT refreshall: {0}'.format(e)) # Create the desired rule. new_rule = create_nat_rule(rule_name=rule_name, description=description, tag_name=tag_name, source_zone=source_zone, destination_zone=destination_zone, source_ip=source_ip, destination_ip=destination_ip, service=service, to_interface=to_interface, nat_type=nat_type, snat_type=snat_type, snat_address_type=snat_address_type, snat_static_address=snat_static_address, snat_dynamic_address=snat_dynamic_address, snat_interface=snat_interface, snat_interface_address=snat_interface_address, snat_bidirectional=snat_bidirectional, dnat_address=dnat_address, dnat_port=dnat_port) if not new_rule: module.fail_json(msg='Incorrect NAT rule params specified; quitting') parent.add(new_rule) # Perform the desired operation. changed = False do_move = False if state == 'present': match = find_rule(rules, new_rule) if match is not None: if not match.equal(new_rule): try: new_rule.apply() except PanDeviceError as e: module.fail_json( msg='Failed "present" apply: {0}'.format(e)) else: changed = True do_move = True else: try: new_rule.create() except PanDeviceError as e: module.fail_json(msg='Failed "present" create: {0}'.format(e)) else: changed = True do_move = True elif state == 'absent': match = find_rule(rules, new_rule) if match is not None: try: new_rule.delete() except PanDeviceError as e: module.fail_json(msg='Failed "absent" delete: {0}'.format(e)) else: changed = True elif operation == "find": # Search for the rule match = find_rule(rules, new_rule) # If found, format and return the result if match: match_dict = xmltodict.parse(match.element_str()) module.exit_json(stdout_lines=json.dumps(match_dict, indent=2), msg='Rule matched') else: module.fail_json( msg='Rule \'%s\' not found. Is the name correct?' % rule_name) elif operation == "delete": # Search for the object match = find_rule(rules, new_rule) if match is None: module.fail_json( msg='Rule \'%s\' not found. Is the name correct?' % rule_name) try: new_rule.delete() except PanDeviceError as e: module.fail_json(msg='Failed "delete" delete: {0}'.format(e)) else: changed = True elif operation == "add": # Look for required parameters if not source_zone or not destination_zone or not nat_type: module.fail_json( msg= 'Missing parameter. Required: source_zone, destination_zone, nat_type' ) # Search for the rule. Fail if found. match = find_rule(rules, new_rule) if match: module.fail_json( msg= 'Rule \'%s\' already exists. Use operation: \'update\' to change it.' % rule_name) try: new_rule.create() except PanDeviceError as e: module.fail_json(msg='Failed "add" create: {0}'.format(e)) else: changed = True do_move = True elif operation == 'update': # Search for the rule. Update if found. match = find_rule(rulebase, rule_name) if not match: module.fail_json( msg= 'Rule \'%s\' does not exist. Use operation: \'add\' to add it.' % rule_name) try: new_rule.apply() except PanDeviceError as e: module.fail_json(msg='Failed "update" apply: {0}'.format(e)) else: changed = True do_move = True elif operation == 'disable': # Search for the rule, disable if found. match = find_rule(rules, new_rule) if not match: module.fail_json(msg='Rule \'%s\' does not exist.' % rule_name) if not match.disabled: match.disabled = True try: match.update('disabled') except PanDeviceError as e: module.fail_json(msg='Failed "disabled": {0}'.format(e)) else: changed = True # Optional move. if do_move: try: new_rule.move(location, existing_rule) except PanDeviceError as e: if '{0}'.format(e) not in ACCEPTABLE_MOVE_ERRORS: module.fail_json(msg='Failed move: {0}'.format(e)) else: changed = True # Optional commit. if changed and commit: try: con.commit(sync=True) except PanDeviceError as e: module.fail_json(msg='Failed commit: {0}'.format(e)) module.exit_json(changed=changed, msg='Done')
def main(): helper = get_connection( vsys=True, device_group=True, rulebase=True, error_on_shared=True, argument_spec=dict( rule_name=dict(required=True), description=dict(), nat_type=dict(default='ipv4', choices=['ipv4', 'nat64', 'nptv6']), source_zone=dict(type='list'), source_ip=dict(type='list', default=['any']), destination_zone=dict(), destination_ip=dict(type='list', default=['any']), to_interface=dict(default='any'), service=dict(default='any'), snat_type=dict( choices=['static-ip', 'dynamic-ip-and-port', 'dynamic-ip']), snat_address_type=dict( choices=['interface-address', 'translated-address'], default='interface-address'), snat_static_address=dict(), snat_dynamic_address=dict(type='list'), snat_interface=dict(), snat_interface_address=dict(), snat_bidirectional=dict(type='bool'), dnat_address=dict(), dnat_port=dict(), tag=dict(type='list'), state=dict(default='present', choices=['present', 'absent', 'enable', 'disable']), location=dict(choices=['top', 'bottom', 'before', 'after']), existing_rule=dict(), commit=dict(type='bool', default=True), # TODO(gfreeman) - remove later. tag_name=dict(), devicegroup=dict(), operation=dict(), ), ) module = AnsibleModule( argument_spec=helper.argument_spec, supports_check_mode=True, required_one_of=helper.required_one_of, ) # TODO(gfreeman) - remove later. if module.params['operation'] is not None: module.fail_json(msg='Param "operation" is removed; use "state"') if module.params['devicegroup'] is not None: module.deprecate( 'Param "devicegroup" is deprecated; use "device_group"', '2.12') module.params['device_group'] = module.params['devicegroup'] if module.params['tag_name'] is not None: tag_val = module.params['tag_name'] module.deprecate('Param "tag_name" is deprecated; use "tag"', '2.12') if module.params['tag']: module.fail_json( msg='Both "tag" and "tag_name" specified, use only one') else: tag_val = module.params['tag'] parent = helper.get_pandevice_parent(module) # Get object params. rule_name = module.params['rule_name'] description = module.params['description'] source_zone = module.params['source_zone'] source_ip = module.params['source_ip'] destination_zone = module.params['destination_zone'] destination_ip = module.params['destination_ip'] service = module.params['service'] to_interface = module.params['to_interface'] nat_type = module.params['nat_type'] snat_type = module.params['snat_type'] snat_address_type = module.params['snat_address_type'] snat_static_address = module.params['snat_static_address'] snat_dynamic_address = module.params['snat_dynamic_address'] snat_interface = module.params['snat_interface'] snat_interface_address = module.params['snat_interface_address'] snat_bidirectional = module.params['snat_bidirectional'] dnat_address = module.params['dnat_address'] dnat_port = module.params['dnat_port'] # Get other info. state = module.params['state'] location = module.params['location'] existing_rule = module.params['existing_rule'] # Sanity check the location / existing_rule params. if location in ('before', 'after') and not existing_rule: module.fail_json( msg= "'existing_rule' must be specified if location is 'before' or 'after'." ) # Get the current NAT rules. try: rules = NatRule.refreshall(parent) except PanDeviceError as e: module.fail_json(msg='Failed NAT refreshall: {0}'.format(e)) # Create the desired rule. new_rule = create_nat_rule(rule_name=rule_name, description=description, tag_val=tag_val, source_zone=source_zone, destination_zone=destination_zone, source_ip=source_ip, destination_ip=destination_ip, service=service, to_interface=to_interface, nat_type=nat_type, snat_type=snat_type, snat_address_type=snat_address_type, snat_static_address=snat_static_address, snat_dynamic_address=snat_dynamic_address, snat_interface=snat_interface, snat_interface_address=snat_interface_address, snat_bidirectional=snat_bidirectional, dnat_address=dnat_address, dnat_port=dnat_port) if not new_rule: module.fail_json(msg='Incorrect NAT rule params specified; quitting') # Perform the desired operation. changed = False if state in ('enable', 'disable'): for rule in rules: if rule.name == new_rule.name: break else: module.fail_json( msg='Rule "{0}" not present'.format(new_rule.name)) if state == 'enable' and rule.disabled: changed = True elif state == 'disable' and not rule.disabled: changed = True if changed: rule.disabled = not rule.disabled if not module.check_mode: try: rule.update('disabled') except PanDeviceError as e: module.fail_json(msg='Failed enable: {0}'.format(e)) else: parent.add(new_rule) changed = helper.apply_state(new_rule, rules, module) if state == 'present': changed |= helper.apply_position(new_rule, location, existing_rule, module) if changed and module.params['commit']: helper.commit(module) module.exit_json(changed=changed, msg='Done')
def main(): helper = get_connection( vsys=True, device_group=True, rulebase=True, with_classic_provider_spec=True, error_on_shared=True, required_one_of=[ ['listing', 'rule_name', 'rule_regex', 'uuid'], ], argument_spec=dict( listing=dict(type='bool'), rule_name=dict(), rule_regex=dict(), uuid=dict(), ), ) module = AnsibleModule( argument_spec=helper.argument_spec, supports_check_mode=False, required_one_of=helper.required_one_of, ) parent = helper.get_pandevice_parent(module) renames = ( ('name', 'rule_name'), ('fromzone', 'source_zone'), ('tozone', 'destination_zone'), ('source', 'source_ip'), ('destination', 'destination_ip'), ('source_translation_type', 'snat_type'), ('source_translation_static_translated_address', 'snat_static_address'), ('source_translation_static_bi_directional', 'snat_bidirectional'), ('source_translation_address_type', 'snat_address_type'), ('source_translation_interface', 'snat_interface'), ('source_translation_ip_address', 'snat_interface_address'), ('source_translation_translated_addresses', 'snat_dynamic_address'), ('destination_translated_address', 'dnat_address'), ('destination_translated_port', 'dnat_port'), ('tag', 'tag_val'), ) if module.params['rule_name']: obj = NatRule(module.params['rule_name']) parent.add(obj) try: obj.refresh() except PanDeviceError as e: module.fail_json(msg='Failed refresh: {0}'.format(e)) module.exit_json( changed=False, object=helper.to_module_dict(obj, renames), ) try: listing = NatRule.refreshall(parent) except PanDeviceError as e: module.fail_json(msg='Failed refreshall: {0}'.format(e)) if module.params['uuid']: for x in listing: if x.uuid == module.params['uuid']: module.exit_json( changed=False, object=helper.to_module_dict(x, renames), ) module.fail_json( msg='No rule with uuid "{0}"'.format(module.params['uuid'])) ans = [] matcher = None if module.params['rule_regex']: try: matcher = re.compile(module.params['rule_regex']) except Exception as e: module.fail_json(msg='Invalid regex: {0}'.format(e)) ans = [ helper.to_module_dict(x, renames) for x in listing if module.params['listing'] or matcher.search(x.uid) is not None ] module.exit_json(changed=False, listing=ans)
def main(): helper = get_connection( vsys=True, rulebase=True, with_classic_provider_spec=True, panorama_error='Panorama is not supported', argument_spec=dict( rule_type=dict(default='security', choices=['security', 'nat']), source_zone=dict(), source_ip=dict(required=True), source_port=dict(type='int'), source_user=dict(), to_interface=dict(), destination_zone=dict(), destination_ip=dict(required=True), destination_port=dict(required=True, type='int'), application=dict(), protocol=dict(required=True, type='int'), category=dict(), # TODO(gfreeman) - Remove this in the next role release. vsys_id=dict(), ), ) module = AnsibleModule( argument_spec=helper.argument_spec, supports_check_mode=False, required_one_of=helper.required_one_of, ) # TODO(gfreeman) - Remove this in the next role release. if not HAS_LIB: module.fail_json(msg='Missing xmltodict library') if module.params['vsys_id'] is not None: module.fail_json(msg='Param "vsys_id" is removed; use vsys') parent = helper.get_pandevice_parent(module) params = ( ('application', 'application', [ 'security', ]), ('category', 'category', [ 'security', ]), ('destination_ip', 'destination', ['security', 'nat']), ('destination_port', 'destination-port', ['security', 'nat']), ('source_zone', 'from', ['security', 'nat']), ('protocol', 'protocol', ['security', 'nat']), ('source_ip', 'source', ['security', 'nat']), ('source_user', 'source-user', [ 'security', ]), ('destination_zone', 'to', ['security', 'nat']), ('to_interface', 'to-interface', [ 'nat', ]), ) cmd = [] rtype = module.params['rule_type'] if rtype == 'security': cmd.append('test security-policy-match') listing = SecurityRule.refreshall(parent) else: cmd.append('test nat-policy-match') listing = NatRule.refreshall(parent) for ansible_param, cmd_param, rule_types in params: if rtype not in rule_types or module.params[ansible_param] is None: continue cmd.append('{0} "{1}"'.format(cmd_param, module.params[ansible_param])) # Submit the op command with the appropriate test string test_string = ' '.join(cmd) try: response = helper.device.op(cmd=test_string, vsys=parent.vsys) except PanDeviceError as e: module.fail_json(msg='Failed "{0}": {1}'.format(test_string, e)) elm = response.find('./result/rules/entry') if elm is not None: try: rule_name = elm.attrib['name'] except KeyError: rule_name = elm.text else: module.exit_json(msg='No matching {0} rule.'.format(rtype)) for x in listing: if x.name != rule_name: continue module.deprecate( 'The "stdout_lines" output is deprecated; use "rule" instead', '2.12') module.exit_json( stdout_lines=json.dumps(xmltodict.parse(x.element_str()), indent=2), msg='Rule matched', rule=x.about(), ) module.fail_json( msg='Matched "{0}" with "{1}", but wasn\'t in rulebase'.format( rule_name, test_string))
def main(): helper = get_connection( vsys=True, with_classic_provider_spec=True, panorama_error='Panorama is not supported', argument_spec=dict( rule_type=dict(default='security', choices=['security', 'nat']), source_zone=dict(), source_ip=dict(required=True), source_port=dict(type='int'), source_user=dict(), to_interface=dict(), destination_zone=dict(), destination_ip=dict(required=True), destination_port=dict(required=True, type='int'), application=dict(), protocol=dict(required=True, type='int'), category=dict(), # TODO(gfreeman) - Remove this in the next role release. vsys_id=dict(), rulebase=dict(), ), ) module = AnsibleModule( argument_spec=helper.argument_spec, supports_check_mode=False, required_one_of=helper.required_one_of, ) # TODO(gfreeman) - Remove this in the next role release. if not HAS_LIB: module.fail_json(msg='Missing xmltodict library') if module.params['vsys_id'] is not None: module.fail_json(msg='Param "vsys_id" is removed; use vsys') if module.params['rulebase'] is not None: module.deprecate( 'Param "rulebase" is deprecated and may safely be removed from your playbook', '2.12', ) parent = helper.get_pandevice_parent(module) params = ( ('application', 'application', [ 'security', ]), ('category', 'category', [ 'security', ]), ('destination_ip', 'destination', ['security', 'nat']), ('destination_port', 'destination-port', ['security', 'nat']), ('source_zone', 'from', ['security', 'nat']), ('protocol', 'protocol', ['security', 'nat']), ('source_ip', 'source', ['security', 'nat']), ('source_user', 'source-user', [ 'security', ]), ('destination_zone', 'to', ['security', 'nat']), ('to_interface', 'to-interface', [ 'nat', ]), ) cmd = [] rtype = module.params['rule_type'] vsys = module.params['vsys'] # This module used to refreshall on either the security rules or the NAT # rules, however if the rule matched came from Panorama, then this module # failed. To account for this, instead directly query the 3 path locations # where the rule could exist, and return that instead. When pandevice # supports querying the firewall for the pushed down Panorama config, change # this back to using normal pandevice objects. rule_locations = ( ( 'panorama-pre-rulebase', "/config/panorama/vsys/entry[@name='{0}']/pre-rulebase", ), ( 'firewall-rulebase', "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='{0}']/rulebase", ), ( 'panorama-post-rulebase', "/config/panorama/vsys/entry[@name='{0}']/post-rulebase", ), ) suffix = "/{0}/rules/entry[@name='{1}']" if rtype == 'security': cmd.append('test security-policy-match') obj = SecurityRule() else: cmd.append('test nat-policy-match') obj = NatRule() parent.add(obj) for ansible_param, cmd_param, rule_types in params: if rtype not in rule_types or module.params[ansible_param] is None: continue cmd.append('{0} "{1}"'.format(cmd_param, module.params[ansible_param])) # Submit the op command with the appropriate test string test_string = ' '.join(cmd) try: response = helper.device.op(cmd=test_string, vsys=parent.vsys) except PanDeviceError as e: module.fail_json(msg='Failed "{0}": {1}'.format(test_string, e)) elm = response.find('./result/rules/entry') elm2 = response.find('./result/msg/line') if elm is not None: try: rule_name = elm.attrib['name'] except KeyError: rule_name = elm.text elif elm2 is not None: ''' From 8.1 (matching Panorama rule): NOTE: Ending newlines have been truncated to appease codestyle rules. <response cmd="status" status="success"><result><msg><line><![CDATA["Rule Name; index: 1" { from L3-trust; source [ 10.0.0.1 1.1.1.1 ]; source-region none; to L3-untrust; destination [ 8.8.8.8 ]; destination-region none; user any; category any; application/service [0:any/tcp/any/21 1:any/tcp/any/22 ]; action allow; icmp-unreachable: no terminal yes; } ]]></line></msg></result></response> ''' rule_name = elm2.text.split(';')[0].split('"')[1].strip() else: msg = 'No matching {0} rule; resp = {1}'.format( rtype, ET.tostring(response, enoding='utf-8'), ) module.exit_json(msg=msg) ''' Example response (newlines after newlines to appease pycodestyle line length limitations): <response cmd="status" status="success"><result><rules>\n \t<entry>deny all and log; index: 3</entry>\n </rules>\n </result></response> ''' tokens = rule_name.split(';') if len(tokens) == 2 and tokens[1].startswith(' index: '): rule_name = tokens[0] fw = obj.nearest_pandevice() for rulebase, prefix in rule_locations: xpath = prefix.format(vsys) + suffix.format(rtype, rule_name) ans = fw.xapi.get(xpath) if ans is None: continue rules = obj.refreshall_from_xml(ans.find('./result')) if rules: x = rules[0] module.deprecate( 'The "stdout_lines" output is deprecated; use "rule" instead', '2.12', ) module.exit_json( stdout_lines=json.dumps(xmltodict.parse(x.element_str()), indent=2), msg='Rule matched', rule=x.about(), rulebase=rulebase, ) module.fail_json( msg='Matched "{0}" with "{1}", but wasn\'t in any rulebase'.format( rule_name, test_string))
def configure_policy(device): web_srv = AddressObject(name='web-srv', value='192.168.45.5') db_srv = AddressObject(name='db-srv', value='192.168.35.5') device.add(web_srv) device.add(db_srv) web_srv.create() db_srv.create() service_tcp_221 = ServiceObject(name='service-tcp-221', protocol='tcp', destination_port='221') service_tcp_222 = ServiceObject(name='service-tcp-222', protocol='tcp', destination_port='222') device.add(service_tcp_221) device.add(service_tcp_222) service_tcp_221.create() service_tcp_222.create() rulebase = Rulebase() device.add(rulebase) allow_ping = SecurityRule(name='Allow ping', fromzone=['any'], source=['any'], tozone=['any'], destination=['any'], application=['ping'], service=['application-default'], action='allow') ssh_inbound = SecurityRule(name='SSH inbound', fromzone=['untrust'], source=['any'], tozone=['web', 'db'], destination=['any'], application=['ping', 'ssh'], service=['service-tcp-221', 'service-tcp-222'], action='allow') web_inbound = SecurityRule(name='Web inbound', fromzone=['untrust'], source=['any'], tozone=['web'], destination=['any'], application=['any'], service=['service-http'], action='allow') web_to_db = SecurityRule(name='Web to DB', fromzone=['any'], source=['web-srv'], tozone=['any'], destination=['db-srv'], application=['mysql'], service=['application-default'], action='allow') allow_outbound = SecurityRule(name='Allow outbound', fromzone=['web', 'db'], source=['any'], tozone=['untrust'], destination=['any'], application=['any'], service=['application-default'], action='allow') rulebase.add(allow_ping) rulebase.add(ssh_inbound) rulebase.add(web_inbound) rulebase.add(web_to_db) rulebase.add(allow_outbound) allow_ping.create() ssh_inbound.create() web_inbound.create() web_to_db.create() allow_outbound.create() web_ssh = NatRule(name='Web SSH', fromzone=['untrust'], source=['any'], tozone=['untrust'], destination=['192.168.55.20'], service='service-tcp-221', source_translation_type='dynamic-ip-and-port', source_translation_address_type='interface-address', source_translation_interface='ethernet1/2', destination_translated_address='web-srv', destination_translated_port='22') db_ssh = NatRule(name='DB SSH', fromzone=['untrust'], source=['any'], tozone=['untrust'], destination=['192.168.55.20'], service='service-tcp-222', source_translation_type='dynamic-ip-and-port', source_translation_address_type='interface-address', source_translation_interface='ethernet1/3', destination_translated_address='db-srv', destination_translated_port='22') wordpress_nat = NatRule( name='WordPress NAT', fromzone=['untrust'], source=['any'], tozone=['untrust'], destination=['192.168.55.20'], service='service-http', source_translation_type='dynamic-ip-and-port', source_translation_address_type='interface-address', source_translation_interface='ethernet1/2', destination_translated_address='web-srv') outgoing_traffic = NatRule( name='Outgoing traffic', fromzone=['web', 'db'], source=['any'], tozone=['untrust'], destination=['any'], source_translation_type='dynamic-ip-and-port', source_translation_address_type='interface-address', source_translation_interface='ethernet1/1', ) rulebase.add(web_ssh) rulebase.add(db_ssh) rulebase.add(wordpress_nat) rulebase.add(outgoing_traffic) web_ssh.create() db_ssh.create() wordpress_nat.create() outgoing_traffic.create()