Example #1
0
    def _validate_network_policy_resources(self,
                                           name,
                                           uuid,
                                           spec={},
                                           validate_delete=False,
                                           namespace=None):

        ns_name = namespace if namespace else self.ns_name
        np_event_obj = NetworkPolicyKM.find_by_name_or_uuid(uuid)
        if validate_delete:
            self.assertIsNone(np_event_obj)
        elif not spec:
            fw_policy_uuid = VncSecurityPolicy.get_firewall_policy_uuid(
                name, ns_name)
            fw_policy = FirewallPolicyKM.locate(fw_policy_uuid)
            self.assertIsNotNone(np_event_obj)
            self.assertIsNone(fw_policy)
        else:
            fw_policy_uuid = VncSecurityPolicy.get_firewall_policy_uuid(
                name, ns_name)
            fw_policy = FirewallPolicyKM.locate(fw_policy_uuid)
            self.assertIsNotNone(np_event_obj)
            self.assertIsNotNone(fw_policy)

            # Validate network policy spec.
            self._validate_spec(spec, fw_policy)
    def add_firewall_rule(cls, fw_policy_uuid, fw_rule_uuid):

        try:
            fw_policy_obj = cls.vnc_lib.firewall_policy_read(id=fw_policy_uuid)
        except NoIdError:
            raise

        try:
            fw_rule_obj = cls.vnc_lib.firewall_rule_read(id=fw_rule_uuid)
        except NoIdError:
            raise

        last_entry_sequence = None
        rule_refs = fw_policy_obj.get_firewall_rule_refs()
        for rule in rule_refs if rule_refs else []:

            if fw_rule_uuid == rule['uuid']:
                return

            if last_entry_sequence < rule['attr'].get_sequence():
                last_entry_sequence = rule['attr'].get_sequence()

        # Start with presumption that this is the first.
        sequence = cls.construct_sequence_number('1.0')
        if last_entry_sequence:
            sequence = cls.construct_sequence_number(
                float(last_entry_sequence) + float('1.0'))

        fw_policy_obj.add_firewall_rule(fw_rule_obj, sequence)
        cls.vnc_lib.firewall_policy_update(fw_policy_obj)
        FirewallPolicyKM.locate(fw_policy_obj.get_uuid())
    def delete_firewall_rule(cls, fw_policy_uuid, fw_rule_uuid):

        # If policy or rule info is not provided, then there is nothing to do.
        if not fw_policy_uuid or not fw_rule_uuid:
            return

        try:
            fw_policy_obj = cls.vnc_lib.firewall_policy_read(id=fw_policy_uuid)
        except NoIdError:
            raise

        try:
            fw_rule_obj = cls.vnc_lib.firewall_rule_read(id=fw_rule_uuid)
        except NoIdError:
            return

        addr_grp_refs = fw_rule_obj.get_address_group_refs()

        fw_policy_obj.del_firewall_rule(fw_rule_obj)

        cls.vnc_lib.firewall_policy_update(fw_policy_obj)
        FirewallPolicyKM.locate(fw_policy_obj.get_uuid())

        # Delete the rule.
        cls.vnc_lib.firewall_rule_delete(id=fw_rule_uuid)

        # Try to delete address groups allocated for this FW rule.
        for addr_grp in addr_grp_refs if addr_grp_refs else []:
            FWRule.delete_address_group(addr_grp['uuid'])
    def delete_firewall_policy(cls, name, namespace, is_global=False):

        if not cls.cluster_aps_uuid:
            raise Exception("Cluster Application Policy Set not available.")

        # Get parent object for this firewall policy.
        aps_obj = cls.vnc_lib.application_policy_set_read(
            id=cls.cluster_aps_uuid)

        try:
            pm_obj = cls.vnc_lib.policy_management_read(
                fq_name=aps_obj.get_parent_fq_name())
        except NoIdError:
            raise
        fw_policy_fq_name = pm_obj.get_fq_name() +\
            [cls.get_firewall_policy_name(name, namespace, is_global)]
        fw_policy_uuid = FirewallPolicyKM.get_fq_name_to_uuid(
            fw_policy_fq_name)

        if not fw_policy_uuid:
            # We are not aware of this firewall policy.
            return

        fw_policy = FirewallPolicyKM.locate(fw_policy_uuid)
        fw_policy_rules = fw_policy.firewall_rules

        # Remove deny all firewall rule, if any.
        if fw_policy.deny_all_rule_uuid:
            VncSecurityPolicy.delete_firewall_rule(
                VncSecurityPolicy.deny_all_fw_policy_uuid,
                fw_policy.deny_all_rule_uuid)

        # Remove egress deny all firewall rule, if any.
        if fw_policy.egress_deny_all_rule_uuid:
            VncSecurityPolicy.delete_firewall_rule(
                VncSecurityPolicy.deny_all_fw_policy_uuid,
                fw_policy.egress_deny_all_rule_uuid)

        for rule_uuid in fw_policy_rules:
            try:
                VncSecurityPolicy.delete_firewall_rule(fw_policy_uuid,
                                                       rule_uuid)
            except:
                raise

        cls.remove_firewall_policy(name, namespace)
        try:
            cls.vnc_lib.firewall_policy_delete(id=fw_policy_uuid)
            FirewallPolicyKM.delete(fw_policy_uuid)
        except:
            raise
    def remove_firewall_policy(cls, name, namespace, is_global=False):
        if not cls.cluster_aps_uuid:
            raise Exception("Cluster Application Policy Set not available.")

        aps_obj = cls.vnc_lib.application_policy_set_read(
            id=cls.cluster_aps_uuid)

        try:
            pm_obj = cls.vnc_lib.policy_management_read(
                fq_name=aps_obj.get_parent_fq_name())
        except NoIdError:
            raise

        fw_policy_fq_name = pm_obj.get_fq_name() +\
            [cls.get_firewall_policy_name(name, namespace, is_global)]

        fw_policy_uuid = FirewallPolicyKM.get_fq_name_to_uuid(
            fw_policy_fq_name)

        if not fw_policy_uuid:
            # We are not aware of this firewall policy.
            return

        try:
            fw_policy_obj = cls.vnc_lib.firewall_policy_read(id=fw_policy_uuid)
        except NoIdError:
            raise

        aps_obj.del_firewall_policy(fw_policy_obj)
        cls.vnc_lib.application_policy_set_update(aps_obj)
