Ejemplo n.º 1
0
    def handle_port(self, context, port):
        """Handle port update event"""

        # Check if port is trusted and called at once.
        if nl_net.is_port_trusted(port) and not self.fwg_map.get_port(port):
            self._add_rule_for_trusted_port(port)
            self.fwg_map.set_port(port)
            return

        if not self._is_port_layer2(port):
            return

        # check if port is already assigned to a fwg
        if self.fwg_map.get_port_fwg(port):
            return

        fwg = self.plugin_rpc.get_firewall_group_for_port(
            context, port.get('port_id'))
        if not fwg:
            LOG.info(
                "Firewall group applied to port %s is "
                "not available on server.", port['port_id'])
            return

        ret = self._apply_fwg_rules(fwg, [port])
        status = self._compute_status(fwg, ret, event=consts.HANDLE_PORT)
        self.fwg_map.set_port_fwg(port, fwg)
        self._send_fwg_status(context,
                              fwg_id=fwg['id'],
                              status=status,
                              host=self.conf.host)
Ejemplo n.º 2
0
    def _get_security_groups_on_port(self, context, port):
        """Check that all security groups on port belong to tenant.

        :returns: all security groups on port belonging to tenant)

        """
        port = port['port']
        if not validators.is_attr_set(port.get(ext_sg.SECURITYGROUPS)):
            return
        if port.get('device_owner') and net.is_port_trusted(port):
            return

        port_sg = port.get(ext_sg.SECURITYGROUPS, [])
        tenant_id = port.get('tenant_id')

        sg_objs = sg_obj.SecurityGroup.get_objects(context, id=port_sg)

        valid_groups = set(
            g.id for g in sg_objs
            if (context.is_admin or not tenant_id or g.tenant_id == tenant_id
                or sg_obj.SecurityGroup.is_shared_with_tenant(
                    context, g.id, tenant_id)))

        requested_groups = set(port_sg)
        port_sg_missing = requested_groups - valid_groups
        if port_sg_missing:
            raise ext_sg.SecurityGroupNotFound(id=', '.join(port_sg_missing))

        return sg_objs
Ejemplo n.º 3
0
    def _determine_port_security_and_has_ip(self, context, port):
        """Returns a tuple of booleans (port_security_enabled, has_ip).

        Port_security is the value associated with the port if one is present
        otherwise the value associated with the network is returned. has_ip is
        if the port is associated with an ip or not.
        """
        has_ip = self._ip_on_port(port)
        # we don't apply security groups for dhcp, router
        if port.get('device_owner') and net.is_port_trusted(port):
            return (False, has_ip)

        if validators.is_attr_set(port.get(psec.PORTSECURITY)):
            port_security_enabled = port[psec.PORTSECURITY]

        # If port has an ip and security_groups are passed in
        # conveniently set port_security_enabled to true this way
        # user doesn't also have to pass in port_security_enabled=True
        # when creating ports.
        elif has_ip and validators.is_attr_set(port.get('security_groups')):
            port_security_enabled = True
        else:
            port_security_enabled = self._get_network_security_binding(
                context, port['network_id'])

        return (port_security_enabled, has_ip)
Ejemplo n.º 4
0
    def _get_devices_info(self, context, devices):
        # NOTE(kevinbenton): this format is required by the sg code, it is
        # defined in get_port_from_device and mimics
        # make_port_dict_with_security_groups in ML2 db
        result = {}
        for device in devices:
            ovo = self.rcache.get_resource_by_id('Port', device)
            if not ovo:
                continue
            port = ovo.to_dict()
            # the caller expects trusted ports to be excluded from the result
            if net.is_port_trusted(port):
                continue

            port['security_groups'] = list(ovo.security_group_ids)
            port['security_group_rules'] = []
            port['security_group_source_groups'] = []
            port['fixed_ips'] = [str(f['ip_address'])
                                 for f in port['fixed_ips']]
            # NOTE(kevinbenton): this id==device is only safe for OVS. a lookup
            # will be required for linux bridge and others that don't have the
            # full port UUID
            port['device'] = port['id']
            port['port_security_enabled'] = getattr(
                ovo.security, 'port_security_enabled', True)
            result[device] = port
        return result
