Ejemplo n.º 1
0
    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="same_zone_rule">
                <service>
                  <member>tcp-123</member>
                  <member>myservicegroup</member>
                </service>
              </entry>
            </rules></security></pre-rulebase>
            <service><entry name="tcp-123"><protocol><tcp><port>123</port></tcp></protocol></entry></service>
            <service-group><entry name="myservicegroup"><members><member>tcp-123</member></members></entry></service-group>
          </entry></device-group></entry></devices>
          <readonly><devices><entry name="localhost.localdomain"><device-group>
            <entry name="test_dg"><id>11</id></entry>
          </device-group></entry></devices></readonly>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)

        profilepackage = self.create_profilepackage(pan_config)
        _, _, validator_function = get_policy_validators()['RedundantRuleServices']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        ruletype, rule_entry, members_to_remove = results[0].data
        self.assertEqual(ruletype, 'SecurityPreRules')
        self.assertEqual(rule_entry.get('name'), 'same_zone_rule')
        self.assertEqual(members_to_remove, [('tcp-123', 'myservicegroup')])
def consolidate_addressgroups(profilepackage):
    object_friendly_type = "Address Group"
    _, _, validator_function = get_policy_validators(
    )['FindConsolidatableAddressGroups']
    return consolidate_service_like_objects(profilepackage,
                                            object_friendly_type,
                                            validator_function)
