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 _create_sg_rules_with_container_ports(matched_pods, container_ports, allow_all, namespace, matched, crd_rules, sg_id, direction, port, rule_selected_pod): """Create security group rules based on container ports If it's an allow from/to everywhere rule or a rule with a NamespaceSelector, updates a sg rule that might already exist and match the named port or creates a new one with the remote_ip_prefixes field containing the matched pod info. Otherwise, creates rules for each container port without a remote_ip_prefixes field. param matched_pods: List of dicts where the key is a container port and value is the pods that have the port param container_ports: List of tuples with pods and port values param allow_all: True is it's an allow from/to everywhere rule, False otherwise. param namespace: Namespace name param matched: If a sg rule was created for the NP rule param crd_rules: List of sg rules to update when patching the CRD param sg_id: ID of the security group param direction: String representing rule direction, ingress or egress param port: Dict containing port and protocol param rule_selected_pod: K8s Pod object selected by the rules selectors return: True if a sg rule was created, False otherwise. """ for pod, container_port in container_ports: pod_namespace = pod['metadata']['namespace'] pod_ip = driver_utils.get_pod_ip(pod) pod_info = {pod_ip: pod_namespace} matched = True if allow_all or namespace: crd_rule = _get_crd_rule(crd_rules, container_port) if crd_rule: crd_rule['remote_ip_prefixes'].update(pod_info) else: if container_port in matched_pods: matched_pods[container_port].update(pod_info) else: matched_pods[container_port] = pod_info else: pod_ip = driver_utils.get_pod_ip(rule_selected_pod) sg_rule = driver_utils.create_security_group_rule_body( sg_id, direction, container_port, protocol=port.get('protocol'), cidr=pod_ip, pods=pod_info) sgr_id = driver_utils.create_security_group_rule(sg_rule) sg_rule['security_group_rule']['id'] = sgr_id if sg_rule not in crd_rules: crd_rules.append(sg_rule) return matched
def delete_sg_rules(self, pod): LOG.debug("Deleting sg rule for pod: %s", pod['metadata']['name']) pod_ip = driver_utils.get_pod_ip(pod) if not pod_ip: LOG.debug("Skipping SG rule deletion as pod %s has no IP assigned", pod['metadata']['name']) return None crd_pod_selectors = [] knp_crds = driver_utils.get_kuryrnetpolicy_crds() for crd in knp_crds.get('items'): crd_selector = crd['spec'].get('podSelector') ingress_rule_list = crd['spec'].get('ingressSgRules') egress_rule_list = crd['spec'].get('egressSgRules') i_matched, i_rules = _parse_rules_on_delete_pod( ingress_rule_list, "ingress", pod_ip) e_matched, e_rules = _parse_rules_on_delete_pod( egress_rule_list, "egress", pod_ip) if i_matched or e_matched: driver_utils.patch_kuryrnetworkpolicy_crd( crd, i_rules, e_rules, crd_selector) if i_matched: crd_pod_selectors.append(crd_selector) return crd_pod_selectors
def _pods_in_ip_block(self, pods, resource): for pod in pods: pod_ip = driver_utils.get_pod_ip(pod) if (ipaddress.ip_address(pod_ip) in ipaddress.ip_network(resource.get('cidr'))): return True return False
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 delete_sg_rules(self, pod): LOG.debug("Deleting SG rules for pod: %s", pod['metadata']['name']) pod_ip = driver_utils.get_pod_ip(pod) crd_pod_selectors = [] if not pod_ip: LOG.debug("Skipping SG rule deletion as pod %s has no IP assigned", pod['metadata']['name']) return crd_pod_selectors knp_crds = driver_utils.get_kuryrnetworkpolicy_crds() for crd in knp_crds: crd_selector = crd['spec'].get('podSelector') ingress_rule_list = crd['spec'].get('ingressSgRules') egress_rule_list = crd['spec'].get('egressSgRules') i_matched = _parse_rules_on_delete_pod(ingress_rule_list, "ingress", pod_ip) e_matched = _parse_rules_on_delete_pod(egress_rule_list, "egress", pod_ip) if i_matched or e_matched: try: driver_utils.bump_networkpolicy(crd) except exceptions.K8sResourceNotFound: # The NP got deleted, ignore it. continue if i_matched: crd_pod_selectors.append(crd_selector) return crd_pod_selectors
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
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
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 _create_sg_rules_with_container_ports(container_ports, matched): """Checks if security group rules based on container ports will be updated param container_ports: List of tuples with pods and port values param matched: If a sg rule was created for the NP rule return: True if a sg rule needs to be created, False otherwise. """ for pod, container_port in container_ports: 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']) continue return matched return False
def delete_sg_rules(self, pod): LOG.debug("Deleting sg rule for pod: %s", pod['metadata']['name']) pod_ip = driver_utils.get_pod_ip(pod) crd_pod_selectors = [] knp_crds = driver_utils.get_kuryrnetpolicy_crds() for crd in knp_crds.get('items'): crd_selector = crd['spec'].get('podSelector') ingress_rule_list = crd['spec'].get('ingressSgRules') egress_rule_list = crd['spec'].get('egressSgRules') i_rules = [] e_rules = [] matched = False for i_rule in ingress_rule_list: LOG.debug("Parsing ingress rule: %r", i_rule) remote_ip_prefix = i_rule['security_group_rule'].get( 'remote_ip_prefix') if remote_ip_prefix and remote_ip_prefix == pod_ip: matched = True driver_utils.delete_security_group_rule( i_rule['security_group_rule']['id']) else: i_rules.append(i_rule) for e_rule in egress_rule_list: LOG.debug("Parsing egress rule: %r", e_rule) remote_ip_prefix = e_rule['security_group_rule'].get( 'remote_ip_prefix') if remote_ip_prefix and remote_ip_prefix == pod_ip: matched = True driver_utils.delete_security_group_rule( e_rule['security_group_rule']['id']) else: e_rules.append(e_rule) if matched: driver_utils.patch_kuryr_crd(crd, i_rules, e_rules, crd_selector) crd_pod_selectors.append(crd_selector) return crd_pod_selectors
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