Exemple #1
0
def _parse_selectors_on_namespace(crd, direction, pod_selector, ns_selector,
                                  rule_block, crd_rules, namespace, matched):
    ns_name = namespace['metadata'].get('name')
    ns_labels = namespace['metadata'].get('labels')
    sg_id = crd['spec']['securityGroupId']

    if (ns_selector and ns_labels
            and driver_utils.match_selector(ns_selector, ns_labels)):
        if pod_selector:
            pods = driver_utils.get_pods(pod_selector, ns_name).get('items')
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = (_create_sg_rule_on_text_port(
                            sg_id, direction, port, pods, crd_rules, matched,
                            crd))
                    else:
                        matched = True
                        for pod in pods:
                            pod_ip = driver_utils.get_pod_ip(pod)
                            crd_rules.append(
                                _create_sg_rule(sg_id,
                                                direction,
                                                pod_ip,
                                                port=port,
                                                namespace=ns_name))
            else:
                for pod in pods:
                    pod_ip = driver_utils.get_pod_ip(pod)
                    matched = True
                    crd_rules.append(
                        _create_sg_rule(sg_id,
                                        direction,
                                        pod_ip,
                                        namespace=ns_name))
        else:
            ns_pods = driver_utils.get_pods(ns_selector)
            ns_cidr = driver_utils.get_namespace_subnet_cidr(namespace)
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = (_create_sg_rule_on_text_port(
                            sg_id, direction, port, ns_pods, crd_rules,
                            matched, crd))
                    else:
                        matched = True
                        crd_rules.append(
                            _create_sg_rule(sg_id,
                                            direction,
                                            ns_cidr,
                                            port=port,
                                            namespace=ns_name))
            else:
                matched = True
                crd_rules.append(
                    _create_sg_rule(sg_id,
                                    direction,
                                    ns_cidr,
                                    namespace=ns_name))
    return matched, crd_rules
def _get_pod_sgs(pod, project_id):
    sg_list = []

    pod_labels = pod['metadata'].get('labels')
    pod_namespace = pod['metadata']['namespace']

    knp_crds = driver_utils.get_kuryrnetpolicy_crds(namespace=pod_namespace)
    for crd in knp_crds.get('items'):
        pod_selector = crd['spec'].get('podSelector')
        if pod_selector:
            if driver_utils.match_selector(pod_selector, pod_labels):
                LOG.debug("Appending %s", str(crd['spec']['securityGroupId']))
                sg_list.append(str(crd['spec']['securityGroupId']))
        else:
            LOG.debug("Appending %s", str(crd['spec']['securityGroupId']))
            sg_list.append(str(crd['spec']['securityGroupId']))

    # NOTE(maysams) Pods that are not selected by any Networkpolicy
    # are fully accessible. Thus, the default security group is associated.
    if not sg_list:
        sg_list = config.CONF.neutron_defaults.pod_security_groups
        if not sg_list:
            raise cfg.RequiredOptError('pod_security_groups',
                                       cfg.OptGroup('neutron_defaults'))

    return sg_list[:]
 def _create_sg_rules_with_container_ports(
     self, container_ports, allow_all, resource, matched_pods,
         crd_rules, direction, port, pod_selector=None,
         policy_namespace=None):
     cidr, ns = self._get_resource_details(resource)
     for pod, container_port in container_ports:
         pod_label = pod['metadata'].get('labels')
         pod_ip = pod['status'].get('podIP')
         pod_namespace = pod['metadata']['namespace']
         pod_info = {pod_ip: pod_namespace}
         # NOTE(maysams) Avoid to take into account pods that are also
         # matched by NetworkPolicySpec's podSelector. This way we do
         # not allow egress traffic to the actual set of pods the NP
         # is enforced on.
         if (direction == 'egress' and
             (driver_utils.match_selector(pod_selector, pod_label) and
              policy_namespace == pod_namespace)):
             continue
         if container_port in matched_pods:
             matched_pods[container_port].update(pod_info)
         else:
             matched_pods[container_port] = pod_info
     if not allow_all and matched_pods and cidr:
         for container_port, pods in matched_pods.items():
             sg_rule = driver_utils.create_security_group_rule_body(
                 direction, container_port,
                 protocol=port.get('protocol'),
                 cidr=cidr, pods=pods)
             if sg_rule not in crd_rules:
                 crd_rules.append(sg_rule)
             if direction == 'egress':
                 self._create_svc_egress_sg_rule(
                     policy_namespace, crd_rules,
                     resource=resource, port=container_port,
                     protocol=port.get('protocol'))