Ejemplo n.º 5
0
    def _determine_port_security_and_has_ip(self, context, port):
        """Returns a tuple of booleans (port_security_enabled, has_ip).

        Port_security is the value associated with the port if one is present
        otherwise the value associated with the network is returned. has_ip is
        if the port is associated with an ip or not.
        """
        has_ip = self._ip_on_port(port)
        # we don't apply security groups for dhcp, router
        if port.get('device_owner') and net.is_port_trusted(port):
            return (False, has_ip)

        if validators.is_attr_set(port.get(psec.PORTSECURITY)):
            port_security_enabled = port[psec.PORTSECURITY]

        # If port has an ip and security_groups are passed in
        # conveniently set port_security_enabled to true this way
        # user doesn't also have to pass in port_security_enabled=True
        # when creating ports.
        elif has_ip and validators.is_attr_set(port.get('security_groups')):
            port_security_enabled = True
        else:
            port_security_enabled = self._get_network_security_binding(
                context, port['network_id'])

        return (port_security_enabled, has_ip)
Ejemplo n.º 6
0
    def _get_security_groups_on_port(self, context, port):
        """Check that all security groups on port belong to tenant.

        :returns: all security groups IDs on port belonging to tenant.
        """
        port = port['port']
        if not validators.is_attr_set(port.get(ext_sg.SECURITYGROUPS)):
            return
        if port.get('device_owner') and net.is_port_trusted(port):
            return

        port_sg = port.get(ext_sg.SECURITYGROUPS, [])
        filters = {'id': port_sg}
        tenant_id = port.get('tenant_id')
        if tenant_id:
            filters['tenant_id'] = [tenant_id]
        valid_groups = set(g['id'] for g in self.get_security_groups(
            context, fields=['id'], filters=filters))

        requested_groups = set(port_sg)
        port_sg_missing = requested_groups - valid_groups
        if port_sg_missing:
            raise ext_sg.SecurityGroupNotFound(id=', '.join(port_sg_missing))

        return list(requested_groups)
Ejemplo n.º 7
0
    def _get_security_groups_on_port(self, context, port):
        """Check that all security groups on port belong to tenant.

        :returns: all security groups IDs on port belonging to tenant.
        """
        port = port['port']
        if not validators.is_attr_set(port.get(ext_sg.SECURITYGROUPS)):
            return
        if port.get('device_owner') and net.is_port_trusted(port):
            return

        port_sg = port.get(ext_sg.SECURITYGROUPS, [])
        tenant_id = port.get('tenant_id')

        sg_objs = sg_obj.SecurityGroup.get_objects(context, id=port_sg)

        valid_groups = set(
            g.id for g in sg_objs
            if (not tenant_id or g.tenant_id == tenant_id or
                sg_obj.SecurityGroup.is_shared_with_tenant(
                    context, g.id, tenant_id))
        )

        requested_groups = set(port_sg)
        port_sg_missing = requested_groups - valid_groups
        if port_sg_missing:
            raise ext_sg.SecurityGroupNotFound(id=', '.join(port_sg_missing))

        return list(requested_groups)
    def _get_security_groups_on_port(self, context, port):
        """Check that all security groups on port belong to tenant.

        :returns: all security groups IDs on port belonging to tenant.
        """
        port = port['port']
        if not validators.is_attr_set(port.get(ext_sg.SECURITYGROUPS)):
            return
        if port.get('device_owner') and net.is_port_trusted(port):
            return

        port_sg = port.get(ext_sg.SECURITYGROUPS, [])
        filters = {'id': port_sg}
        tenant_id = port.get('tenant_id')
        if tenant_id:
            filters['tenant_id'] = [tenant_id]
        valid_groups = set(g['id'] for g in
                           self.get_security_groups(context, fields=['id'],
                                                    filters=filters))

        requested_groups = set(port_sg)
        port_sg_missing = requested_groups - valid_groups
        if port_sg_missing:
            raise ext_sg.SecurityGroupNotFound(id=', '.join(port_sg_missing))

        return list(requested_groups)