Example #6
0
    def get_firewall_policy_rule_uuid(cls, name, namespace, is_global=False):

        if not cls.cluster_aps_uuid:
            raise Exception("Cluster Application Policy Set not available.")
        aps = ApplicationPolicySetKM.locate(cls.cluster_aps_uuid)
        pm = PolicyManagementKM.locate(aps.parent_uuid)
        fw_policy_fq_name = pm.fq_name +\
            [cls.get_firewall_policy_name(name, namespace, is_global)]
        fw_policy_uuid = FirewallPolicyKM.get_fq_name_to_uuid(fw_policy_fq_name)
        return fw_policy_uuid
    def _validate_network_policy_resources(self, name, uuid, spec={},
                                           validate_delete=False,
                                           namespace=None):

        ns_name = namespace if namespace else self.ns_name
        np_event_obj = NetworkPolicyKM.find_by_name_or_uuid(uuid)
        if validate_delete:
            self.assertIsNone(np_event_obj)
        elif not spec:
            fw_policy_uuid = VncSecurityPolicy.get_firewall_policy_uuid(name,
                                                                       ns_name)
            fw_policy = FirewallPolicyKM.locate(fw_policy_uuid)
            self.assertIsNotNone(np_event_obj)
            self.assertIsNone(fw_policy)
        else:
            fw_policy_uuid = VncSecurityPolicy.get_firewall_policy_uuid(name,
                                                                       ns_name)
            fw_policy = FirewallPolicyKM.locate(fw_policy_uuid)
            self.assertIsNotNone(np_event_obj)
            self.assertIsNotNone(fw_policy)

            # Validate network policy spec.
            self._validate_spec(spec, fw_policy)
    def _create_network_policy_delete_event(self, fw_policy_uuid):
        """
        Self-create a network policy delete event.
        """
        event = {}
        object_ = {}
        event['type'] = 'DELETED'
        object_['kind'] = 'NetworkPolicy'
        object_['metadata'] = {}

        fw_policy = FirewallPolicyKM.find_by_name_or_uuid(fw_policy_uuid)
        object_['metadata']['uid'] = fw_policy.k8s_uuid
        object_['metadata']['name'] = fw_policy.k8s_name
        object_['metadata']['namespace'] = fw_policy.k8s_namespace

        event['object'] = object_
        self._queue.put(event)
        return
