def test_with_mandated_profile(self):
        test_xml = """\
        <response status="success"><result><config>
          <devices><entry><device-group><entry name="test_dg">
            <pre-rulebase><security><rules>
              <entry name="first_rule">
                <from><member>src_zone</member></from>
                <to><member>dest_zone</member></to>
                <source><member>ip-127.0.0.2</member></source>
                <destination><member>ip-127.0.0.3</member></destination>
              </entry>
              <entry name="superseding_rule">
                <from><member>src_zone</member></from>
                <to><member>dest_zone</member></to>
                <source><member>ip-127.0.0.2</member></source>
                <destination>
                  <member>ip-127.0.0.3</member>
                  <member>ip-127.0.0.4</member>
                </destination>
              </entry>
            </rules></security></pre-rulebase>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        rules = pan_config.get_devicegroup_policy('SecurityPreRules',
                                                  'test_dg')

        profilepackage = self.create_profilepackage(rules)
        results = find_superseding_rules(profilepackage)
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0].data[0][2], 'first_rule')
        self.assertEqual(results[0].data[1][2], 'superseding_rule')
Пример #2
0
    def test_badhostname(self, mocked_dns_lookup):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <pre-rulebase><security><rules>
              <entry name="test_rule">
                <source><member>invalid_fqdn</member></source>
                <destination><member>ignored_fqdn</member></destination>
              </entry>
            </rules></security></pre-rulebase>
            <address>
              <entry name="ignored_ip_netmask"><ip-netmask>127.0.0.1</ip-netmask></entry>
              <entry name="ignored_fqdn"><fqdn>ignored.tld</fqdn></entry>
              <entry name="valid_fqdn"><fqdn>valid.tld</fqdn></entry>
              <entry name="invalid_fqdn"><fqdn>invalid.bad.tld</fqdn></entry>
            </address>
            <address-group>
              <entry name="Sample valid AG"><static><member>valid_fqdn</member></static></entry>
              <entry name="Sample invalid AG"><static><member>invalid_fqdn</member></static></entry>
            </address-group>
          </shared>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        addresses = pan_config.get_devicegroup_object('Addresses', 'shared')
        address_groups = pan_config.get_devicegroup_object('AddressGroups', 'shared')
        rules = pan_config.get_devicegroup_policy('SecurityPreRules', 'shared')
        ignored_dns_prefixes = ["ignored"]
        mocked_dns_lookup.side_effect = ['127.0.0.1', None]
        profilepackage = self.create_profilepackage(addresses, address_groups, rules, ignored_dns_prefixes)

        _, _, validator_function = get_policy_validators()['BadHostname']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0].data.get('name'), 'invalid_fqdn')
    def test_missingzones(self, get_firewall_zone):
        test_xml = """\
        <response status="success"><result><config>
          <devices><entry><device-group><entry name="test_dg">
            <pre-rulebase><security><rules>
              <entry name="missing_zone_rule">
                <from>
                  <member>src_zone</member>
                </from>
                <to>
                  <member>dest_zone</member>
                </to>
                <source>
                  <member>ip-127.0.0.2</member>
                </source>
                <destination>
                  <member>ip-127.0.0.3</member>
                  <member>ip-127.0.0.4</member>
                </destination>
              </entry>
            </rules></security></pre-rulebase>
            <address>
              <entry name="ip-127.0.0.2"><ip-netmask>127.0.0.2</ip-netmask></entry>
              <entry name="ip-127.0.0.3"><ip-netmask>127.0.0.3</ip-netmask></entry>
              <entry name="ip-127.0.0.4"><ip-netmask>127.0.0.4</ip-netmask></entry>
            </address>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        rules = pan_config.get_devicegroup_policy('SecurityPreRules',
                                                  'test_dg')
        addresses = pan_config.get_devicegroup_object('Addresses', 'test_dg')

        profilepackage = self.create_profilepackage(rules, addresses)
        get_firewall_zone.side_effect = [
            'src_zone', 'dest_zone', "missing_zone"
        ]
        _, _, validator_function = get_policy_validators()['MissingZones']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0].data.get('name'), 'missing_zone_rule')
