コード例 #1
0
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',
            version='3.0.0',
            collection_name='paloaltonetworks.panos')

    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, encoding='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',
                version='3.0.0',
                collection_name='paloaltonetworks.panos',
            )
            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))
コード例 #2
0
def main():
    helper = get_connection(
        with_classic_provider_spec=True,
        vsys=True,
        device_group=True,
        rulebase=True,
        error_on_firewall_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', elements='str'),
            source_ip=dict(type='list', elements='str', default=['any']),
            destination_zone=dict(type='str'),
            destination_ip=dict(type='list', elements='str', 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', elements='str'),
            snat_interface=dict(),
            snat_interface_address=dict(),
            snat_bidirectional=dict(type='bool'),
            dnat_address=dict(),
            dnat_port=dict(),
            tag=dict(type='list', elements='str'),
            state=dict(default='present', choices=['present', 'absent', 'enable', 'disable']),
            location=dict(choices=['top', 'bottom', 'before', 'after']),
            existing_rule=dict(),
            commit=dict(type='bool', default=False),

            # 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"',
            version='3.0.0', collection_name='paloaltonetworks.panos'
        )
        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"',
            version='3.0.0', collection_name='paloaltonetworks.panos'
        )
        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
    diff = None
    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:
            diff = dict(
                before=eltostr(rule)
            )
            rule.disabled = not rule.disabled
            diff['after'] = eltostr(rule)
            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, diff = 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, diff=diff, msg='Done')
コード例 #3
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_val' in kwargs:
        nat_rule.tag = kwargs['tag_val']

    return nat_rule
コード例 #4
0
def main():
    helper = get_connection(
        vsys=True,
        device_group=True,
        rulebase=True,
        with_classic_provider_spec=True,
        error_on_firewall_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)
コード例 #5
0
def main():
    helper = get_connection(
        with_classic_provider_spec=True,
        vsys=True,
        device_group=True,
        rulebase=True,
        error_on_firewall_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", elements="str"),
            source_ip=dict(type="list", elements="str", default=["any"]),
            destination_zone=dict(type="str"),
            destination_ip=dict(type="list", elements="str", 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", elements="str"),
            snat_interface=dict(),
            snat_interface_address=dict(),
            snat_bidirectional=dict(type="bool"),
            dnat_address=dict(),
            dnat_port=dict(),
            tag=dict(type="list", elements="str"),
            state=dict(default="present",
                       choices=["present", "absent", "enable", "disable"]),
            location=dict(choices=["top", "bottom", "before", "after"]),
            existing_rule=dict(),
            target=dict(type="list", elements="str"),
            negate_target=dict(type="bool"),
            commit=dict(type="bool", default=False),
            # 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"',
            version="3.0.0",
            collection_name="paloaltonetworks.panos",
        )
        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"',
            version="3.0.0",
            collection_name="paloaltonetworks.panos",
        )
        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"]
    target = module.params["target"]
    negate_target = module.params["negate_target"]

    # 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,
        target=target,
        negate_target=negate_target,
    )

    if not new_rule:
        module.fail_json(msg="Incorrect NAT rule params specified; quitting")

    # Perform the desired operation.
    changed = False
    diff = None
    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:
            diff = dict(before=eltostr(rule))
            rule.disabled = not rule.disabled
            diff["after"] = eltostr(rule)
            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, diff = 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, diff=diff, msg="Done")
コード例 #6
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_val" in kwargs:
        nat_rule.tag = kwargs["tag_val"]

    nat_rule.target = kwargs["target"]
    nat_rule.negate_target = kwargs["negate_target"]

    return nat_rule