def _create_sg_rules(crd, pod, pod_selector, rule_block, direction, matched):
    pod_labels = pod['metadata'].get('labels')
    pod_ip = driver_utils.get_pod_ip(pod)
    if not pod_ip:
        LOG.debug(
            "Skipping SG rule creation for pod %s due to "
            "no IP assigned", pod['metadata']['name'])
        return None

    # NOTE (maysams) No need to differentiate between podSelector
    # with empty value or with '{}', as they have same result in here.
    if pod_selector:
        if driver_utils.match_selector(pod_selector, pod_labels):
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = _create_sg_rule_on_text_port(
                            direction, port, [pod], matched, crd)
                    else:
                        matched = True
            else:
                matched = True
    else:
        # NOTE (maysams) When a policy with namespaceSelector and text port
        # is applied the port on the pods needs to be retrieved.
        if 'ports' in rule_block:
            for port in rule_block['ports']:
                if type(port.get('port')) is not int:
                    matched = _create_sg_rule_on_text_port(
                        direction, port, [pod], matched, crd)
    return matched
def _get_pod_sgs(pod):
    sg_list = []

    pod_labels = pod['metadata'].get('labels')
    pod_namespace = pod['metadata']['namespace']

    knp_crds = driver_utils.get_kuryrnetworkpolicy_crds(
        namespace=pod_namespace)
    for crd in knp_crds:
        pod_selector = crd['spec'].get('podSelector')
        if driver_utils.match_selector(pod_selector, pod_labels):
            sg_id = crd['status'].get('securityGroupId')
            if not sg_id:
                # NOTE(dulek): We could just assume KNP handler will apply it,
                #              but it's possible that when it gets this pod it
                #              will have no IP yet and will be skipped.
                LOG.warning('SG for NP %s not created yet, will retry.',
                            utils.get_res_unique_name(crd))
                raise exceptions.ResourceNotReady(pod)
            LOG.debug("Appending %s", crd['status']['securityGroupId'])
            sg_list.append(crd['status']['securityGroupId'])

    # NOTE(maysams) Pods that are not selected by any Networkpolicy
    # are fully accessible. Thus, the default security group is associated.
    if not sg_list:
        sg_list = config.CONF.neutron_defaults.pod_security_groups
        if not sg_list:
            raise cfg.RequiredOptError('pod_security_groups',
                                       cfg.OptGroup('neutron_defaults'))

    return sg_list[:]
def _parse_rules(direction, crd, namespace):
    policy = crd['spec']['networkpolicy_spec']
    sg_id = crd['spec']['securityGroupId']

    ns_labels = namespace['metadata'].get('labels')
    ns_name = namespace['metadata'].get('name')
    ns_cidr = utils.get_namespace_subnet_cidr(namespace)

    rule_direction = 'from'
    crd_rules = crd['spec'].get('ingressSgRules')
    if direction == 'egress':
        rule_direction = 'to'
        crd_rules = crd['spec'].get('egressSgRules')

    matched = False
    rule_list = policy.get(direction, [])
    for rule_block in rule_list:
        for rule in rule_block.get(rule_direction, []):
            pod_selector = rule.get('podSelector')
            ns_selector = rule.get('namespaceSelector')
            if (ns_selector and ns_labels
                    and utils.match_selector(ns_selector, ns_labels)):
                if pod_selector:
                    pods = utils.get_pods(pod_selector, ns_name)
                    for pod in pods.get('items'):
                        pod_ip = utils.get_pod_ip(pod)
                        if 'ports' in rule_block:
                            for port in rule_block['ports']:
                                matched = True
                                crd_rules.append(
                                    _create_sg_rule(sg_id,
                                                    direction,
                                                    pod_ip,
                                                    port=port,
                                                    namespace=ns_name))
                        else:
                            matched = True
                            crd_rules.append(
                                _create_sg_rule(sg_id,
                                                direction,
                                                pod_ip,
                                                namespace=ns_name))
                else:
                    if 'ports' in rule_block:
                        for port in rule_block['ports']:
                            matched = True
                            crd_rules.append(
                                _create_sg_rule(sg_id,
                                                direction,
                                                ns_cidr,
                                                port=port,
                                                namespace=ns_name))
                    else:
                        matched = True
                        crd_rules.append(
                            _create_sg_rule(sg_id,
                                            direction,
                                            ns_cidr,
                                            namespace=ns_name))
    return matched, crd_rules