Ejemplo n.º 9
0
    def _validate_max_ips_per_port(self, fixed_ip_list, device_owner):
        if net.is_port_trusted({'device_owner': device_owner}):
            return

        if len(fixed_ip_list) > cfg.CONF.max_fixed_ips_per_port:
            msg = _('Exceeded maximum amount of fixed ips per port')
            raise exc.InvalidInput(error_message=msg)
Ejemplo n.º 10
0
def setup_arp_spoofing_protection(vif, port_details):
    current_rules = ebtables(['-L']).splitlines()
    if not port_details.get('port_security_enabled', True):
        # clear any previous entries related to this port
        delete_arp_spoofing_protection([vif], current_rules)
        LOG.info(
            _LI("Skipping ARP spoofing rules for port '%s' because "
                "it has port security disabled"), vif)
        return
    if net.is_port_trusted(port_details):
        # clear any previous entries related to this port
        delete_arp_spoofing_protection([vif], current_rules)
        LOG.debug(
            "Skipping ARP spoofing rules for network owned port "
            "'%s'.", vif)
        return
    _install_mac_spoofing_protection(vif, port_details, current_rules)
    # collect all of the addresses and cidrs that belong to the port
    addresses = {f['ip_address'] for f in port_details['fixed_ips']}
    if port_details.get('allowed_address_pairs'):
        addresses |= {
            p['ip_address']
            for p in port_details['allowed_address_pairs']
        }

    addresses = {ip for ip in addresses if netaddr.IPNetwork(ip).version == 4}
    if any(netaddr.IPNetwork(ip).prefixlen == 0 for ip in addresses):
        # don't try to install protection because a /0 prefix allows any
        # address anyway and the ARP_SPA can only match on /1 or more.
        return

    install_arp_spoofing_protection(vif, addresses, current_rules)
Ejemplo n.º 11
0
    def _get_devices_info(self, context, devices):
        # NOTE(kevinbenton): this format is required by the sg code, it is
        # defined in get_port_from_device and mimics
        # make_port_dict_with_security_groups in ML2 db
        result = {}
        for device in devices:
            ovo = self.rcache.get_resource_by_id('Port', device)
            if not ovo:
                continue
            port = ovo.to_dict()
            # the caller expects trusted ports to be excluded from the result
            if net.is_port_trusted(port):
                continue

            port['security_groups'] = list(ovo.security_group_ids)
            port['security_group_rules'] = []
            port['security_group_source_groups'] = []
            port['security_group_remote_address_groups'] = []
            port['fixed_ips'] = [
                str(f['ip_address']) for f in port['fixed_ips']
            ]
            # NOTE(kevinbenton): this id==device is only safe for OVS. a lookup
            # will be required for linux bridge and others that don't have the
            # full port UUID
            port['device'] = port['id']
            port['port_security_enabled'] = getattr(ovo.security,
                                                    'port_security_enabled',
                                                    True)
            result[device] = port
        return result
Ejemplo n.º 12
0
 def _ensure_default_security_group_on_port(self, context, port):
     # we don't apply security groups for dhcp, router
     port = port['port']
     if port.get('device_owner') and net.is_port_trusted(port):
         return
     if not validators.is_attr_set(port.get(ext_sg.SECURITYGROUPS)):
         default_sg = self._ensure_default_security_group(context,
                                                          port['tenant_id'])
         port[ext_sg.SECURITYGROUPS] = [default_sg]
Ejemplo n.º 13
0
 def _ensure_default_security_group_on_port(self, context, port):
     # we don't apply security groups for dhcp, router
     port = port['port']
     if port.get('device_owner') and net.is_port_trusted(port):
         return
     if not validators.is_attr_set(port.get(ext_sg.SECURITYGROUPS)):
         default_sg = self._ensure_default_security_group(
             context, port['tenant_id'])
         port[ext_sg.SECURITYGROUPS] = [default_sg]