def load_config_package(configuration_settings, api_key, device_group, limit, no_api, xml_file=None):
    if xml_file:
        # The list of firewalls are not available from the API, so
        # these variables will remain empty
        logger.debug(f"Loading configuration from XML file: {xml_file}")
        with open(xml_file, encoding='utf-8') as fh:
            xml_config = fh.read()
        pan_config = PanConfig(xml_config, True)
        device_groups_and_firewalls = collections.defaultdict(list)
        active_firewalls_per_devicegroup = collections.defaultdict(list)
    else:
        # Load the XML configuration and list of firewalls via API requests
        panorama = configuration_settings.get('panorama')
        xml_config = pan_api.export_configuration2(panorama, api_key)
        pan_config = PanConfig(xml_config)
        device_groups_and_firewalls = pan_api.get_device_groups_and_firewalls(panorama, api_key)
        active_firewalls = pan_api.get_active_firewalls(panorama, api_key)
        # Build the mapping of active FWs in each device group
        active_firewalls_per_devicegroup = collections.defaultdict(list)
        for dg, firewalls in device_groups_and_firewalls.items():
            active_firewalls_per_devicegroup[dg] = [fw for fw in firewalls if fw in active_firewalls]

    device_group_hierarchy_children, device_group_hierarchy_parent = pan_config.get_device_groups_hierarchy()

    # Build a mapping of device groups to their 'child' device groups
    all_device_groups = pan_config.get_device_groups() + ['shared']
    devicegroups_to_child_devicegroups = squash_all_devicegroups(all_device_groups,
                                                                 device_group_hierarchy_children)

    all_active_firewalls_per_devicegroup = collections.defaultdict(list)
    for dg, child_dgs in devicegroups_to_child_devicegroups.items():
        all_active_firewalls_per_devicegroup[dg] = []
        for child_dg in child_dgs:
            all_active_firewalls_per_devicegroup[dg] += active_firewalls_per_devicegroup[child_dg]

    # Create and fill in the devicegroup_objects, which represents all entries, per devicegroup
    devicegroup_objects = {}

    if device_group:
        device_groups = [device_group]
    else:
        device_groups = all_device_groups

    for device_group in all_device_groups:
        devicegroup_objects[device_group] = {}
        devicegroup_objects[device_group]['all_child_device_groups'] = devicegroups_to_child_devicegroups[device_group]
        devicegroup_objects[device_group]['all_active_child_firewalls'] = all_active_firewalls_per_devicegroup[
            device_group]

        for policy_type in pan_config.SUPPORTED_POLICY_TYPES:
            devicegroup_objects[device_group][policy_type] = pan_config.get_devicegroup_policy(policy_type, device_group)[:limit]
        for object_type in pan_config.SUPPORTED_OBJECT_TYPES:
            devicegroup_objects[device_group][object_type] = pan_config.get_devicegroup_object(object_type, device_group)

    rule_limit_enabled = limit is not None

    # Build a listing of policy objects that are exclusive to each device group, which won't include policies inherited from the parent device groups
    devicegroup_exclusive_objects = {}
    for device_group in all_device_groups:
        devicegroup_exclusive_objects[device_group] = {}

        for policy_type in pan_config.SUPPORTED_POLICY_TYPES:
            if device_group not in device_group_hierarchy_parent:
                # No parent means no inherited policies
                devicegroup_exclusive_objects[device_group][policy_type] = devicegroup_objects[device_group][
                    policy_type]
            else:
                parent_dg = device_group_hierarchy_parent[device_group]
                parent_policy_uuids = set([entry.get('@uuid') for entry in devicegroup_objects[parent_dg][policy_type]])
                exclusive_objects = [entry for entry in devicegroup_objects[device_group][policy_type] if
                                     entry.get('@uuid') not in parent_policy_uuids]
                devicegroup_exclusive_objects[device_group][policy_type] = exclusive_objects

    profilepackage = ProfilePackage(
        api_key=api_key,
        pan_config=pan_config,
        settings=configuration_settings,
        device_group_hierarchy_children=device_group_hierarchy_children,
        device_group_hierarchy_parent=device_group_hierarchy_parent,
        device_groups_and_firewalls=device_groups_and_firewalls,
        device_groups=device_groups,
        devicegroup_objects=devicegroup_objects,
        devicegroup_exclusive_objects=devicegroup_exclusive_objects,
        rule_limit_enabled=rule_limit_enabled,
        no_api=no_api
    )
    return profilepackage
    def test_unusedaddresses(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <address>
              <entry name="address_unused"/>
              <entry name="address_used_addressgroup"/>
              <entry name="address_used_security"/>
              <entry name="address_used_in_nat1"/>
              <entry name="address_used_in_dg"/>
            </address>
            <address-group>
              <entry name="addressgroup1"><static><member>address_used_addressgroup</member></static></entry>
            </address-group>
            <pre-rulebase>
              <security><rules>
                <entry name="shared_rule1"><source><member>address_used_security</member></source></entry>
                <entry name="shared_rule2"><destination><member>addressgroup1</member></destination></entry>
              </rules></security>
              <nat><rules>
                <entry name="nat1"><source-translation><translated-address>address_used_in_nat1</translated-address></source-translation></entry>
              </rules></nat>
            </pre-rulebase>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <address>
              <entry name="service_unused_dg"/>
            </address>
            <pre-rulebase>
              <security><rules>
                <entry name="shared_rule"><source><member>address_used_in_dg</member></source></entry>
              </rules></security>
            </pre-rulebase>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        shared_addresses = pan_config.get_devicegroup_object(
            'Addresses', 'shared')
        shared_addressgroups = pan_config.get_devicegroup_object(
            'AddressGroups', 'shared')
        shared_securityprerules = pan_config.get_devicegroup_policy(
            'SecurityPreRules', 'shared')
        shared_natprerules = pan_config.get_devicegroup_policy(
            'NATPreRules', 'shared')
        dg_addresses = pan_config.get_devicegroup_object(
            'Addresses', 'test_dg')
        dg_securityprerules = pan_config.get_devicegroup_policy(
            'SecurityPreRules', 'test_dg')

        profilepackage = self.create_profilepackage(
            shared_addresses, shared_addressgroups, shared_securityprerules,
            shared_natprerules, dg_addresses, dg_securityprerules)

        _, _, validator_function = get_policy_validators()['UnusedAddresses']
        results = validator_function(profilepackage)

        self.assertEqual(len(results), 1)
        self.assertEqual(len(results[0].data), 1)
        self.assertEqual(results[0].data[0].get('name'), 'address_unused')
        self.assertEqual(results[0].device_group, 'shared')