Ejemplo n.º 3
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_unusedaddresses(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <profile-group>
              <entry name="used_group1"></entry>
              <entry name="used_group2"></entry>
              <entry name="unused_group3"></entry>
            </profile-group>
            <pre-rulebase>
              <security><rules>
                <entry name="shared_rule1"><profile-setting><group><member>used_group1</member></group></profile-setting></entry>
              </rules></security>
            </pre-rulebase>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <pre-rulebase>
              <security><rules>
                <entry name="dg_rule2"><profile-setting><group><member>used_group2</member></group></profile-setting></entry>
              </rules></security>
            </pre-rulebase>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        profilepackage = self.create_profilepackage(pan_config)

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

        self.assertEqual(len(results), 1)
        self.assertEqual(len(results[0].data), 1)
        self.assertEqual(results[0].data[0].get('name'), 'unused_group3')
        self.assertEqual(results[0].device_group, 'shared')
def delete_disabled_policies(profilepackage):
    panorama = profilepackage.settings.get("Panorama")
    api_key = profilepackage.api_key
    pan_config = profilepackage.pan_config
    version = pan_config.get_major_version()

    _, _, validator_function = get_policy_validators()['DisabledPolicies']
    policies_to_delete = validator_function(profilepackage)
    if policies_to_delete:
        logger.info(
            f"Deleting {len(policies_to_delete)} disabled policies now")
        for policy_entry in policies_to_delete:
            device_group = policy_entry.device_group
            policy_name = policy_entry.data[0].get('name')
            policy_type = policy_entry.entry_type

            logger.info(
                f"Deleting Device Group {device_group}'s {policy_type} {policy_name}"
            )
            try:
                pan_api.delete_policy(panorama, version, api_key, policy_type,
                                      policy_name, device_group)
            except requests.HTTPError as err:
                logger.info(
                    f"Error deleting {device_group}'s {policy_type} {policy_name}: {err.response.text}"
                )
        pan_api.validate_commit(panorama, api_key)

    return policies_to_delete
    def test_shadowing_addresses_and_groups(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <address>
              <entry name="dup_shared_address_shared_ag_dg_address"/>
            </address>
            <address-group>
              <entry name="dup_shared_address_shared_ag_dg_address"/>
            </address-group>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <address>
              <entry name="dup_shared_address_shared_ag_dg_address"/>
            </address>
            <address-group>
            </address-group>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        shared_addresses = pan_config.get_devicegroup_object(
            'Addresses', 'shared')
        dg_addesses = pan_config.get_devicegroup_object('Addresses', 'test_dg')
        shared_addressgroups = pan_config.get_devicegroup_object(
            'AddressGroups', 'shared')
        dg_addessgroups = pan_config.get_devicegroup_object(
            'AddressGroups', 'test_dg')
        profilepackage = self.create_profilepackage(shared_addresses,
                                                    dg_addesses,
                                                    shared_addressgroups,
                                                    dg_addessgroups)

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

        self.assertEqual(len(results), 2)
        self.assertEqual(len(results[0].data), 2)
        self.assertEqual(results[0].data[0][0], 'shared')
        self.assertEqual(results[0].data[0][1], 'AddressGroups')
        self.assertEqual(results[0].data[0][2].get('name'),
                         'dup_shared_address_shared_ag_dg_address')
        self.assertEqual(results[0].data[1][0], 'shared')
        self.assertEqual(results[0].data[1][1], 'Addresses')
        self.assertEqual(results[0].data[1][2].get('name'),
                         'dup_shared_address_shared_ag_dg_address')
        self.assertEqual(len(results[1].data), 3)
        self.assertEqual(results[1].data[0][0], 'test_dg')
        self.assertEqual(results[1].data[0][1], 'Addresses')
        self.assertEqual(results[1].data[0][2].get('name'),
                         'dup_shared_address_shared_ag_dg_address')
        self.assertEqual(results[1].data[1][0], 'shared')
        self.assertEqual(results[1].data[1][1], 'Addresses')
        self.assertEqual(results[1].data[1][2].get('name'),
                         'dup_shared_address_shared_ag_dg_address')
        self.assertEqual(results[1].data[2][0], 'shared')
        self.assertEqual(results[1].data[2][1], 'AddressGroups')
        self.assertEqual(results[1].data[2][2].get('name'),
                         'dup_shared_address_shared_ag_dg_address')
    def test_misleading_services(self):
        test_xml = """\
        <response status="success"><result><config><shared><service>
            <entry name="valid-tcp-123"><protocol><tcp><port>123</port></tcp></protocol></entry>
            <entry name="valid-tcp-1234"><protocol><tcp><port>123</port></tcp></protocol></entry>
            <entry name="valid-udp-123"><protocol><udp><port>123</port></udp></protocol></entry>
            <entry name="valid-udp-1234"><protocol><udp><port>123</port></udp></protocol></entry>
            <entry name="invalid-protocol-tcp-123"><protocol><udp><port>123</port></udp></protocol></entry>
            <entry name="invalid-protocol-udp-1234"><protocol><tcp><port>123</port></tcp></protocol></entry>
            <entry name="invalid-port-1233"><protocol><udp><port>1234</port></udp></protocol></entry>
            <entry name="invalid-port-and-protocol-tcp-123"><protocol><udp><port>1234</port></udp></protocol></entry>
        </service></shared></config></result></response>
        """
        pan_config = PanConfig(test_xml)
        services = pan_config.get_devicegroup_object('Services', 'shared')
        profilepackage = self.create_profilepackage(services)

        _, _, validator_function = get_policy_validators(
        )['MisleadingServices']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 4)
        self.assertEqual(results[0].data.get('name'),
                         'invalid-protocol-tcp-123')
        self.assertEqual(results[1].data.get('name'),
                         'invalid-protocol-udp-1234')
        self.assertEqual(results[2].data.get('name'), 'invalid-port-1233')
        self.assertEqual(results[3].data.get('name'),
                         'invalid-port-and-protocol-tcp-123')
Ejemplo n.º 8
0
def remove_redundant_rule_members(profilepackage):
    panorama = profilepackage.settings.get("Panorama")
    api_key = profilepackage.api_key
    pan_config = profilepackage.pan_config
    version = pan_config.get_major_version()

    _, _, validator_function = get_policy_validators(
    )['RedundantRuleAddresses']
    logger.info("*" * 80)
    logger.info("Checking for redundant rule addresses")

    rules_to_update = validator_function(profilepackage)

    logger.info(f"Replacing the contents of {len(rules_to_update)} Policies")
    for badentry in rules_to_update:
        object_policy_dg = badentry.device_group
        rule_type, rule_entry, members_to_remove = badentry.data
        rule_dict = xml_object_to_dict(rule_entry)['entry']
        for direction, member_and_containing_pairs in members_to_remove.items(
        ):
            for member, _ in member_and_containing_pairs:
                # It's possible a member is contained in two of a rule's address groups
                if member in rule_dict[direction]['member']:
                    rule_dict[direction]['member'].remove(member)
        pan_api.update_devicegroup_policy(panorama, version, api_key,
                                          rule_dict, rule_type,
                                          object_policy_dg)
    pan_api.validate_commit(panorama, api_key)
    logger.info("Replacement complete. Please commit in the firewall.")
    return rules_to_update
 def test_equivalent_addressgroups(self):
     test_xml = """\
     <response status="success"><result><config>
       <shared>
         <address>
           <entry name="unique_netmask1"><ip-netmask>127.0.0.2/32</ip-netmask></entry>
           <entry name="unique_netmask2"><ip-netmask>127.0.0.1/32</ip-netmask></entry>
         </address>
         <address-group>
           <entry name="address_group1"><static><member>unique_netmask1</member><member>unique_netmask2</member></static></entry>
           <entry name="address_group2"><static><member>unique_netmask2</member><member>unique_netmask1</member></static></entry>
         </address-group>
       </shared>
     </config></result></response>
     """
     pan_config = PanConfig(test_xml)
     profilepackage = self.create_profilepackage('AddressGroups',
                                                 pan_config)
     _, _, validator_function = get_policy_validators(
     )['EquivalentAddressGroups']
     results = validator_function(profilepackage)
     self.assertEqual(len(results), 1)
     self.assertEqual(len(results[0].data), 2)
     self.assertEqual(results[0].data[0][0], 'shared')
     self.assertEqual(results[0].data[0][1].get('name'), 'address_group1')
     self.assertEqual(results[0].data[1][0], 'shared')
     self.assertEqual(results[0].data[1][1].get('name'), 'address_group2')
Ejemplo n.º 10
0
def find_consolidatable_services(profilepackage):
    object_type = "Services"
    object_friendly_type = "Service"
    _, _, validator_function = get_policy_validators()['EquivalentServices']
    return consolidate_service_like_objects(profilepackage, object_type,
                                            object_friendly_type,
                                            validator_function)
    def test_equivalent_servicegroups(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <service>
              <entry name="tcp-1"><protocol><tcp><port>1</port><override><no/></override></tcp></protocol></entry>
              <entry name="tcp-2"><protocol><tcp><port>2</port><override><no/></override></tcp></protocol></entry>
            </service>
            <service-group>
              <entry name="dup1"><members><member>tcp-1</member><member>tcp-2</member></members></entry>
              <entry name="dup2"><members><member>tcp-2</member><member>tcp-1</member></members></entry>
            </service-group>
          </shared>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        profilepackage = self.create_profilepackage('ServiceGroups',
                                                    pan_config)

        _, _, validator_function = get_policy_validators(
        )['EquivalentServiceGroups']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        self.assertEqual(len(results[0].data), 2)
        self.assertEqual(results[0].data[0][0], 'shared')
        self.assertEqual(results[0].data[0][1].get('name'), 'dup1')
        self.assertEqual(results[0].data[1][0], 'shared')
        self.assertEqual(results[0].data[1][1].get('name'), 'dup2')
    def test_similar_shared_address_and_dg_addressgroups(self):
        # SimilarAddressesAndGroups previously detected
        # duplicates across device groups. This test is
        # being kept to ensure behavior is as expected.
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <address-group>
              <entry name="SHARED_address_and_dg_addressgroup"/>
            </address-group>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <address>
              <entry name="shared_address_and_DG_addressgroup"/>
            </address>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        shared_addresses = pan_config.get_devicegroup_object(
            'Addresses', 'shared')
        dg_addesses = pan_config.get_devicegroup_object('Addresses', 'test_dg')
        shared_addressgroups = pan_config.get_devicegroup_object(
            'AddressGroups', 'shared')
        dg_addessgroups = pan_config.get_devicegroup_object(
            'AddressGroups', 'test_dg')
        profilepackage = self.create_profilepackage(shared_addresses,
                                                    dg_addesses,
                                                    shared_addressgroups,
                                                    dg_addessgroups)

        _, _, validator_function = get_policy_validators(
        )['SimilarAddressesAndGroups']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 0)
    def test_shadowing_services(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <service>
              <entry name="tcp-nondup"><protocol><tcp><port>1</port><override><no/></override></tcp></protocol></entry>
              <entry name="tcp-dup"><protocol><tcp><port>2</port><override><no/></override></tcp></protocol></entry>
            </service>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <service>
              <entry name="tcp-dup"><protocol><tcp><port>2</port><override><no/></override></tcp></protocol></entry>
            </service>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        shared_services = pan_config.get_devicegroup_object('Services', 'shared')
        dg_services = pan_config.get_devicegroup_object('Services', 'test_dg')
        profilepackage = self.create_profilepackage(shared_services, dg_services, [], [])

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

        self.assertEqual(len(results), 1)
        self.assertEqual(len(results[0].data), 2)
        self.assertEqual(results[0].data[0][0], 'shared')
        self.assertEqual(results[0].data[0][1].get('name'), 'tcp-dup')
        self.assertEqual(results[0].data[1][0], 'test_dg')
        self.assertEqual(results[0].data[1][1].get('name'), 'tcp-dup')
    def test_shadowing_servicegroups(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <service-group>
              <entry name="uniquegroup1"><members><member>mem1</member><member>mem2</member></members></entry>
              <entry name="dupgroup1"><members><member>mem1</member><member>mem2</member></members></entry>
            </service-group>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <service-group>
              <entry name="dupgroup1"><members><member>mem1</member><member>mem2</member></members></entry>
              <entry name="uniquegroup2"><members><member>mem1</member><member>mem2</member></members></entry>
            </service-group>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        shared_service_groups = pan_config.get_devicegroup_object('ServiceGroups', 'shared')
        dg_service_groups = pan_config.get_devicegroup_object('ServiceGroups', 'test_dg')

        profilepackage = self.create_profilepackage([], [], shared_service_groups, dg_service_groups)

        _, _, validator_function = get_policy_validators()['ShadowingServiceGroups']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        self.assertEqual(len(results[0].data), 2)
        self.assertEqual(results[0].data[0][0], 'shared')
        self.assertEqual(results[0].data[0][1].get('name'), 'dupgroup1')
        self.assertEqual(results[0].data[1][0], 'test_dg')
        self.assertEqual(results[0].data[1][1].get('name'), 'dupgroup1')
    def test_misleading_services(self):
        test_xml = """\
        <response status="success"><result><config><shared><service>
            <entry name="prefix-tcp-123"><protocol><tcp><port>123</port></tcp></protocol></entry>
            <entry name="prefix-tcp-1234"><protocol><tcp><port>123</port></tcp></protocol></entry>
            <entry name="prefix-udp-123"><protocol><udp><port>123</port></udp></protocol></entry>
            <entry name="prefix-udp-1234"><protocol><udp><port>123</port></udp></protocol></entry>
            <entry name="missing-tcp-123"><protocol><udp><port>1234</port></udp></protocol></entry>
        </service></shared></config></result></response>
        """
        pan_config = PanConfig(test_xml)
        service_name_format = 'prefix-{transport}-{port}'
        profilepackage = self.create_profilepackage(pan_config,
                                                    service_name_format)

        _, _, validator_function = get_policy_validators(
        )['UnconventionallyNamedServices']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 3)
        self.assertEqual(results[0].data[0].get('name'), 'prefix-tcp-1234')
        self.assertEqual(results[0].data[1], 'prefix-tcp-123')
        self.assertEqual(results[1].data[0].get('name'), 'prefix-udp-1234')
        self.assertEqual(results[1].data[1], 'prefix-udp-123')
        self.assertEqual(results[2].data[0].get('name'), 'missing-tcp-123')
        self.assertEqual(results[2].data[1], 'prefix-udp-1234')
def find_badhostnameusage(profilepackage):
    device_groups = profilepackage.device_groups
    devicegroup_objects = profilepackage.devicegroup_objects
    devicegroup_exclusive_objects = profilepackage.devicegroup_exclusive_objects

    _, _, validator_function = get_policy_validators()['BadHostname']

    bad_hostname_results = validator_function(profilepackage)
    bad_address_objects = set()
    for entry in bad_hostname_results:
        bad_address_objects.add(entry.data.get('name'))

    badentries = []
    for i, device_group in enumerate(device_groups):
        logger.info(
            f"({i + 1}/{len(device_groups)}) Checking {device_group}'s Address Groups"
        )
        for entry in devicegroup_objects[device_group]['AddressGroups']:
            address_group_members = []
            for ag_member in entry.findall('./static/member'):
                address_group_members.append(ag_member.text)
            bad_members = bad_address_objects & set(address_group_members)
            if bad_members:
                text = f"Device Group {device_group}'s Address Group '{entry.get('name')}' uses the following address objects which don't resolve: {sorted(bad_members)}"
                badentries.append(
                    BadEntry(data=entry,
                             text=text,
                             device_group=device_group,
                             entry_type='AddressGroups'))

    for i, device_group in enumerate(device_groups):
        for ruletype in ('SecurityPreRules', 'SecurityPostRules'):
            rules = devicegroup_exclusive_objects[device_group][ruletype]
            logger.info(
                f"({i + 1}/{len(device_groups)}) Checking {device_group}'s {ruletype}"
            )

            for entry in rules:
                # Disabled rules can be ignored
                if entry.find("./disabled") is not None and entry.find(
                        "./disabled").text == "yes":
                    continue

                rule_name = entry.get('name')
                source_members = set(
                    [sm.text for sm in entry.findall('./source/member')])
                dest_members = set(
                    [dm.text for dm in entry.findall('./destination/member')])

                for members, direction in [(source_members, 'Source'),
                                           (dest_members, 'Dest')]:
                    bad_members = bad_address_objects & members
                    if bad_members:
                        text = f"Device Group {device_group}'s {ruletype} '{rule_name}' {direction} contain the following address objects which don't resolve: {sorted(bad_members)}"
                        badentries.append(
                            BadEntry(data=entry,
                                     text=text,
                                     device_group=device_group,
                                     entry_type=ruletype))
    return badentries
def rename_unconventional_object(profilepackage, validator_name, object_type,
                                 object_friendly_name):
    panorama = profilepackage.settings.get("Panorama")
    api_key = profilepackage.api_key
    pan_config = profilepackage.pan_config
    version = pan_config.get_major_version()

    _, _, validator_function = get_policy_validators()[validator_name]
    objects_to_rename = validator_function(profilepackage)
    if not objects_to_rename:
        return objects_to_rename

    logger.info(
        f"Renaming {len(objects_to_rename)} {object_friendly_name} now")
    for object_entry in objects_to_rename:
        device_group = object_entry.device_group
        old_name = object_entry.data[0].get('name')
        new_name = object_entry.data[1]

        logger.info(
            f"Renaming Device Group {device_group}'s {object_friendly_name} from {old_name} to {new_name}"
        )
        try:
            pan_api.rename_object(panorama, version, api_key, object_type,
                                  old_name, new_name, device_group)
        except requests.HTTPError as err:
            logger.info(
                f"Error Renaming {device_group}'s {object_friendly_name} {old_name}: {err.response.text}"
            )
    pan_api.validate_commit(panorama, api_key)

    return objects_to_rename
    def test_IPWithResolvingFQDN(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="redundant_ip"><ip-netmask>127.0.0.1/32</ip-netmask></entry>
              <entry name="valid_fqdn"><fqdn>valid.tld</fqdn></entry>
              <entry name="invalid_fqdn"><fqdn>invalid.bad.tld</fqdn></entry>
            </address>
          </shared>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        mocked_dns_lookup.side_effect = [('valid.tld', [], ["127.0.0.1"]),
                                         (None, [], [])]
        profilepackage = self.create_profilepackage(pan_config)

        _, _, validator_function = get_policy_validators(
        )['IPWithResolvingFQDN']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0].data[0].get('name'), 'redundant_ip')
        self.assertEqual(results[0].data[1], 'valid.tld')
def remove_redundant_rule_services(profilepackage):
    panorama = profilepackage.settings.get("Panorama")
    api_key = profilepackage.api_key
    pan_config = profilepackage.pan_config
    version = pan_config.get_major_version()

    _, _, validator_function = get_policy_validators()['ShadowingRules']
    logger.info("*" * 80)
    logger.info("Checking for shadowed rules to disable")

    rules_to_update = validator_function(profilepackage)

    logger.info(f"Disabling {len(rules_to_update)} Policies")
    for badentry in rules_to_update:
        shadowed_tuple = badentry.data[0]
        device_group, ruletype, rule_name, rule_entry = shadowed_tuple
        disabled = (rule_entry.find('disabled') is not None
                    and rule_entry.find('disabled').text == 'yes')
        if not disabled:
            policy_dict = xml_object_to_dict(rule_entry)['entry']
            policy_dict['disabled'] = 'yes'
            logger.info(f"Disabling {device_group}'s {ruletype} {rule_name}")
            pan_api.update_devicegroup_policy(panorama, version, api_key,
                                              policy_dict, ruletype,
                                              device_group)
    pan_api.validate_commit(panorama, api_key)
    logger.info("Disabling complete. Please commit in the firewall.")
    return rules_to_update
Ejemplo n.º 20
0
    def test_consolidatable_addresses(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <address>
              <entry name="unique_netmask1"><ip-netmask>127.0.0.1/32</ip-netmask></entry>
              <entry name="unique_netmask2"><ip-netmask>127.0.0.2/32</ip-netmask></entry>
              <entry name="duplicate_netmask2"><ip-netmask>127.0.0.2/32</ip-netmask></entry>
            </address>
            <address-group>
              <entry name="address_group1"><static><member>unique_netmask1</member><member>unique_netmask2</member></static></entry>
              <entry name="address_group2"><static><member>unique_netmask2</member><member>unique_netmask1</member></static></entry>
              <entry name="address_group3"><static><member>duplicate_netmask2</member><member>unique_netmask1</member></static></entry>
            </address-group>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <pre-rulebase><security><rules>
              <entry name="rule1">
                <from><member>src_zone</member></from>
                <to><member>dest_zone</member></to>
                <source><member>unique_netmask1</member></source>
                <destination><member>unique_netmask2</member></destination>
                <service><member>tcp2-dup1</member></service>
              </entry>
              <entry name="rule2">
                <from><member>src_zone</member></from>
                <to><member>dest_zone</member></to>
                <source><member>unique_netmask1</member></source>
                <destination><member>unique_netmask2</member></destination>
                <service><member>tcp2-dup1</member></service>
              </entry>
              <entry name="rule3">
                <from><member>src_zone</member></from>
                <to><member>dest_zone</member></to>
                <source><member>unique_netmask1</member></source>
                <destination><member>duplicate_netmask2</member></destination>
                <service><member>tcp2-dup2</member></service>
              </entry>
            </rules></security></pre-rulebase>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        profilepackage = self.create_profilepackage(pan_config)

        _, _, validator_function = get_policy_validators(
        )['FindConsolidatableAddresses']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 2)
        self.assertEqual(len(results[0].data), 2)
        self.assertEqual(results[0].data[0].get('name'), 'address_group3')
        self.assertEqual(results[0].data[1]['static']['member'][0],
                         'unique_netmask2')
        self.assertEqual(len(results[1].data), 2)
        self.assertEqual(results[1].data[0].get('name'), 'rule3')
        self.assertEqual(results[1].data[1]['destination']['member'],
                         'unique_netmask2')
    def test_similar_servicegroups(self):
        test_xml = """\
        <response status="success"><result><config>
          <shared>
            <service-group>
              <entry name="shared_servicegroup1"/>
              <entry name="SHARED_servicegroup1"/>
            </service-group>
          </shared>
          <devices><entry><device-group><entry name="test_dg">
            <service-group>
              <entry name="dg_servicegroup1"/>
              <entry name="DG_servicegroup1"/>
            </service-group>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        shared_services = pan_config.get_devicegroup_object(
            'Services', 'shared')
        dg_services = pan_config.get_devicegroup_object('Services', 'test_dg')
        shared_servicegroups = pan_config.get_devicegroup_object(
            'ServiceGroups', 'shared')
        dg_servicegroups = pan_config.get_devicegroup_object(
            'ServiceGroups', 'test_dg')
        profilepackage = self.create_profilepackage(shared_services,
                                                    dg_services,
                                                    shared_servicegroups,
                                                    dg_servicegroups)

        _, _, validator_function = get_policy_validators(
        )['SimilarServicesAndGroups']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 2)
        self.assertEqual(len(results[0].data), 2)
        self.assertEqual(results[0].data[0][0], 'shared')
        self.assertEqual(results[0].data[0][1], 'ServiceGroups')
        self.assertEqual(results[0].data[0][2].get('name'),
                         'shared_servicegroup1')
        self.assertEqual(results[0].data[1][0], 'shared')
        self.assertEqual(results[0].data[1][1], 'ServiceGroups')
        self.assertEqual(results[0].data[1][2].get('name'),
                         'SHARED_servicegroup1')
        self.assertEqual(len(results[1].data), 2)
        self.assertEqual(results[1].data[0][0], 'test_dg')
        self.assertEqual(results[1].data[0][1], 'ServiceGroups')
        self.assertEqual(results[1].data[0][2].get('name'), 'dg_servicegroup1')
        self.assertEqual(results[1].data[1][0], 'test_dg')
        self.assertEqual(results[1].data[1][1], 'ServiceGroups')
        self.assertEqual(results[1].data[1][2].get('name'), 'DG_servicegroup1')
    def test_replaceableaddresses(self):
        test_xml = """\
        <response status="success"><result><config>
          <devices><entry><device-group><entry name="test_dg">
            <pre-rulebase><security><rules>
              <entry name="sservices_can_be_group">
                <source>
                  <member>ip-127.0.0.1</member>
                  <member>ip-127.0.0.2</member>
                </source>
                <destination>
                  <member>ip-127.0.0.3</member>
                </destination>
                <service>
                  <member>tcp-123</member>
                  <member>tcp-456</member>
                </service>
              </entry>
            </rules></security></pre-rulebase>
            <address>
              <entry name="ip-127.0.0.1"><ip-netmask>127.0.0.1</ip-netmask></entry>
              <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>
            </address>
            <address-group>
              <entry name="address_addressgroup1"><static><member>ip-127.0.0.1</member><member>ip-127.0.0.2</member></static></entry>
            </address-group>
            <service>
              <entry name="tcp-123"><protocol><tcp><port>123</port></tcp></protocol></entry>
              <entry name="tcp-456"><protocol><tcp><port>456</port></tcp></protocol></entry>
            </service>
            <service-group><entry name="myservicegroup"><members><member>tcp-123</member><member>tcp-456</member></members></entry></service-group>
          </entry></device-group></entry></devices>
          <readonly><devices><entry name="localhost.localdomain"><device-group>
            <entry name="test_dg"><id>11</id></entry>
          </device-group></entry></devices></readonly>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)
        profilepackage = self.create_profilepackage(pan_config)

        _, _, validator_function = get_policy_validators()['ServicesShouldBeGroups']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        self.assertEqual(len(results[0].data), 3)
        self.assertEqual(results[0].data[0], 'SecurityPreRules')
        self.assertEqual(results[0].data[1].get('name'), 'sservices_can_be_group')
        self.assertEqual(results[0].data[2], "myservicegroup")
        self.assertEqual(results[0].device_group, 'test_dg')