Ejemplo n.º 14
0
    def _validate_max_ips_per_port(self, fixed_ip_list, device_owner):
        """Validate the number of fixed ips on a port

        Do not allow multiple ip addresses on a port since the nsx backend
        cannot add multiple static dhcp bindings with the same port
        """
        if (device_owner and
            net.is_port_trusted({'device_owner': device_owner})):
            return

        if validators.is_attr_set(fixed_ip_list) and len(fixed_ip_list) > 1:
            msg = _('Exceeded maximum amount of fixed ips per port')
            raise n_exc.InvalidInput(error_message=msg)
Ejemplo n.º 15
0
    def _validate_max_ips_per_port(self, fixed_ip_list, device_owner):
        """Validate the number of fixed ips on a port

        Do not allow multiple ip addresses on a port since the nsx backend
        cannot add multiple static dhcp bindings with the same port
        """
        if (device_owner and
            nl_net_utils.is_port_trusted({'device_owner': device_owner})):
            return

        if validators.is_attr_set(fixed_ip_list) and len(fixed_ip_list) > 1:
            msg = _('Exceeded maximum amount of fixed ips per port')
            raise n_exc.InvalidInput(error_message=msg)
Ejemplo n.º 16
0
 def _ensure_default_security_group_on_port(self, context, port):
     # we don't apply security groups for dhcp, router
     port = port['port']
     if port.get('device_owner') and net.is_port_trusted(port):
         return
     port_sg = port.get(ext_sg.SECURITYGROUPS)
     if port_sg is None or not validators.is_attr_set(port_sg):
         # TODO(ralonsoh): "tenant_id" reference should be removed.
         port_project = port.get('project_id') or port.get('tenant_id')
         default_sg = self._ensure_default_security_group(context,
                                                          port_project)
         if default_sg:
             port[ext_sg.SECURITYGROUPS] = [default_sg]
Ejemplo n.º 17
0
def setup_arp_spoofing_protection(vif, port_details):
    if not port_details.get('port_security_enabled', True):
        # clear any previous entries related to this port
        delete_arp_spoofing_protection([vif])
        LOG.info("Skipping ARP spoofing rules for port '%s' because "
                 "it has port security disabled", vif)
        return
    if net.is_port_trusted(port_details):
        # clear any previous entries related to this port
        delete_arp_spoofing_protection([vif])
        LOG.debug("Skipping ARP spoofing rules for network owned port "
                  "'%s'.", vif)
        return
    _setup_arp_spoofing_protection(vif, port_details)
Ejemplo n.º 18
0
def setup_arp_spoofing_protection(vif, port_details):
    if not port_details.get('port_security_enabled', True):
        # clear any previous entries related to this port
        delete_arp_spoofing_protection([vif])
        LOG.info("Skipping ARP spoofing rules for port '%s' because "
                 "it has port security disabled", vif)
        return
    if net.is_port_trusted(port_details):
        # clear any previous entries related to this port
        delete_arp_spoofing_protection([vif])
        LOG.debug("Skipping ARP spoofing rules for network owned port "
                  "'%s'.", vif)
        return
    _setup_arp_spoofing_protection(vif, port_details)