def _create_sg_rules(crd,
                     pod,
                     pod_selector,
                     rule_block,
                     crd_rules,
                     direction,
                     matched,
                     namespace=None):
    pod_labels = pod['metadata'].get('labels')

    # NOTE (maysams) No need to differentiate between podSelector
    # with empty value or with '{}', as they have same result in here.
    if (pod_selector
            and driver_utils.match_selector(pod_selector, pod_labels)):
        matched = True
        pod_ip = driver_utils.get_pod_ip(pod)
        sg_id = crd['spec']['securityGroupId']
        if 'ports' in rule_block:
            for port in rule_block['ports']:
                sg_rule = _create_sg_rule(sg_id,
                                          direction,
                                          cidr=pod_ip,
                                          port=port,
                                          namespace=namespace)
                crd_rules.append(sg_rule)
        else:
            sg_rule = _create_sg_rule(sg_id,
                                      direction,
                                      cidr=pod_ip,
                                      namespace=namespace)
            crd_rules.append(sg_rule)
    return matched
Exemple #8
0
def _create_sg_rules(crd,
                     pod,
                     pod_selector,
                     rule_block,
                     crd_rules,
                     direction,
                     matched,
                     namespace=None,
                     allow_all=False):
    pod_labels = pod['metadata'].get('labels')
    pod_ip = driver_utils.get_pod_ip(pod)
    if not pod_ip:
        LOG.debug(
            "Skipping SG rule creation for pod %s due to "
            "no IP assigned", pod['metadata']['name'])
        return None

    # NOTE (maysams) No need to differentiate between podSelector
    # with empty value or with '{}', as they have same result in here.
    if pod_selector:
        if driver_utils.match_selector(pod_selector, pod_labels):
            sg_id = crd['spec']['securityGroupId']
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = _create_sg_rule_on_text_port(
                            sg_id, direction, port, [pod], crd_rules, matched,
                            crd)
                    else:
                        matched = True
                        sg_rule = _create_sg_rule(sg_id,
                                                  direction,
                                                  cidr=pod_ip,
                                                  port=port,
                                                  namespace=namespace)
                        crd_rules.append(sg_rule)
            else:
                matched = True
                sg_rule = _create_sg_rule(sg_id,
                                          direction,
                                          cidr=pod_ip,
                                          namespace=namespace)
                crd_rules.append(sg_rule)
    else:
        # NOTE (maysams) When a policy with namespaceSelector and text port
        # is applied the port on the pods needs to be retrieved.
        sg_id = crd['spec']['securityGroupId']
        if 'ports' in rule_block:
            for port in rule_block['ports']:
                if type(port.get('port')) is not int:
                    matched = (_create_sg_rule_on_text_port(
                        sg_id,
                        direction,
                        port, [pod],
                        crd_rules,
                        matched,
                        crd,
                        allow_all=allow_all,
                        namespace=namespace))
    return matched
Exemple #9
0
def _create_sg_rule_on_text_port(sg_id,
                                 direction,
                                 port,
                                 rule_selected_pods,
                                 crd_rules,
                                 matched,
                                 crd,
                                 allow_all=False,
                                 namespace=None):
    matched_pods = {}

    spec_pod_selector = crd['spec'].get('podSelector')
    policy_namespace = crd['metadata']['namespace']
    spec_pods = driver_utils.get_pods(spec_pod_selector,
                                      policy_namespace).get('items')
    if direction == 'ingress':
        for spec_pod in spec_pods:
            container_ports = driver_utils.get_ports(spec_pod, port)
            for rule_selected_pod in rule_selected_pods:
                matched = _create_sg_rules_with_container_ports(
                    matched_pods, container_ports, allow_all, namespace,
                    matched, crd_rules, sg_id, direction, port,
                    rule_selected_pod)
    elif direction == 'egress':
        for rule_selected_pod in rule_selected_pods:
            pod_label = rule_selected_pod['metadata'].get('labels')
            pod_ns = rule_selected_pod['metadata'].get('namespace')
            # NOTE(maysams) Do not allow egress traffic to the actual
            # set of pods the NP is enforced on.
            if (driver_utils.match_selector(spec_pod_selector, pod_label)
                    and policy_namespace == pod_ns):
                continue
            container_ports = driver_utils.get_ports(rule_selected_pod, port)
            matched = _create_sg_rules_with_container_ports(
                matched_pods, container_ports, allow_all, namespace, matched,
                crd_rules, sg_id, direction, port, rule_selected_pod)
    for container_port, pods in matched_pods.items():
        if allow_all:
            sg_rule = driver_utils.create_security_group_rule_body(
                sg_id,
                direction,
                container_port,
                protocol=port.get('protocol'),
                pods=pods)
        else:
            namespace_obj = driver_utils.get_namespace(namespace)
            namespace_cidr = driver_utils.get_namespace_subnet_cidr(
                namespace_obj)
            sg_rule = driver_utils.create_security_group_rule_body(
                sg_id,
                direction,
                container_port,
                protocol=port.get('protocol'),
                cidr=namespace_cidr,
                pods=pods)
        sgr_id = driver_utils.create_security_group_rule(sg_rule)
        sg_rule['security_group_rule']['id'] = sgr_id
        crd_rules.append(sg_rule)
    return matched