def fix_bad_log_setting(profilepackage):
    panorama = profilepackage.settings.get("Panorama")
    api_key = profilepackage.api_key
    pan_config = profilepackage.pan_config
    version = pan_config.get_major_version()

    _, _, validator = get_policy_validators()['BadLogSetting']
    problems = validator(profilepackage)

    for problem in problems:
        entry = xml_object_to_dict(problem.data[0])['entry']
        ruletype = problem.entry_type
        device_group = problem.device_group
        entry["log-setting"] = problem.data[1]
        logger.debug(f"Updating {device_group}'s {ruletype} {problem.data[0].get('name')} log-setting to {entry['log-setting']}")
        pan_api.update_devicegroup_policy(panorama, version, api_key, entry, ruletype, device_group)

    return problems
def fix_bad_log_setting(profilepackage):
    panorama = profilepackage.settings.get("Panorama")
    api_key = profilepackage.api_key
    pan_config = profilepackage.pan_config
    version = pan_config.get_major_version()

    _, _, validator = get_policy_validators()['UnqualifiedFQDN']
    problems = validator(profilepackage)

    for problem in problems:
        entry = xml_object_to_dict(problem.data[0])['entry']
        object_type = problem.entry_type
        device_group = problem.device_group
        entry['fqdn'] = problem.data[1]
        pan_api.update_devicegroup_object(panorama, version, api_key, entry,
                                          object_type, device_group)

    return problems
 def test_equivalent_addresses(self):
     test_xml = """\
     <response status="success"><result><config>
       <shared>
         <address>
           <entry name="unique_netmask"><ip-netmask>ignored.tld</ip-netmask></entry>
           <entry name="dupe_netmask1"><ip-netmask>127.0.0.1</ip-netmask></entry>
           <entry name="dupe_netmask2"><ip-netmask>127.0.0.1/32</ip-netmask></entry>
           <entry name="dup_fqdn1"><fqdn>dupfqdn.tld</fqdn></entry>
           <entry name="dup_fqdn2"><fqdn>dupfqdn.tld</fqdn></entry>
         </address>
       </shared>
       <devices><entry><device-group><entry name="test_dg">
         <address>
           <entry name="unique_fqdn"><ip-netmask>unique.tld</ip-netmask></entry>
           <entry name="dup_fqdn3"><fqdn>dupfqdn.tld</fqdn></entry>
         </address>
       </entry></device-group></entry></devices>
     </config></result></response>
     """
     pan_config = PanConfig(test_xml)
     profilepackage = self.create_profilepackage('Addresses', pan_config)
     _, _, validator_function = get_policy_validators(
     )['EquivalentAddresses']
     results = validator_function(profilepackage)
     self.assertEqual(len(results), 3)
     self.assertEqual(len(results[0].data), 2)
     self.assertEqual(results[0].data[0][0], 'shared')
     self.assertEqual(results[0].data[0][1].get('name'), 'dup_fqdn1')
     self.assertEqual(results[0].data[1][0], 'shared')
     self.assertEqual(results[0].data[1][1].get('name'), 'dup_fqdn2')
     self.assertEqual(len(results[1].data), 2)
     self.assertEqual(results[1].data[0][0], 'shared')
     self.assertEqual(results[1].data[0][1].get('name'), 'dupe_netmask1')
     self.assertEqual(results[1].data[1][0], 'shared')
     self.assertEqual(results[1].data[1][1].get('name'), 'dupe_netmask2')
     self.assertEqual(len(results[2].data), 3)
     self.assertEqual(results[2].data[0][0], 'shared')
     self.assertEqual(results[2].data[0][1].get('name'), 'dup_fqdn1')
     self.assertEqual(results[2].data[1][0], 'shared')
     self.assertEqual(results[2].data[1][1].get('name'), 'dup_fqdn2')
     self.assertEqual(results[2].data[2][0], 'test_dg')
     self.assertEqual(results[2].data[2][1].get('name'), 'dup_fqdn3')
    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="same_zone_rule">
                <source>
                  <member>address_addressgroup1</member>
                  <member>ip-127.0.0.2</member>
                </source>
                <destination>
                  <member>ip-127.0.0.3</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>
            </address>
            <address-group>
              <entry name="address_addressgroup1"><static><member>ip-127.0.0.2</member></static></entry>
            </address-group>
          </entry></device-group></entry></devices>
          <readonly><devices><entry name="localhost.localdomain"><device-group>
            <entry name="test_dg"><id>11</id></entry>
          </device-group></entry></devices></readonly>
        </config></result></response>
        """
        pan_config = PanConfig(test_xml)

        profilepackage = self.create_profilepackage(pan_config)
        _, _, validator_function = get_policy_validators()['RedundantRuleAddresses']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 1)
        ruletype, rule_entry, members_to_remove = results[0].data
        self.assertEqual(ruletype, 'SecurityPreRules')
        self.assertEqual(rule_entry.get('name'), 'same_zone_rule')
        self.assertEqual(list(members_to_remove.keys()), ['source'])
        self.assertEqual(len(members_to_remove['source']), 1)
        member, containing = members_to_remove['source'][0]
        self.assertEqual(member, 'ip-127.0.0.2')
        self.assertEqual(containing, 'address_addressgroup1')
    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')
Ejemplo n.º 28
0
def fix_bad_log_setting(profilepackage):
    panorama = profilepackage.settings.get("Panorama")
    api_key = profilepackage.api_key
    pan_config = profilepackage.pan_config
    version = pan_config.get_major_version()

    _, _, validator = get_policy_validators()['IPWithResolvingFQDN']
    problems = validator(profilepackage)

    for problem in problems:
        object_type = problem.entry_type
        device_group = problem.device_group
        address_entry, fqdn = problem.data
        updated_object = xml_object_to_dict(address_entry)['entry']
        logger.debug(f"Updating {device_group} Address {address_entry.get('name')} from {updated_object['ip-netmask']} to {fqdn}")
        del updated_object['ip-netmask']
        updated_object['fqdn'] = fqdn
        pan_api.update_devicegroup_object(panorama, version, api_key, updated_object, object_type, device_group)

    return problems
 def test_without_mandated_logsetting(self):
     test_xml = """\
     <response status="success"><result><config>
       <devices><entry><device-group><entry name="test_dg">
         <pre-rulebase><security><rules>
           <entry name="disabled_rule"><disabled>yes</disabled></entry>
           <entry name="missing_log-setting"><disabled>no</disabled></entry>
           <entry name="correct_log-setting"><log-setting>correct</log-setting></entry>
           <entry name="wrong_log-setting"><log-setting>wrong</log-setting></entry>
         </rules></security></pre-rulebase>
       </entry></device-group></entry></devices>
     </config></result></response>
     """
     mandated_log_profile = None
     pan_config = PanConfig(test_xml)
     profilepackage = self.create_profilepackage(pan_config,
                                                 mandated_log_profile)
     _, _, validator_function = get_policy_validators()['BadLogSetting']
     results = validator_function(profilepackage)
     self.assertEqual(len(results), 0)
    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="disabled_rule"><disabled>yes</disabled></entry>
              <entry name="missing_gp"></entry>
              <entry name="correct_gp"><profile-setting><group><member>correct</member></group></profile-setting></entry>
              <entry name="wrong_gp"><profile-setting><group><member>wrong</member></group></profile-setting></entry>
            </rules></security></pre-rulebase>
          </entry></device-group></entry></devices>
        </config></result></response>
        """
        allowed_group_profile = 'correct'
        pan_config = PanConfig(test_xml)
        profilepackage = self.create_profilepackage(allowed_group_profile,
                                                    pan_config)

        _, _, validator_function = get_policy_validators()['BadGroupProfile']
        results = validator_function(profilepackage)
        self.assertEqual(len(results), 2)
        self.assertEqual(results[0].data.get('name'), 'missing_gp')
        self.assertEqual(results[1].data.get('name'), 'wrong_gp')