Example #1
0
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))
Example #3
0
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)
Example #4
0
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()