def _parse_selectors_on_namespace(crd, direction, pod_selector, ns_selector,
                                  rule_block, namespace, matched):
    ns_name = namespace['metadata'].get('name')
    ns_labels = namespace['metadata'].get('labels')

    if (ns_selector and ns_labels
            and driver_utils.match_selector(ns_selector, ns_labels)):
        if pod_selector:
            pods = driver_utils.get_pods(pod_selector, ns_name).get('items')
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = (_create_sg_rule_on_text_port(
                            direction, port, pods, matched, crd))
                    else:
                        for pod in pods:
                            pod_ip = driver_utils.get_pod_ip(pod)
                            if not pod_ip:
                                pod_name = pod['metadata']['name']
                                LOG.debug(
                                    "Skipping SG rule creation for pod "
                                    "%s due to no IP assigned", pod_name)
                                continue
                            matched = True
            else:
                for pod in pods:
                    pod_ip = driver_utils.get_pod_ip(pod)
                    if not pod_ip:
                        pod_name = pod['metadata']['name']
                        LOG.debug(
                            "Skipping SG rule creation for pod %s due"
                            " to no IP assigned", pod_name)
                        continue
                    matched = True
        else:
            ns_pods = driver_utils.get_pods(ns_selector)['items']
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = (_create_sg_rule_on_text_port(
                            direction, port, ns_pods, matched, crd))
                    else:
                        matched = True
            else:
                matched = True
    return matched
def _parse_selectors_on_pod(crd, pod, pod_selector, namespace_selector,
                            rule_block, direction, matched):
    pod_namespace = pod['metadata']['namespace']
    pod_namespace_labels = _get_namespace_labels(pod_namespace)
    policy_namespace = crd['metadata']['namespace']

    if namespace_selector == {}:
        matched = _create_sg_rules(crd, pod, pod_selector, rule_block,
                                   direction, matched)
    elif namespace_selector:
        if (pod_namespace_labels and driver_utils.match_selector(
                namespace_selector, pod_namespace_labels)):
            matched = _create_sg_rules(crd, pod, pod_selector, rule_block,
                                       direction, matched)
    else:
        if pod_namespace == policy_namespace:
            matched = _create_sg_rules(crd, pod, pod_selector, rule_block,
                                       direction, matched)
    return matched
def _parse_rules(direction, crd, pod):
    policy = crd['spec']['networkpolicy_spec']

    pod_namespace = pod['metadata']['namespace']
    pod_namespace_labels = _get_namespace_labels(pod_namespace)
    policy_namespace = crd['metadata']['namespace']

    rule_direction = 'from'
    crd_rules = crd['spec'].get('ingressSgRules')
    if direction == 'egress':
        rule_direction = 'to'
        crd_rules = crd['spec'].get('egressSgRules')

    matched = False
    rule_list = policy.get(direction, [])
    for rule_block in rule_list:
        for rule in rule_block.get(rule_direction, []):
            namespace_selector = rule.get('namespaceSelector')
            pod_selector = rule.get('podSelector')
            if namespace_selector == {}:
                if _create_sg_rules(crd, pod, pod_selector, rule_block,
                                    crd_rules, direction, matched):
                    matched = True
            elif namespace_selector:
                if (pod_namespace_labels and driver_utils.match_selector(
                        namespace_selector, pod_namespace_labels)):
                    if _create_sg_rules(crd, pod, pod_selector, rule_block,
                                        crd_rules, direction, matched,
                                        pod_namespace):
                        matched = True
            else:
                if pod_namespace == policy_namespace:
                    if _create_sg_rules(crd, pod, pod_selector, rule_block,
                                        crd_rules, direction, matched,
                                        pod_namespace):
                        matched = True
    return matched, crd_rules
