def main():
    helper = get_connection(
        vsys=True,
        device_group=True,
        rulebase=True,
        with_classic_provider_spec=True,
        error_on_shared=True,
        argument_spec=dict(
            rule_name=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)

    name = module.params['rule_name']
    if name is None:
        try:
            listing = SecurityRule.refreshall(parent, name_only=True)
        except PanDeviceError as e:
            module.fail_json(msg='Failed refreshall: {0}'.format(e))
        module.exit_json(changed=False, rules=[x.name for x in listing])

    rule = SecurityRule(name)
    parent.add(rule)
    try:
        rule.refresh()
    except PanDeviceError as e:
        module.fail_json(msg='Failed refresh for "{0}": {1}'.format(name, e))

    spec = rule.about()

    renames = (
        ('name', 'rule_name'),
        ('fromzone', 'source_zone'),
        ('tozone', 'destination_zone'),
        ('source', 'source_ip'),
        ('destination', 'destination_ip'),
        ('type', 'rule_type'),
        ('tag', 'tag_name'),
        ('group', 'group_profile'),
        ('virus', 'antivirus'),
    )
    for pandevice_param, ansible_param in renames:
        spec[ansible_param] = spec[pandevice_param]
        del(spec[pandevice_param])

    module.exit_json(changed=False, spec=spec)
def main():
    helper = get_connection(
        vsys=True,
        device_group=True,
        rulebase=True,
        with_state=True,
        with_classic_provider_spec=True,
        error_on_shared=True,
        argument_spec=dict(
            rule_name=dict(required=True),
            source_zone=dict(type='list', default=['any']),
            source_ip=dict(type='list', default=["any"]),
            source_user=dict(type='list', default=['any']),
            hip_profiles=dict(type='list', default=['any']),
            destination_zone=dict(type='list', default=['any']),
            destination_ip=dict(type='list', default=["any"]),
            application=dict(type='list', default=['any']),
            service=dict(type='list', default=['application-default']),
            category=dict(type='list', default=['any']),
            action=dict(
                default='allow',
                choices=[
                    'allow', 'deny', 'drop', 'reset-client', 'reset-server',
                    'reset-both'
                ],
            ),
            log_setting=dict(),
            log_start=dict(type='bool', default=False),
            log_end=dict(type='bool', default=True),
            description=dict(),
            rule_type=dict(default='universal',
                           choices=['universal', 'intrazone', 'interzone']),
            tag_name=dict(type='list'),
            negate_source=dict(type='bool', default=False),
            negate_destination=dict(type='bool', default=False),
            disabled=dict(type='bool', default=False),
            schedule=dict(),
            icmp_unreachable=dict(type='bool'),
            disable_server_response_inspection=dict(type='bool',
                                                    default=False),
            group_profile=dict(),
            antivirus=dict(),
            spyware=dict(),
            vulnerability=dict(),
            url_filtering=dict(),
            file_blocking=dict(),
            wildfire_analysis=dict(),
            data_filtering=dict(),
            target=dict(type='list'),
            negate_target=dict(type='bool'),
            location=dict(choices=['top', 'bottom', 'before', 'after']),
            existing_rule=dict(),
            commit=dict(type='bool', default=True),

            # TODO(gfreeman) - remove this in the next role release.
            operation=dict(),

            # TODO(gfreeman) - remove this in the next role release.
            devicegroup=dict(),
        ),
    )
    module = AnsibleModule(
        argument_spec=helper.argument_spec,
        supports_check_mode=True,
        required_one_of=helper.required_one_of,
    )

    # TODO(gfreeman) - removed when operation is removed.
    if module.params['operation'] is not None:
        module.fail_json(
            msg='Param "operation" is removed; use "state" instead')

    # TODO(gfreeman) - remove when devicegroup is removed.
    if module.params['devicegroup'] is not None:
        module.deprecate(
            'Param "devicegroup" is deprecated; use "device_group"', '2.12')
        if module.params['device_group'] is not None:
            msg = [
                'Both "devicegroup" and "device_group" are specified',
                'Specify one or the other, not both.',
            ]
            module.fail_json(msg='. '.join(msg))
        module.params['device_group'] = module.params['devicegroup']

    # Verify imports, build pandevice object tree.
    parent = helper.get_pandevice_parent(module)

    # Set the SecurityRule object params.
    rule_spec = {
        'name':
        module.params['rule_name'],
        'fromzone':
        module.params['source_zone'],
        'tozone':
        module.params['destination_zone'],
        'source':
        module.params['source_ip'],
        'source_user':
        module.params['source_user'],
        'hip_profiles':
        module.params['hip_profiles'],
        'destination':
        module.params['destination_ip'],
        'application':
        module.params['application'],
        'service':
        module.params['service'],
        'category':
        module.params['category'],
        'action':
        module.params['action'],
        'log_setting':
        module.params['log_setting'],
        'log_start':
        module.params['log_start'],
        'log_end':
        module.params['log_end'],
        'description':
        module.params['description'],
        'type':
        module.params['rule_type'],
        'tag':
        module.params['tag_name'],
        'negate_source':
        module.params['negate_source'],
        'negate_destination':
        module.params['negate_destination'],
        'disabled':
        module.params['disabled'],
        'schedule':
        module.params['schedule'],
        'icmp_unreachable':
        module.params['icmp_unreachable'],
        'disable_server_response_inspection':
        module.params['disable_server_response_inspection'],
        'group':
        module.params['group_profile'],
        'virus':
        module.params['antivirus'],
        'spyware':
        module.params['spyware'],
        'vulnerability':
        module.params['vulnerability'],
        'url_filtering':
        module.params['url_filtering'],
        'file_blocking':
        module.params['file_blocking'],
        'wildfire_analysis':
        module.params['wildfire_analysis'],
        'data_filtering':
        module.params['data_filtering'],
        'target':
        module.params['target'],
        'negate_target':
        module.params['negate_target'],
    }

    # Other module info.
    location = module.params['location']
    existing_rule = module.params['existing_rule']
    commit = module.params['commit']

    # Retrieve the current rules.
    try:
        rules = SecurityRule.refreshall(parent, add=False)
    except PanDeviceError as e:
        module.fail_json(msg='Failed refresh: {0}'.format(e))

    # Create new rule object from the params.
    new_rule = SecurityRule(**rule_spec)
    parent.add(new_rule)

    # Which action shall we take on the rule object?
    changed, diff = helper.apply_state(new_rule, rules, module)

    # Move the rule to the correct spot, if applicable.
    if module.params['state'] == 'present':
        changed |= helper.apply_position(new_rule, location, existing_rule,
                                         module)

    # Optional commit.
    if changed and commit:
        helper.commit(module)

    # Done.
    module.exit_json(changed=changed, diff=diff, msg='Done')
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():
    argument_spec = dict(
        ip_address=dict(required=True),
        username=dict(default='admin'),
        password=dict(no_log=True),
        api_key=dict(no_log=True),
        rule_name=dict(required=True),
        source_zone=dict(type='list', default=['any']),
        source_ip=dict(type='list', default=["any"]),
        source_user=dict(type='list', default=['any']),
        hip_profiles=dict(type='list', default=['any']),
        destination_zone=dict(type='list', default=['any']),
        destination_ip=dict(type='list', default=["any"]),
        application=dict(type='list', default=['any']),
        service=dict(type='list', default=['application-default']),
        category=dict(type='list', default=['any']),
        action=dict(default='allow',
                    choices=[
                        'allow', 'deny', 'drop', 'reset-client',
                        'reset-server', 'reset-both'
                    ]),
        log_setting=dict(),
        log_start=dict(type='bool', default=False),
        log_end=dict(type='bool', default=True),
        description=dict(default=''),
        rule_type=dict(default='universal',
                       choices=['universal', 'intrazone', 'interzone']),
        tag_name=dict(type='list'),
        negate_source=dict(type='bool', default=False),
        negate_destination=dict(type='bool', default=False),
        disabled=dict(type='bool', default=False),
        schedule=dict(),
        icmp_unreachable=dict(type='bool'),
        disable_server_response_inspection=dict(type='bool', default=False),
        group_profile=dict(),
        antivirus=dict(),
        spyware=dict(),
        vulnerability=dict(),
        url_filtering=dict(),
        file_blocking=dict(),
        wildfire_analysis=dict(),
        data_filtering=dict(),
        target=dict(type='list'),
        negate_target=dict(type='bool', default=False),
        location=dict(choices=['top', 'bottom', 'before', 'after']),
        existing_rule=dict(),
        devicegroup=dict(),
        rulebase=dict(default='pre-rulebase',
                      choices=['pre-rulebase', 'post-rulebase']),
        vsys=dict(default='vsys1'),
        state=dict(choices=['present', 'absent']),
        operation=dict(default='add',
                       choices=['add', 'update', 'delete', 'find']),
        commit=dict(type='bool', default=True))
    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True,
                           required_one_of=[['api_key', 'password']])

    if not HAS_LIB:
        module.fail_json(msg='Missing required libraries.')
    elif not hasattr(SecurityRule, 'move'):
        module.fail_json(msg='Python library pandevice needs to be updated.')

    # Get the firewall / panorama auth.
    auth = (
        module.params['ip_address'],
        module.params['username'],
        module.params['password'],
        module.params['api_key'],
    )

    # Set the SecurityRule object params
    rule_spec = {
        'name':
        module.params['rule_name'],
        'fromzone':
        module.params['source_zone'],
        'tozone':
        module.params['destination_zone'],
        'source':
        module.params['source_ip'],
        'source_user':
        module.params['source_user'],
        'hip_profiles':
        module.params['hip_profiles'],
        'destination':
        module.params['destination_ip'],
        'application':
        module.params['application'],
        'service':
        module.params['service'],
        'category':
        module.params['category'],
        'action':
        module.params['action'],
        'log_setting':
        module.params['log_setting'],
        'log_start':
        module.params['log_start'],
        'log_end':
        module.params['log_end'],
        'description':
        module.params['description'],
        'type':
        module.params['rule_type'],
        'tag':
        module.params['tag_name'],
        'negate_source':
        module.params['negate_source'],
        'negate_destination':
        module.params['negate_destination'],
        'disabled':
        module.params['disabled'],
        'schedule':
        module.params['schedule'],
        'icmp_unreachable':
        module.params['icmp_unreachable'],
        'disable_server_response_inspection':
        module.params['disable_server_response_inspection'],
        'group':
        module.params['group_profile'],
        'virus':
        module.params['antivirus'],
        'spyware':
        module.params['spyware'],
        'vulnerability':
        module.params['vulnerability'],
        'url_filtering':
        module.params['url_filtering'],
        'file_blocking':
        module.params['file_blocking'],
        'wildfire_analysis':
        module.params['wildfire_analysis'],
        'data_filtering':
        module.params['data_filtering'],
    }

    # Get other info
    location = module.params['location']
    existing_rule = module.params['existing_rule']
    devicegroup = module.params['devicegroup']
    rulebase = module.params['rulebase']
    vsys = module.params['vsys']
    state = module.params['state']
    operation = module.params['operation']
    commit = module.params['commit']

    # 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'."
        )

    # Open the connection to the PAN-OS device
    device = None
    try:
        device = PanDevice.create_from_device(*auth)
    except PanDeviceError:
        e = get_exception()
        module.fail_json(msg=e.message)

    # Add some additional rule params if device is Panorama
    if isinstance(device, Panorama):
        rule_spec['target'] = module.params['target']
        rule_spec['negate_target'] = module.params['negate_target']

    # Set the attachment point for the RuleBase object
    parent = device
    if isinstance(parent, Firewall):
        if vsys is not None:
            vsys_list = Vsys.refreshall(parent)
            parent = get_vsys(vsys, vsys_list)
            if parent is None:
                module.fail_json(msg='VSYS not found: {0}'.format(vsys))
            parent = parent.add(Rulebase())
    elif isinstance(parent, Panorama):
        if devicegroup == 'shared':
            devicegroup = None
        if devicegroup is not None:
            parent = parent.add(Rulebase())
        else:
            parent = get_devicegroup(parent, devicegroup)
            if parent is None:
                module.fail_json(
                    msg='Device group not found: {0}'.format(devicegroup))
        if rulebase == 'pre-rulebase':
            parent = parent.add(PreRulebase())
        elif rulebase == 'post-rulebase':
            parent = parent.add(PostRulebase())

    # Now that we have the rulebase let's grab its security rules
    rules = SecurityRule.refreshall(parent)

    # Create new rule object from the params and add to rulebase
    new_rule = SecurityRule(**rule_spec)
    parent.add(new_rule)

    # Which action shall we take on the rule object?
    changed = False
    if state == 'present':
        match = find_rule(rules, new_rule)
        if match:
            # Change an existing rule
            if not match.equal(new_rule):
                try:
                    if not module.check_mode:
                        new_rule.apply()
                except PanDeviceError as e:
                    module.fail_json(
                        msg='Failed "present" apply: {0}'.format(e))
                else:
                    changed = True
        else:
            # Add a new rule
            try:
                if not module.check_mode:
                    new_rule.create()
            except PanDeviceError as e:
                module.fail_json(msg='Failed "present" apply: {0}'.format(e))
            else:
                changed = True
        # Move the rule if location is defined
        if location:
            try:
                if not module.check_mode:
                    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
    elif state == 'absent':
        match = find_rule(rules, new_rule)
        if match:
            # Delete an existing rule
            try:
                if not module.check_mode:
                    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:
            module.exit_json(stdout_lines=match.about(), msg='Rule matched')
        else:
            module.fail_json(
                msg='Rule \'%s\' not found. Is the name correct?' %
                new_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?' %
                new_rule.name)
        try:
            if not module.check_mode:
                new_rule.delete()
        except PanDeviceError as e:
            module.fail_json(msg='Failed "delete" delete: {0}'.format(e))
        else:
            changed = True
    elif operation == "add":
        # 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.'
                % new_rule.name)
        try:
            if not module.check_mode:
                new_rule.create()
        except PanDeviceError as e:
            module.fail_json(msg='Failed "add" create: {0}'.format(e))
        else:
            changed = True
            if location:
                try:
                    if not module.check_mode:
                        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))
    elif operation == 'update':
        # Search for the rule. Update if found.
        match = find_rule(rulebase, new_rule.name)
        if not match:
            module.fail_json(
                msg=
                'Rule \'%s\' does not exist. Use operation: \'add\' to add it.'
                % new_rule.name)
        try:
            if not module.check_mode:
                new_rule.apply()
        except PanDeviceError as e:
            module.fail_json(msg='Failed "update" apply: {0}'.format(e))
        else:
            changed = True
            if location:
                try:
                    if not module.check_mode:
                        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))

    # Optional commit.
    # FIXME: Commits should be done using the separate commit module
    if changed and commit:
        try:
            device.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,
        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():
    parser = argparse.ArgumentParser()
    parser.add_argument('--panorama',
                        help='hostname or ip of panorama',
                        required=True)
    parser.add_argument(
        '--master_device',
        help='hostname or ip of firewall to retrieve group-mappings',
        required=True)
    parser.add_argument(
        '--dg',
        help=
        'device group of the pre-rulebase that contain user-group-based policies',
        required=True)
    args = parser.parse_args()

    try:
        panorama = Panorama(args.panorama, input('Panorama username: '******'Panorama password: '******'show devices connected'
    try:
        res = panorama.op(cmd, xml=True)
    except PanDeviceError as e:
        print(e.message)
        sys.exit(1)

    devs_connected = xmltodict.parse(
        res)['response']['result']['devices']['entry']

    firewall = None

    for dev in devs_connected:
        if dev['hostname'] == args.master_device or dev[
                'ip-address'] == args.master_device:
            firewall = Firewall(serial=dev['serial'])
            break

    if firewall is not None:
        try:
            panorama.add(firewall)
        except PanDeviceError as e:
            print(e.message)
    else:
        print(
            'Master device (firewall) is not managed by Panorama. Attempting direct connection to firewall...'
        )
        try:
            firewall = Firewall(args.master_device,
                                input('Firewall username: '******'Firewall password: '******'Retrieving user-group-mappings on master device: "{}"...'.format(
        args.master_device))

    cmd = 'show user group list'
    try:
        res = firewall.op(cmd, xml=True)
    except PanDeviceError as e:
        print(e.message)

    user_group_data = xmltodict.parse(res)['response']['result']
    user_group_list = re.findall(r'cn=.*?dc=com', user_group_data)

    print('Number of mapped user-groups found: {}\n'.format(
        len(user_group_list)))
    print('Currently mapped user-groups: ')
    for user_group in user_group_list:
        print('"{}"'.format(user_group))
    print('\n')

    try:
        DeviceGroup.refreshall(panorama)
        target_dg = panorama.find(args.dg, DeviceGroup)

        if target_dg is None:
            print(
                'Device group "{}" not found on Panorama device. Aborting...'.
                format(args.dg))
            sys.exit()

        prb = PreRulebase()
        target_dg.add(prb)

        dg_pre_rules = SecurityRule.refreshall(prb)
    except PanDeviceError as e:
        print(e.message)

    print('Retrieving user-based security policy from device-group: "{}"...'.
          format(args.dg))

    user_based_rules = []
    for rule in dg_pre_rules:
        if not 'any' in rule.source_user:
            user_based_rules.append(rule)

    print('Number of user-based security rules found: {}\n'.format(
        len(user_based_rules)))

    for rule in user_based_rules:
        print('Validating user-based security rule: "{}"...'.format(rule.name))
        for user in rule.source_user:
            if not user in user_group_list:
                print('Invalid user-group: "{}"'.format(user))
        print('\n')
Exemple #7
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--panorama',
                        help='hostname or ip of panorama',
                        required=True)
    parser.add_argument('--user',
                        help='username for auth to panorama',
                        required=True)
    parser.add_argument(
        '--dg',
        help=
        'device group of the pre-rulebase that contain user-group-based policies',
        required=True)
    parser.add_argument('--group_mapping',
                        help='legacy to PAN LDAP group mappings csv file',
                        required=True)
    args = parser.parse_args()

    try:
        panorama = Panorama(args.panorama, args.user, getpass())
    except PanDeviceError as e:
        print(e.message)

    print('Retrieving user-based security policy from device-group: "{}"...'.
          format(args.dg))

    try:
        DeviceGroup.refreshall(panorama)
        target_dg = panorama.find(args.dg, DeviceGroup)

        if target_dg is None:
            print(
                'Device group "{}" not found on Panorama device. Aborting...'.
                format(args.dg))
            sys.exit()

        prb = PreRulebase()
        target_dg.add(prb)

        dg_pre_rules = SecurityRule.refreshall(prb)
    except PanDeviceError as e:
        print(e.message)

    with open(args.group_mapping, newline='') as csvfile:
        reader = csv.reader(csvfile)

        group_map_dict = {}
        for row in reader:
            group_map_dict[row[0]] = row[1]

    changed = None
    for rule in dg_pre_rules:
        if not 'any' in rule.source_user:
            print(rule.name)
            for k, v in group_map_dict.items():
                for user in rule.source_user:
                    if user == k:
                        print('{0} -> {1}'.format(user, v))
                        if not v in rule.source_user:
                            rule.source_user.append(v)
                        rule.source_user.remove(k)
                        changed = True

        if changed:
            try:
                rule.apply()
                changed = False
            except PanDeviceError as e:
                print(e.message)
Exemple #8
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()