Example #9
0
    def test_periodic_validate_with_user_policies(self):
        """
        Validate network policy periodic self-healing when
        multiple user created policies are present.
        """

        np_uuid_dict = {}
        test_range = list(range(1, 10))
        for i in test_range:
            np_spec = {'podSelector': {}, 'ingress': [{}]}
            np_name = "-".join([unittest.TestCase.id(self), str(i)])
            np_uuid_dict[i] = self._add_update_network_policy(np_name, np_spec)
            self._validate_network_policy_resources(np_name, np_uuid_dict[i],
                                                    np_spec)

        # Check if we have a valid config to start with.
        valid = VncSecurityPolicy.validate_cluster_security_policy()
        self.assertTrue(valid)

        # Get some basic object handles.
        self.assertIsNotNone(VncSecurityPolicy.allow_all_fw_policy_uuid)
        fw_policy_obj = self._vnc_lib.firewall_policy_read(
            id=VncSecurityPolicy.allow_all_fw_policy_uuid)
        aps_obj = self._get_default_application_policy_set()
        self.assertIsNotNone(fw_policy_obj)
        self.assertIsNotNone(aps_obj)

        # Detach allow-all policy from APS to introduce error.
        aps_obj.del_firewall_policy(fw_policy_obj)
        self._vnc_lib.application_policy_set_update(aps_obj)

        # Verify that validation of APS will fail.
        valid = VncSecurityPolicy.validate_cluster_security_policy()
        self.assertFalse(valid)

        # Fix the inconsisteny in APS.
        VncSecurityPolicy.recreate_cluster_security_policy()

        # Verify that validation of APS will succeed now.
        valid = VncSecurityPolicy.validate_cluster_security_policy()
        self.assertTrue(valid)

        #
        # After self-healing, verify that the first on the APS, the FW policies
        # are ordered as follows:
        # - Ingress-svc fw policy
        # - User created policies
        # - Deny-all fw policy
        # - Allow-all fw policy
        #
        previous_sequence = None
        aps = ApplicationPolicySetKM.locate(aps_obj.get_uuid())
        aps.update()

        fw_policy_refs = aps.get_firewall_policy_refs_sorted()
        ingress_fw_policy_idx = None
        for index, fw_policy_ref in enumerate(fw_policy_refs):
            fw_policy = FirewallPolicyKM.locate(fw_policy_ref['uuid'])
            if fw_policy.owner and\
               fw_policy.cluster_name == self.cluster_name():
                self.assertTrue(fw_policy.uuid ==
                                VncSecurityPolicy.ingress_svc_fw_policy_uuid)
                ingress_fw_policy_idx = index
                break

        last_user_policy_index = None
        loop_start_index = ingress_fw_policy_idx + 1
        for i in test_range:
            np_name = "-".join([unittest.TestCase.id(self), str(i)])
            fw_policy_name = VncSecurityPolicy.get_firewall_policy_name(
                np_name, self.ns_name, False)
            for index, fw_policy in enumerate(
                    fw_policy_refs[loop_start_index:]):
                if fw_policy_name == fw_policy['to'][-1]:
                    if previous_sequence:
                        self.assertTrue(previous_sequence < \
                           fw_policy['attr']['sequence'])
                    previous_sequence = fw_policy['attr']['sequence']
                    last_user_policy_index = loop_start_index + index
                    break

        deny_all_policy_index = None
        loop_start_index = last_user_policy_index + 1
        for index, fw_policy_ref in enumerate(
                fw_policy_refs[loop_start_index:]):
            fw_policy = FirewallPolicyKM.locate(fw_policy_ref['uuid'])
            if fw_policy.cluster_name and\
               fw_policy.cluster_name == self.cluster_name():
                self.assertTrue(fw_policy.uuid ==
                                VncSecurityPolicy.deny_all_fw_policy_uuid)
                deny_all_policy_index = loop_start_index + index
                break

        loop_start_index = deny_all_policy_index + 1
        for fw_policy_ref in fw_policy_refs[loop_start_index:]:
            fw_policy = FirewallPolicyKM.locate(fw_policy_ref['uuid'])
            if fw_policy.cluster_name and\
               fw_policy.cluster_name == self.cluster_name():
                self.assertTrue(fw_policy.uuid ==
                                VncSecurityPolicy.allow_all_fw_policy_uuid)
                break

        for i in test_range:
            self._delete_network_policy(unittest.TestCase.id(self),
                                        np_uuid_dict[i])
            self._validate_network_policy_resources(np_name,
                                                    np_uuid_dict[i],
                                                    np_spec,
                                                    validate_delete=True)
    def create_firewall_policy(cls,
                               name,
                               namespace,
                               spec,
                               tag_last=False,
                               is_global=False,
                               k8s_uuid=None):

        if not cls.cluster_aps_uuid:
            raise Exception("Cluster Application Policy Set not available.")

        # Get parent object for this firewall policy.
        aps_obj = cls.vnc_lib.application_policy_set_read(
            id=cls.cluster_aps_uuid)

        try:
            pm_obj = cls.vnc_lib.policy_management_read(
                fq_name=aps_obj.get_parent_fq_name())
        except NoIdError:
            raise

        fw_policy_obj = FirewallPolicy(
            cls.get_firewall_policy_name(name, namespace, is_global), pm_obj)

        custom_ann_kwargs = {}
        custom_ann_kwargs['k8s_uuid'] = k8s_uuid
        curr_fw_policy = None
        fw_rules_del_candidates = set()

        # If this firewall policy already exists, get its uuid.
        fw_policy_uuid = VncSecurityPolicy.get_firewall_policy_uuid(
            name, namespace, is_global)
        if fw_policy_uuid:
            #
            # FW policy exists.
            # Check for modidifcation to its spec.
            # If not modifications are found, return the uuid of policy.
            #
            curr_fw_policy = FirewallPolicyKM.locate(fw_policy_uuid)
            if curr_fw_policy and curr_fw_policy.spec:
                if curr_fw_policy.spec == json.dumps(spec):
                    # Input spec is same as existing spec. Nothing to do.
                    # Just return the uuid.
                    return fw_policy_uuid

                # Get the current firewall rules on this policy.
                # All rules are delete candidates as any of them could have
                # changed.
                fw_rules_del_candidates = curr_fw_policy.firewall_rules

        # Annotate the FW policy object with input spec.
        # This will be used later to identify and validate subsequent modify
        # or add (i.e post restart) events.
        custom_ann_kwargs['spec'] = json.dumps(spec)

        # Check if we are being asked to place this firewall policy in the end
        # of fw policy list in its Application Policy Set.
        # If yes, tag accordingly.
        if tag_last:
            custom_ann_kwargs['tail'] = "True"

        # Parse input spec and construct the list of rules for this FW policy.
        fw_rules = []
        deny_all_rule_uuid = None
        egress_deny_all_rule_uuid = None

        if spec is not None:
            fw_rules, deny_all_rule_uuid, egress_deny_all_rule_uuid =\
                FWRule.parser(name, namespace, pm_obj, spec)

        for rule in fw_rules:
            try:
                rule_uuid = cls.vnc_lib.firewall_rule_create(rule)
            except RefsExistError:
                cls.vnc_lib.firewall_rule_update(rule)
                rule_uuid = rule.get_uuid()

                # The rule is in use and needs to stay.
                # Remove it from delete candidate collection.
                if fw_rules_del_candidates and\
                   rule_uuid in fw_rules_del_candidates:
                    fw_rules_del_candidates.remove(rule_uuid)

            rule_obj = cls.vnc_lib.firewall_rule_read(id=rule_uuid)
            FirewallRuleKM.locate(rule_uuid)

            fw_policy_obj.add_firewall_rule(
                rule_obj, cls.construct_sequence_number(fw_rules.index(rule)))

        if deny_all_rule_uuid:
            VncSecurityPolicy.add_firewall_rule(
                VncSecurityPolicy.deny_all_fw_policy_uuid, deny_all_rule_uuid)
            custom_ann_kwargs['deny_all_rule_uuid'] = deny_all_rule_uuid

        if egress_deny_all_rule_uuid:
            VncSecurityPolicy.add_firewall_rule(
                VncSecurityPolicy.deny_all_fw_policy_uuid,
                egress_deny_all_rule_uuid)
            custom_ann_kwargs['egress_deny_all_rule_uuid'] =\
                egress_deny_all_rule_uuid

        FirewallPolicyKM.add_annotations(
            VncSecurityPolicy.vnc_security_policy_instance, fw_policy_obj,
            namespace, name, None, **custom_ann_kwargs)

        try:
            fw_policy_uuid = cls.vnc_lib.firewall_policy_create(fw_policy_obj)
        except RefsExistError:

            # Remove existing firewall rule refs on this fw policy.
            # Once existing firewall rules are remove, firewall policy will
            # be updated with rules correspoinding to current input spec.
            for rule in fw_rules_del_candidates:
                cls.delete_firewall_rule(fw_policy_uuid, rule)

            cls.vnc_lib.firewall_policy_update(fw_policy_obj)
            fw_policy_uuid = fw_policy_obj.get_uuid()

        fw_policy_obj = cls.vnc_lib.firewall_policy_read(id=fw_policy_uuid)
        FirewallPolicyKM.locate(fw_policy_uuid)

        return fw_policy_uuid
    def sync_cluster_security_policy(cls):
        """
        Synchronize K8s network policies with Contrail Security policy.
        Expects that FW policies on the APS are in proper order.

        Returns a list of orphaned or invalid firewall policies.
        """

        # If APS does not exist for this cluster, then there is nothing to do.
        if not cls.cluster_aps_uuid:
            return []

        aps = ApplicationPolicySetKM.find_by_name_or_uuid(cls.cluster_aps_uuid)
        if not aps:
            return []

        # If APS does not match this cluster name, then there is nothing to do.
        if aps.name != vnc_kube_config.cluster_name():
            return []

        # Get the current list of firewall policies on the APS.
        fw_policy_uuids = aps.get_firewall_policies()

        # Construct list of firewall policies that belong to the cluster.
        cluster_firewall_policies = []
        for fw_policy_uuid in fw_policy_uuids:
            fw_policy = FirewallPolicyKM.find_by_name_or_uuid(fw_policy_uuid)
            if fw_policy.cluster_name != vnc_kube_config.cluster_name():
                continue
            cluster_firewall_policies.append(fw_policy_uuid)

        # We are interested only in policies created by k8s user via network
        # policy. These policies are sequenced between the infra created ingress
        # policy and infra created deny-all policy.
        try:
            start_index = cluster_firewall_policies.index(
                cls.ingress_svc_fw_policy_uuid)
            end_index = cluster_firewall_policies.index(
                cls.deny_all_fw_policy_uuid)
            curr_user_firewall_policies =\
                          cluster_firewall_policies[start_index+1:end_index]
        except ValueError:
            return []

        # Get list of user created network policies.
        configured_network_policies = NetworkPolicyKM.get_configured_policies()
        for nw_policy_uuid in configured_network_policies:

            np = NetworkPolicyKM.find_by_name_or_uuid(nw_policy_uuid)
            if not np or not np.get_vnc_fq_name():
                continue

            # Decipher the firewall policy corresponding to the network policy.
            fw_policy_uuid = FirewallPolicyKM.get_fq_name_to_uuid(
                np.get_vnc_fq_name().split(":"))
            if not fw_policy_uuid:
                # We are yet to process this network policy.
                continue

            # A firewall policy was found but it is not inbetween the infra
            # created policies as expected. Add it again so it will be inserted
            # in the right place.
            if fw_policy_uuid not in curr_user_firewall_policies:
                cls.add_firewall_policy(fw_policy_uuid)
            else:
                # Filter out processed policies.
                curr_user_firewall_policies.remove(fw_policy_uuid)

        # Return orphaned firewall policies that could not be validated against
        # user created network policy.
        headless_fw_policy_uuids = curr_user_firewall_policies

        return headless_fw_policy_uuids
    def recreate_cluster_security_policy(cls):

        # If APS does not exist for this cluster, then there is nothing to do.
        if not cls.cluster_aps_uuid:
            return

        aps = ApplicationPolicySetKM.find_by_name_or_uuid(cls.cluster_aps_uuid)

        # If APS does not match this cluster name, then there is nothing to do.
        if aps.name != vnc_kube_config.cluster_name():
            return

        # Update the APS, so we have the latest state.
        aps_obj = cls.vnc_lib.application_policy_set_read(
            id=cls.cluster_aps_uuid)
        aps.update()

        vnc_kube_config.logger().debug(
            "%s - Remove existing firewall policies of cluster from APS [%s]"\
            %(cls.name, aps.name))

        # To begin with, remove all existing firewall policies of this cluster
        # from the APS.
        fw_policy_uuids = aps.get_firewall_policies()
        removed_firewall_policies = []
        for fw_policy_uuid in fw_policy_uuids if fw_policy_uuids else []:
            fw_policy = FirewallPolicyKM.find_by_name_or_uuid(fw_policy_uuid)

            # Filter out policies not owned by this cluster.
            if fw_policy.cluster_name != vnc_kube_config.cluster_name():
                continue

            # De-link the firewall policy from APS.
            try:
                fw_policy_obj = cls.vnc_lib.firewall_policy_read(
                    id=fw_policy_uuid)
            except NoIdError:
                raise
            aps_obj.del_firewall_policy(fw_policy_obj)
            removed_firewall_policies.append(fw_policy_uuid)

        # If we need to remove some policies, update the object accordingly.
        if removed_firewall_policies:
            cls.vnc_lib.application_policy_set_update(aps_obj)
            aps.update()

        # Derive the sequence number we can use to start recreating firewall
        # policies. If there are existing policies that dont belong and are
        # not managed by the cluster, recreate the cluster firewall policies
        # to the tail.
        fw_policy_refs = aps.get_firewall_policy_refs_sorted()

        # Lets begin with the assumption that we are the first policy.
        sequence = cls.construct_sequence_number('1.0')
        if fw_policy_refs:
            # Get the sequence number of the last policy on this APS.
            last_entry_sequence = fw_policy_refs[-1]['attr'].get_sequence()
            # Construct the next sequence number to use.
            sequence = cls.construct_sequence_number(
                float(last_entry_sequence) + float('1.0'))

        # Filter our infra created firewall policies.
        try:
            removed_firewall_policies.remove(cls.ingress_svc_fw_policy_uuid)
        except ValueError:
            pass

        try:
            removed_firewall_policies.remove(cls.deny_all_fw_policy_uuid)
        except ValueError:
            pass

        try:
            removed_firewall_policies.remove(cls.allow_all_fw_policy_uuid)
        except ValueError:
            pass

        # Reconstruct the policies in the order we want them to be.
        add_firewall_policies = [cls.ingress_svc_fw_policy_uuid] +\
                                removed_firewall_policies+\
                                [cls.deny_all_fw_policy_uuid]+\
                                [cls.allow_all_fw_policy_uuid]

        # Attach the policies to the APS.
        for fw_policy_uuid in add_firewall_policies:
            vnc_kube_config.logger().debug(
                "%s - Recreate  FW policy [%s] on APS [%s] at sequence [%s]"\
                %(cls.name, fw_policy_uuid, aps.name, sequence.get_sequence()))
            try:
                fw_policy_obj = cls.vnc_lib.firewall_policy_read(
                    id=fw_policy_uuid)
            except NoIdError:
                raise
            aps_obj.add_firewall_policy(fw_policy_obj, sequence)
            sequence = cls.construct_sequence_number(
                float(sequence.get_sequence()) + float('1.0'))

        # Update the APS.
        cls.vnc_lib.application_policy_set_update(aps_obj)
    def validate_cluster_security_policy(cls):

        # If APS does not exist for this cluster, then there is nothing to do.
        if not cls.cluster_aps_uuid:
            return True

        aps = ApplicationPolicySetKM.find_by_name_or_uuid(cls.cluster_aps_uuid)

        # If we are not able to local APS in cache, then there is nothing to do.
        if not aps:
            return True

        # If APS does not match this cluster name, then there is nothing to do.
        if aps.name != vnc_kube_config.cluster_name():
            return True

        # Update the APS, so we have the latest state.
        aps.update()
        fw_policy_uuids = aps.get_firewall_policies()

        # If there are no firewall policies on this APS yet, there is nothing
        # to verify.
        if not fw_policy_uuids:
            if cls.ingress_svc_fw_policy_uuid and\
               cls.deny_all_fw_policy_uuid and\
               cls.allow_all_fw_policy_uuid:
                return False
            else:
                return True

        # Validate that ingress firewall policy is the first policy of the
        # cluster owned firewall policies in the APS.
        if cls.ingress_svc_fw_policy_uuid:
            for fw_policy_uuid in fw_policy_uuids:
                fw_policy = FirewallPolicyKM.find_by_name_or_uuid(
                    fw_policy_uuid)
                if not fw_policy:
                    continue

                # Filter out policies not owned by this cluster.
                if fw_policy.cluster_name != vnc_kube_config.cluster_name():
                    continue

                # The first policy to reach here should be ingress policy.
                # Else return validation failure.
                if cls.ingress_svc_fw_policy_uuid == fw_policy_uuid:
                    break

                vnc_kube_config.logger().error(
                 "%s - Ingress FW Policy [%s] not the first policy on APS [%s]"\
                     %(cls.name, cls.ingress_svc_fw_policy_uuid, aps.name))
                return False

        # Validate that deny and allow policies of this cluster are found on
        # on this APS.
        # The allow policy should follow the deny policy.
        deny_all_fw_policy_index = None
        allow_all_fw_policy_index = None
        if cls.deny_all_fw_policy_uuid and cls.allow_all_fw_policy_uuid:
            for index, fw_policy_uuid in enumerate(fw_policy_uuids):
                fw_policy = FirewallPolicyKM.find_by_name_or_uuid(
                    fw_policy_uuid)
                if not fw_policy:
                    continue

                # Filter out policies not owned by this cluster.
                if fw_policy.cluster_name != vnc_kube_config.cluster_name():
                    continue

                # Allow policy should follow the deny policy.
                # If not, return validation failure.
                if deny_all_fw_policy_index:
                    if cls.allow_all_fw_policy_uuid == fw_policy_uuid:
                        allow_all_fw_policy_index = index
                        break
                elif cls.deny_all_fw_policy_uuid == fw_policy_uuid:
                    deny_all_fw_policy_index = index

        # If we are unable to locate deny or allow policy, return validation
        # failure.
        if not deny_all_fw_policy_index or not allow_all_fw_policy_index:
            if cls.deny_all_fw_policy_uuid and not deny_all_fw_policy_index:
                vnc_kube_config.logger().error(
                    "%s - deny-all FW Policy [%s] not found on APS [%s]"\
                     %(cls.name, cls.deny_all_fw_policy_uuid, aps.name))

            if cls.allow_all_fw_policy_uuid and not allow_all_fw_policy_index:
                vnc_kube_config.logger().error(
                    "%s - allow-all FW Policy [%s] not found (or not found"\
                    " after deny-all policy) on APS [%s]"\
                     %(cls.name, cls.allow_all_fw_policy_uuid, aps.name))
            return False

        # Validation succeeded. All is well.
        return True
    def test_periodic_validate_with_user_policies(self):
        """
        Validate network policy periodic self-healing when
        multiple user created policies are present.
        """

        np_uuid_dict={}
        test_range = range(1, 10)
        for i in test_range:
            np_spec = {
                      'podSelector': {},
                      'ingress': [{}]
                  }
            np_name = "-".join([unittest.TestCase.id(self), str(i)])
            np_uuid_dict[i] = self._add_update_network_policy(np_name, np_spec)
            self._validate_network_policy_resources(np_name, np_uuid_dict[i],
                                                    np_spec)

        # Check if we have a valid config to start with.
        valid = VncSecurityPolicy.validate_cluster_security_policy()
        self.assertTrue(valid)

        # Get some basic object handles.
        self.assertIsNotNone(VncSecurityPolicy.allow_all_fw_policy_uuid)
        fw_policy_obj = self._vnc_lib.firewall_policy_read(
            id=VncSecurityPolicy.allow_all_fw_policy_uuid)
        aps_obj = self._get_default_application_policy_set()
        self.assertIsNotNone(fw_policy_obj)
        self.assertIsNotNone(aps_obj)

        # Detach allow-all policy from APS to introduce error.
        aps_obj.del_firewall_policy(fw_policy_obj)
        self._vnc_lib.application_policy_set_update(aps_obj)

        # Verify that validation of APS will fail.
        valid = VncSecurityPolicy.validate_cluster_security_policy()
        self.assertFalse(valid)

        # Fix the inconsisteny in APS.
        VncSecurityPolicy.recreate_cluster_security_policy()

        # Verify that validation of APS will succeed now.
        valid = VncSecurityPolicy.validate_cluster_security_policy()
        self.assertTrue(valid)

        #
        # After self-healing, verify that the first on the APS, the FW policies
        # are ordered as follows:
        # - Ingress-svc fw policy
        # - User created policies
        # - Deny-all fw policy
        # - Allow-all fw policy
        #
        previous_sequence = None
        aps = ApplicationPolicySetKM.locate(aps_obj.get_uuid())
        aps.update()

        fw_policy_refs = aps.get_firewall_policy_refs_sorted()
        ingress_fw_policy_idx = None
        for index, fw_policy_ref in enumerate(fw_policy_refs):
            fw_policy = FirewallPolicyKM.locate(fw_policy_ref['uuid'])
            if fw_policy.owner and\
               fw_policy.cluster_name == self.cluster_name():
               self.assertTrue(fw_policy.uuid == VncSecurityPolicy.ingress_svc_fw_policy_uuid)
               ingress_fw_policy_idx = index
               break

        last_user_policy_index = None
        loop_start_index = ingress_fw_policy_idx+1
        for i in test_range:
            np_name = "-".join([unittest.TestCase.id(self), str(i)])
            fw_policy_name = VncSecurityPolicy.get_firewall_policy_name(np_name,
                self.ns_name, False)
            for index, fw_policy in enumerate(fw_policy_refs[loop_start_index:]):
                if fw_policy_name == fw_policy['to'][-1]:
                    if previous_sequence:
                        self.assertTrue(previous_sequence < \
                           fw_policy['attr']['sequence'])
                    previous_sequence = fw_policy['attr']['sequence']
                    last_user_policy_index = loop_start_index + index
                    break

        deny_all_policy_index = None
        loop_start_index = last_user_policy_index + 1
        for index, fw_policy_ref in enumerate(fw_policy_refs[loop_start_index:]):
            fw_policy = FirewallPolicyKM.locate(fw_policy_ref['uuid'])
            if fw_policy.cluster_name and\
               fw_policy.cluster_name == self.cluster_name():
               self.assertTrue(fw_policy.uuid == VncSecurityPolicy.deny_all_fw_policy_uuid)
               deny_all_policy_index = loop_start_index + index
               break

        loop_start_index = deny_all_policy_index + 1
        for fw_policy_ref in fw_policy_refs[loop_start_index:]:
            fw_policy = FirewallPolicyKM.locate(fw_policy_ref['uuid'])
            if fw_policy.cluster_name and\
               fw_policy.cluster_name == self.cluster_name():
               self.assertTrue(fw_policy.uuid == VncSecurityPolicy.allow_all_fw_policy_uuid)
               break

        for i in test_range:
            self._delete_network_policy(unittest.TestCase.id(self), np_uuid_dict[i])
            self._validate_network_policy_resources(np_name, np_uuid_dict[i],
                np_spec, validate_delete=True)