Ejemplo n.º 19
0
def setup_arp_spoofing_protection(vif, port_details, socket_dir):
    kvs_device_name, port_index = get_kvs_device_name_port_index(
        vif, socket_dir)
    LOG.info(
        "setup_arp_spoofing_protection called: vif %s, kvs_device_name %s",
        vif, kvs_device_name)

    if port_index is None:
        LOG.error(
            "setup_arp_spoofing_protection failed: port_index could "
            "not be found for vhost/vdev %s", kvs_device_name)
        return
    if not port_details.get('port_security_enabled', True):
        # clear any previous entries related to this port
        _delete_arp_spoofing_protection(port_index)
        LOG.info(
            "Skipping ARP spoofing rules for port '%s' because "
            "it has port security disabled", vif)
        return
    if net.is_port_trusted(port_details):
        # clear any previous entries related to this port
        _delete_arp_spoofing_protection(port_index)
        LOG.info("Skipping ARP spoofing rules for network owned port "
                 "'%s'.", vif)
        return

    ##apply diff rules, delete extra rules
    new_pairs = _new_anti_spoofing_rules(vif, port_details, port_index)
    #Single port represents parent-port and subports in case of trunk.
    #parent-port rules are associated with vlan=0, and subport rules are associated with other vlans.
    #Here, we should not touch/delete trunk's subports rules.
    existing_pairs = kvs_net.list_anti_spoofing_rules(port_index, vlan=0)
    if existing_pairs is None:
        existing_pairs = []

    new_set = set()
    for new_pair in new_pairs:
        new_set.add((new_pair["ip"], new_pair["mac"]))
    existing_set = set()
    for existing_pair in existing_pairs:
        existing_set.add((existing_pair["ip"], existing_pair["mac"]))

    setup = new_set - existing_set
    delete = existing_set - new_set

    for (ip, mac) in setup:
        kvs_net.add_anti_spoofing_rule(port_index, mac, ip)  #vlan = 0
    for (ip, mac) in delete:
        kvs_net.delete_anti_spoofing_rule(port_index, mac, ip)  #vlan = 0
Ejemplo n.º 20
0
 def _handle_security_group(self, t_ctx, q_ctx, port):
     if 'security_groups' not in port:
         return
     if port.get('device_owner') and net.is_port_trusted(port):
         return
     if not port['security_groups']:
         raw_client = self.neutron_handle._get_client(t_ctx)
         params = {'name': 'default'}
         t_sgs = raw_client.list_security_groups(
             **params)['security_groups']
         if t_sgs:
             port['security_groups'] = [t_sgs[0]['id']]
     if port['security_groups'] is q_constants.ATTR_NOT_SPECIFIED:
         return
     for sg_id in port['security_groups']:
         self.get_security_group(q_ctx, sg_id)
Ejemplo n.º 21
0
 def _handle_security_group(self, t_ctx, q_ctx, port):
     if 'security_groups' not in port:
         return
     if port.get('device_owner') and net.is_port_trusted(port):
         return
     if not port['security_groups']:
         raw_client = self.neutron_handle._get_client(t_ctx)
         params = {'name': 'default'}
         t_sgs = raw_client.list_security_groups(
             **params)['security_groups']
         if t_sgs:
             port['security_groups'] = [t_sgs[0]['id']]
     if port['security_groups'] is q_constants.ATTR_NOT_SPECIFIED:
         return
     for sg_id in port['security_groups']:
         self.get_security_group(q_ctx, sg_id)
Ejemplo n.º 22
0
    def _determine_port_security(self, context, port):
        """Returns a boolean (port_security_enabled).

        Port_security is the value associated with the port if one is present
        otherwise the value associated with the network is returned.
        """
        # we don't apply security groups for dhcp, router
        if port.get('device_owner') and net.is_port_trusted(port):
            return False

        if validators.is_attr_set(port.get(psec.PORTSECURITY)):
            port_security_enabled = port[psec.PORTSECURITY]
        else:
            port_security_enabled = self._get_network_security_binding(
                context, port['network_id'])

        return port_security_enabled
Ejemplo n.º 23
0
    def _determine_port_security(self, context, port):
        """Returns a boolean (port_security_enabled).

        Port_security is the value associated with the port if one is present
        otherwise the value associated with the network is returned.
        """
        # we don't apply security groups for dhcp, router
        if port.get('device_owner') and net.is_port_trusted(port):
            return False

        if validators.is_attr_set(port.get(psec.PORTSECURITY)):
            port_security_enabled = port[psec.PORTSECURITY]
        else:
            port_security_enabled = self._get_network_security_binding(
                context, port['network_id'])

        return port_security_enabled
