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(): 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 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 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()