Exemple #13
0
 def test_match_selector(self):
     self.assertFalse(
         utils.match_selector({'matchLabels': {
             'app': 'demo'
         }}, None))
     self.assertFalse(
         utils.match_selector({'matchLabels': {
             'app': 'demo'
         }}, {}))
     self.assertFalse(
         utils.match_selector({'matchLabels': {
             'app': 'demo'
         }}, {'app': 'foobar'}))
     self.assertTrue(
         utils.match_selector({'matchLabels': {
             'app': 'demo'
         }}, {'app': 'demo'}))
     self.assertTrue(
         utils.match_selector({'matchLabels': {
             'app': 'demo'
         }}, {
             'app': 'demo',
             'foo': 'bar'
         }))
     self.assertTrue(
         utils.match_selector(
             {'matchLabels': {
                 'app': 'demo',
                 'foo': 'bar'
             }}, {
                 'app': 'demo',
                 'foo': 'bar'
             }))
     self.assertFalse(
         utils.match_selector(
             {'matchLabels': {
                 'app': 'demo',
                 'foo': 'bar'
             }}, {'app': 'demo'}))
def _create_sg_rule_on_text_port(direction, port, rule_selected_pods, matched,
                                 crd):
    spec_pod_selector = crd['spec'].get('podSelector')
    policy_namespace = crd['metadata']['namespace']
    spec_pods = driver_utils.get_pods(spec_pod_selector,
                                      policy_namespace).get('items')
    if direction == 'ingress':
        for spec_pod in spec_pods:
            container_ports = driver_utils.get_ports(spec_pod, port)
            matched = _create_sg_rules_with_container_ports(
                container_ports, matched)
    elif direction == 'egress':
        for rule_selected_pod in rule_selected_pods:
            pod_label = rule_selected_pod['metadata'].get('labels')
            pod_ns = rule_selected_pod['metadata'].get('namespace')
            # NOTE(maysams) Do not allow egress traffic to the actual
            # set of pods the NP is enforced on.
            if (driver_utils.match_selector(spec_pod_selector, pod_label)
                    and policy_namespace == pod_ns):
                continue
            container_ports = driver_utils.get_ports(rule_selected_pod, port)
            matched = _create_sg_rules_with_container_ports(
                container_ports, matched)
    return matched
def _parse_selectors_on_namespace(crd, direction, pod_selector, ns_selector,
                                  rule_block, crd_rules, namespace, matched):
    ns_name = namespace['metadata'].get('name')
    ns_labels = namespace['metadata'].get('labels')
    sg_id = crd['spec']['securityGroupId']

    if (ns_selector and ns_labels
            and driver_utils.match_selector(ns_selector, ns_labels)):
        if pod_selector:
            pods = driver_utils.get_pods(pod_selector, ns_name).get('items')
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = (_create_sg_rule_on_text_port(
                            sg_id, direction, port, pods, crd_rules, matched,
                            crd))
                    else:
                        matched = True
                        for pod in pods:
                            pod_ip = driver_utils.get_pod_ip(pod)
                            if not pod_ip:
                                pod_name = pod['metadata']['name']
                                LOG.debug(
                                    "Skipping SG rule creation for pod "
                                    "%s due to no IP assigned", pod_name)
                                continue
                            sg_rule = _create_sg_rule(sg_id,
                                                      direction,
                                                      pod_ip,
                                                      port=port,
                                                      namespace=ns_name)
                            if sg_rule not in crd_rules:
                                crd_rules.append(sg_rule)
            else:
                for pod in pods:
                    pod_ip = driver_utils.get_pod_ip(pod)
                    if not pod_ip:
                        pod_name = pod['metadata']['name']
                        LOG.debug(
                            "Skipping SG rule creation for pod %s due"
                            " to no IP assigned", pod_name)
                        continue
                    matched = True
                    sg_rule = _create_sg_rule(sg_id,
                                              direction,
                                              pod_ip,
                                              namespace=ns_name)
                    if sg_rule not in crd_rules:
                        crd_rules.append(sg_rule)
        else:
            ns_pods = driver_utils.get_pods(ns_selector)['items']
            ns_cidr = driver_utils.get_namespace_subnet_cidr(namespace)
            if 'ports' in rule_block:
                for port in rule_block['ports']:
                    if type(port.get('port')) is not int:
                        matched = (_create_sg_rule_on_text_port(
                            sg_id, direction, port, ns_pods, crd_rules,
                            matched, crd))
                    else:
                        matched = True
                        sg_rule = _create_sg_rule(sg_id,
                                                  direction,
                                                  ns_cidr,
                                                  port=port,
                                                  namespace=ns_name)
                        if sg_rule not in crd_rules:
                            crd_rules.append(sg_rule)
            else:
                matched = True
                sg_rule = _create_sg_rule(sg_id,
                                          direction,
                                          ns_cidr,
                                          namespace=ns_name)
                if sg_rule not in crd_rules:
                    crd_rules.append(sg_rule)
    return matched, crd_rules