Ejemplo n.º 24
0
    def _get_provider_security_groups_on_port(self, context, port):
        p = port['port']
        tenant_id = p['tenant_id']
        provider_sgs = p.get(provider_sg.PROVIDER_SECURITYGROUPS,
                             n_constants.ATTR_NOT_SPECIFIED)

        if p.get('device_owner') and n_utils.is_port_trusted(p):
            return

        if not validators.is_attr_set(provider_sgs):
            if provider_sgs is n_constants.ATTR_NOT_SPECIFIED:
                provider_sgs = self._get_tenant_provider_security_groups(
                    context, tenant_id)
            else:
                # Accept None as indication that this port should not be
                # associated with any provider security-group.
                provider_sgs = []
        return provider_sgs
Ejemplo n.º 25
0
    def _get_provider_security_groups_on_port(self, context, port):
        p = port['port']
        tenant_id = p['tenant_id']
        provider_sgs = p.get(provider_sg.PROVIDER_SECURITYGROUPS,
                             n_constants.ATTR_NOT_SPECIFIED)

        if p.get('device_owner') and n_utils.is_port_trusted(p):
            return

        if not validators.is_attr_set(provider_sgs):
            if provider_sgs is n_constants.ATTR_NOT_SPECIFIED:
                provider_sgs = self._get_tenant_provider_security_groups(
                    context, tenant_id)
            else:
                # Accept None as indication that this port should not be
                # associated with any provider security-group.
                provider_sgs = []
        return provider_sgs
Ejemplo n.º 26
0
    def delete_port(self, context, port):
        """This is being called when a port is deleted by the agent. """

        # delete_port should be handled only unbound timing for a port.
        # If 'vif_port' is included in the port dict, this is called after
        # deleted the port and should be ignored.
        if 'vif_port' in port:
            return

        port = self.fwg_map.get_port(port)

        if port and nl_net.is_port_trusted(port):
            self._delete_rule_for_trusted_port(port)
            self.fwg_map.remove_port(port)
            return

        if not self._is_port_layer2(port):
            return

        fwg = self.fwg_map.get_port_fwg(port)
        if not fwg:
            LOG.info(
                "Firewall group associated to port %(port_id)s is "
                "not available on server.", {'port_id': port['port_id']})
            return

        ret = self._apply_fwg_rules(fwg, [port], event=consts.DELETE_FWG)

        port_id = self.fwg_map.port_id(port)
        if port_id in fwg['ports']:
            fwg['ports'].remove(port_id)

        # update the fwg dict to known_fwgs
        self.fwg_map.set_fwg(fwg)
        self.fwg_map.remove_port(port)
        status = self._compute_status(fwg, ret, event=consts.DELETE_PORT)
        self._send_fwg_status(context, fwg['id'], status, self.conf.host)
Ejemplo n.º 27
0
 def _get_devices_info(self, context, devices):
     return dict(
         (port['id'], port)
         for port in self.plugin.get_ports_from_devices(context, devices)
         if port and not net.is_port_trusted(port)
     )
Ejemplo n.º 28
0
 def _get_devices_info(self, context, devices):
     return dict(
         (port['id'], port)
         for port in self.plugin.get_ports_from_devices(context, devices)
         if port and not net.is_port_trusted(port))
Ejemplo n.º 29
0
def is_lsp_trusted(port):
    return n_utils.is_port_trusted(port) if port.get('device_owner') else False
Ejemplo n.º 30
0
 def test_is_port_trusted(self):
     self.assertTrue(
         net.is_port_trusted({
             'device_owner':
             constants.DEVICE_OWNER_NETWORK_PREFIX + 'dev'
         }))
Ejemplo n.º 31
0
 def test_is_port_not_trusted(self):
     self.assertFalse(
         net.is_port_trusted({
             'device_owner':
             constants.DEVICE_OWNER_COMPUTE_PREFIX + 'dev'
         }))