Example #15
0
    def create_firewall_policy(cls, name, namespace, spec, tag_last=False,
                               is_global=False):

        if not cls.cluster_aps_uuid:
            raise Exception("Cluster Application Policy Set not available.")

        # Get parent object for this firewall policy.
        aps_obj = cls.vnc_lib.application_policy_set_read(
            id=cls.cluster_aps_uuid)

        try:
            pm_obj = cls.vnc_lib.policy_management_read(
                fq_name=aps_obj.get_parent_fq_name())
        except NoIdError:
            raise

        fw_policy_obj = FirewallPolicy(
            cls.get_firewall_policy_name(name, namespace, is_global), pm_obj)

        custom_ann_kwargs = {}
        if tag_last:
            custom_ann_kwargs['tail'] = "True"

        # Parse input spec and construct the list of rules for this FW policy.
        fw_rules = []
        deny_all_rule_uuid = None
        if spec is not None:
            fw_rules, deny_all_rule_uuid = FWRule.parser(name, namespace,
                                                         pm_obj, spec)

        for rule in fw_rules:
            try:
                rule_uuid = cls.vnc_lib.firewall_rule_create(rule)
            except RefsExistError:
                cls.vnc_lib.firewall_rule_update(rule)
                rule_uuid = rule.get_uuid()
            rule_obj = cls.vnc_lib.firewall_rule_read(id=rule_uuid)
            FirewallRuleKM.locate(rule_uuid)
            #FirewallSequence(
            #    sequence=cls.construct_sequence_number(fw_rules.index(rule)))

            fw_policy_obj.add_firewall_rule(rule_obj,
                cls.construct_sequence_number(fw_rules.index(rule)))

        if deny_all_rule_uuid:
            VncSecurityPolicy.add_firewall_rule(
                VncSecurityPolicy.deny_all_fw_policy_uuid, deny_all_rule_uuid)
            custom_ann_kwargs['deny_all_rule_uuid'] = deny_all_rule_uuid

        FirewallPolicyKM.add_annotations(
            VncSecurityPolicy.vnc_security_policy_instance,
            fw_policy_obj, namespace, name, None, **custom_ann_kwargs)

        try:
            fw_policy_uuid = cls.vnc_lib.firewall_policy_create(fw_policy_obj)
        except RefsExistError:
            cls.vnc_lib.firewall_policy_update(fw_policy_obj)
            fw_policy_uuid = fw_policy_obj.get_uuid()
        fw_policy_obj = cls.vnc_lib.firewall_policy_read(id=fw_policy_uuid)

        FirewallPolicyKM.locate(fw_policy_uuid)

        return fw_policy_uuid