def _add_arp_protection(self, machine, addresses, extra_port_dict=None):
     port_dict = {'fixed_ips': [{'ip_address': a} for a in addresses]}
     if extra_port_dict:
         port_dict.update(extra_port_dict)
     name = net_helpers.VethFixture.get_peer_name(machine.port.name)
     arp_protect.setup_arp_spoofing_protection(name, port_dict)
     self.addCleanup(arp_protect.delete_arp_spoofing_protection,
                     [name])
    def treat_devices_added_updated(self, devices):
        try:
            devices_details_list = self.plugin_rpc.get_devices_details_list(
                self.context, devices, self.agent_id)
        except Exception as e:
            LOG.debug("Unable to get port details for "
                      "%(devices)s: %(e)s",
                      {'devices': devices, 'e': e})
            # resync is needed
            return True

        for device_details in devices_details_list:
            device = device_details['device']
            LOG.debug("Port %s added", device)

            if 'port_id' in device_details:
                LOG.info(_LI("Port %(device)s updated. Details: %(details)s"),
                         {'device': device, 'details': device_details})
                if self.prevent_arp_spoofing:
                    port = self.br_mgr.get_tap_device_name(
                        device_details['port_id'])
                    arp_protect.setup_arp_spoofing_protection(port,
                                                              device_details)
                if device_details['admin_state_up']:
                    # create the networking for the port
                    network_type = device_details.get('network_type')
                    if network_type:
                        segmentation_id = device_details.get('segmentation_id')
                    else:
                        # compatibility with pre-Havana RPC vlan_id encoding
                        vlan_id = device_details.get('vlan_id')
                        (network_type,
                         segmentation_id) = lconst.interpret_vlan_id(vlan_id)
                    if self.br_mgr.add_interface(
                        device_details['network_id'],
                        network_type,
                        device_details['physical_network'],
                        segmentation_id,
                        device_details['port_id']):

                        # update plugin about port status
                        self.plugin_rpc.update_device_up(self.context,
                                                         device,
                                                         self.agent_id,
                                                         cfg.CONF.host)
                    else:
                        self.plugin_rpc.update_device_down(self.context,
                                                           device,
                                                           self.agent_id,
                                                           cfg.CONF.host)
                else:
                    self.remove_port_binding(device_details['network_id'],
                                             device_details['port_id'])
            else:
                LOG.info(_LI("Device %s not defined on plugin"), device)
        return False
Beispiel #3
0
    def treat_devices_added_updated(self, devices):
        try:
            devices_details_list = self.plugin_rpc.get_devices_details_list(
                self.context, devices, self.agent_id)
        except Exception as e:
            LOG.debug("Unable to get port details for "
                      "%(devices)s: %(e)s",
                      {'devices': devices, 'e': e})
            # resync is needed
            return True

        for device_details in devices_details_list:
            device = device_details['device']
            LOG.debug("Port %s added", device)

            if 'port_id' in device_details:
                LOG.info(_LI("Port %(device)s updated. Details: %(details)s"),
                         {'device': device, 'details': device_details})
                if self.prevent_arp_spoofing:
                    port = self.br_mgr.get_tap_device_name(
                        device_details['port_id'])
                    arp_protect.setup_arp_spoofing_protection(port,
                                                              device_details)
                if device_details['admin_state_up']:
                    # create the networking for the port
                    network_type = device_details.get('network_type')
                    if network_type:
                        segmentation_id = device_details.get('segmentation_id')
                    else:
                        # compatibility with pre-Havana RPC vlan_id encoding
                        vlan_id = device_details.get('vlan_id')
                        (network_type,
                         segmentation_id) = lconst.interpret_vlan_id(vlan_id)
                    if self.br_mgr.add_interface(
                        device_details['network_id'],
                        network_type,
                        device_details['physical_network'],
                        segmentation_id,
                        device_details['port_id']):

                        # update plugin about port status
                        self.plugin_rpc.update_device_up(self.context,
                                                         device,
                                                         self.agent_id,
                                                         cfg.CONF.host)
                    else:
                        self.plugin_rpc.update_device_down(self.context,
                                                           device,
                                                           self.agent_id,
                                                           cfg.CONF.host)
                else:
                    self.remove_port_binding(device_details['network_id'],
                                             device_details['port_id'])
            else:
                LOG.info(_LI("Device %s not defined on plugin"), device)
        return False
 def _add_arp_protection(self, machine, addresses, extra_port_dict=None):
     port_dict = {
         "fixed_ips": [{"ip_address": a} for a in addresses],
         "device_owner": "nobody",
         "mac_address": machine.port.link.address,
     }
     if extra_port_dict:
         port_dict.update(extra_port_dict)
     name = net_helpers.VethFixture.get_peer_name(machine.port.name)
     arp_protect.setup_arp_spoofing_protection(name, port_dict)
     self.addCleanup(arp_protect.delete_arp_spoofing_protection, [name])
    def treat_devices_added_updated(self, devices):
        try:
            devices_details_list = self.plugin_rpc.get_devices_details_list(self.context, devices, self.agent_id)
        except Exception:
            LOG.exception(_LE("Unable to get port details for %s"), devices)
            # resync is needed
            return True

        for device_details in devices_details_list:
            device = device_details["device"]
            LOG.debug("Port %s added", device)

            if "port_id" in device_details:
                LOG.info(
                    _LI("Port %(device)s updated. Details: %(details)s"), {"device": device, "details": device_details}
                )
                if self.prevent_arp_spoofing:
                    port = self.br_mgr.get_tap_device_name(device_details["port_id"])
                    arp_protect.setup_arp_spoofing_protection(port, device_details)
                if device_details["admin_state_up"]:
                    # create the networking for the port
                    network_type = device_details.get("network_type")
                    segmentation_id = device_details.get("segmentation_id")
                    if self.br_mgr.add_interface(
                        device_details["network_id"],
                        network_type,
                        device_details["physical_network"],
                        segmentation_id,
                        device_details["port_id"],
                    ):

                        # update plugin about port status
                        self.plugin_rpc.update_device_up(self.context, device, self.agent_id, cfg.CONF.host)
                    else:
                        self.plugin_rpc.update_device_down(self.context, device, self.agent_id, cfg.CONF.host)
                else:
                    physical_network = device_details["physical_network"]
                    self.remove_port_binding(device_details["network_id"], physical_network, device_details["port_id"])
            else:
                LOG.info(_LI("Device %s not defined on plugin"), device)
        return False
 def setup_arp_spoofing_protection(self, device, device_details):
     arp_protect.setup_arp_spoofing_protection(device, device_details)
 def setup_arp_spoofing_protection(self, device, device_details):
     arp_protect.setup_arp_spoofing_protection(device, device_details)
Beispiel #8
0
    def treat_devices_added_updated(self, devices):
        try:
            devices_details_list = self.plugin_rpc.get_devices_details_list(
                self.context, devices, self.agent_id)
        except Exception:
            LOG.exception(_LE("Unable to get port details for %s"), devices)
            # resync is needed
            return True

        for device_details in devices_details_list:
            device = device_details['device']
            LOG.debug("Port %s added", device)

            if 'port_id' in device_details:
                LOG.info(_LI("Port %(device)s updated. Details: %(details)s"),
                         {
                             'device': device,
                             'details': device_details
                         })
                if self.prevent_arp_spoofing:
                    port = self.br_mgr.get_tap_device_name(
                        device_details['port_id'])
                    arp_protect.setup_arp_spoofing_protection(
                        port, device_details)
                # create the networking for the port
                network_type = device_details.get('network_type')
                segmentation_id = device_details.get('segmentation_id')
                tap_in_bridge = self.br_mgr.add_interface(
                    device_details['network_id'], network_type,
                    device_details['physical_network'], segmentation_id,
                    device_details['port_id'], device_details['device_owner'])
                # REVISIT(scheuran): Changed the way how ports admin_state_up
                # is implemented.
                #
                # Old lb implementation:
                # - admin_state_up: ensure that tap is plugged into bridge
                # - admin_state_down: remove tap from bridge
                # New lb implementation:
                # - admin_state_up: set tap device state to up
                # - admin_state_down: set tap device stae to down
                #
                # However both approaches could result in races with
                # nova/libvirt and therefore to an invalid system state in the
                # scenario, where an instance is booted with a port configured
                # with admin_state_up = False:
                #
                # Libvirt does the following actions in exactly
                # this order (see libvirt virnetdevtap.c)
                #     1) Create the tap device, set its MAC and MTU
                #     2) Plug the tap into the bridge
                #     3) Set the tap online
                #
                # Old lb implementation:
                #   A race could occur, if the lb agent removes the tap device
                #   right after step 1). Then libvirt will add it to the bridge
                #   again in step 2).
                # New lb implementation:
                #   The race could occur if the lb-agent sets the taps device
                #   state to down right after step 2). In step 3) libvirt
                #   might set it to up again.
                #
                # This is not an issue if an instance is booted with a port
                # configured with admin_state_up = True. Libvirt would just
                # set the tap device up again.
                #
                # This refactoring is recommended for the following reasons:
                # 1) An existing race with libvirt caused by the behavior of
                #    the old implementation. See Bug #1312016
                # 2) The new code is much more readable
                self._ensure_port_admin_state(device_details['port_id'],
                                              device_details['admin_state_up'])
                # update plugin about port status if admin_state is up
                if device_details['admin_state_up']:
                    if tap_in_bridge:
                        self.plugin_rpc.update_device_up(
                            self.context, device, self.agent_id, cfg.CONF.host)
                    else:
                        self.plugin_rpc.update_device_down(
                            self.context, device, self.agent_id, cfg.CONF.host)
            else:
                LOG.info(_LI("Device %s not defined on plugin"), device)
        return False
Beispiel #9
0
    def _test_port_add_arp_spoofing(self, vif, port):
        mac_addresses = {port['mac_address']}
        ip_addresses = {p['ip_address'] for p in port['fixed_ips']}
        if port.get('allowed_address_pairs'):
            mac_addresses |= {p['mac_address']
                              for p in port['allowed_address_pairs']}
            ip_addresses |= {p['ip_address']
                             for p in port['allowed_address_pairs']}
        spoof_chain = arp_protect.SPOOF_CHAIN_PREFIX + vif
        mac_chain = arp_protect.MAC_CHAIN_PREFIX + vif

        expected = [
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True),
            mock.ANY,
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
                       'neutronMAC-%s' % vif, '-P', 'DROP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True),
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
                       'neutronMAC-%s' % vif, '-j', 'DROP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True),
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-I',
                       'PREROUTING', '-i', vif, '-j', mac_chain],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True),
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-I',
                       mac_chain, '-i', vif,
                       '--among-src', '%s' % ','.join(sorted(mac_addresses)),
                       '-j', 'RETURN'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True),
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
                       spoof_chain, '-P', 'DROP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True),
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
                       spoof_chain, '-j', 'DROP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True)
        ]
        for addr in sorted(ip_addresses):
            expected.extend([
                mock.call(['ebtables', '-t', 'nat', '--concurrent', '-I',
                           spoof_chain, '-p', 'ARP',
                           '--arp-ip-src', addr, '-j', 'ACCEPT'],
                          check_exit_code=True, extra_ok_codes=None,
                          log_fail_as_error=True, run_as_root=True,
                          privsep_exec=True),
            ])
        expected.extend([
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
                       'PREROUTING', '-i', vif, '-j',
                       spoof_chain, '-p', 'ARP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True,
                      privsep_exec=True),
        ])

        arp_protect.setup_arp_spoofing_protection(vif, port)
        self.execute.assert_has_calls(expected)
Beispiel #10
0
 def test_port_trusted(self, dasp):
     arp_protect.setup_arp_spoofing_protection(VIF, PORT_TRUSTED)
     dasp.assert_called_with([VIF])
Beispiel #11
0
 def test_port_no_security(self, dasp):
     arp_protect.setup_arp_spoofing_protection(VIF, PORT_NO_SEC)
     dasp.assert_called_with([VIF])
    def treat_devices_added_updated(self, devices):
        try:
            devices_details_list = self.plugin_rpc.get_devices_details_list(
                self.context, devices, self.agent_id)
        except Exception:
            LOG.exception(_LE("Unable to get port details for %s"), devices)
            # resync is needed
            return True

        for device_details in devices_details_list:
            device = device_details['device']
            LOG.debug("Port %s added", device)

            if 'port_id' in device_details:
                LOG.info(_LI("Port %(device)s updated. Details: %(details)s"),
                         {'device': device, 'details': device_details})
                if self.prevent_arp_spoofing:
                    port = self.br_mgr.get_tap_device_name(
                        device_details['port_id'])
                    arp_protect.setup_arp_spoofing_protection(port,
                                                              device_details)
                # create the networking for the port
                network_type = device_details.get('network_type')
                segmentation_id = device_details.get('segmentation_id')
                tap_in_bridge = self.br_mgr.add_interface(
                    device_details['network_id'], network_type,
                    device_details['physical_network'], segmentation_id,
                    device_details['port_id'], device_details['device_owner'])
                # REVISIT(scheuran): Changed the way how ports admin_state_up
                # is implemented.
                #
                # Old lb implementation:
                # - admin_state_up: ensure that tap is plugged into bridge
                # - admin_state_down: remove tap from bridge
                # New lb implementation:
                # - admin_state_up: set tap device state to up
                # - admin_state_down: set tap device stae to down
                #
                # However both approaches could result in races with
                # nova/libvirt and therefore to an invalid system state in the
                # scenario, where an instance is booted with a port configured
                # with admin_state_up = False:
                #
                # Libvirt does the following actions in exactly
                # this order (see libvirt virnetdevtap.c)
                #     1) Create the tap device, set its MAC and MTU
                #     2) Plug the tap into the bridge
                #     3) Set the tap online
                #
                # Old lb implementation:
                #   A race could occur, if the lb agent removes the tap device
                #   right after step 1). Then libvirt will add it to the bridge
                #   again in step 2).
                # New lb implementation:
                #   The race could occur if the lb-agent sets the taps device
                #   state to down right after step 2). In step 3) libvirt
                #   might set it to up again.
                #
                # This is not an issue if an instance is booted with a port
                # configured with admin_state_up = True. Libvirt would just
                # set the tap device up again.
                #
                # This refactoring is recommended for the following reasons:
                # 1) An existing race with libvirt caused by the behavior of
                #    the old implementation. See Bug #1312016
                # 2) The new code is much more readable
                self._ensure_port_admin_state(device_details['port_id'],
                                              device_details['admin_state_up'])
                # update plugin about port status if admin_state is up
                if device_details['admin_state_up']:
                    if tap_in_bridge:
                        self.plugin_rpc.update_device_up(self.context,
                                                         device,
                                                         self.agent_id,
                                                         cfg.CONF.host)
                    else:
                        self.plugin_rpc.update_device_down(self.context,
                                                           device,
                                                           self.agent_id,
                                                           cfg.CONF.host)
            else:
                LOG.info(_LI("Device %s not defined on plugin"), device)
        return False
Beispiel #13
0
    def _test_port_add_arp_spoofing(self, vif, port):
        mac_addresses = {port['mac_address']}
        ip_addresses = {p['ip_address'] for p in port['fixed_ips']}
        if port.get('allowed_address_pairs'):
            mac_addresses |= {p['mac_address']
                              for p in port['allowed_address_pairs']}
            ip_addresses |= {p['ip_address']
                             for p in port['allowed_address_pairs']}
        spoof_chain = arp_protect.SPOOF_CHAIN_PREFIX + vif
        mac_chain = arp_protect.MAC_CHAIN_PREFIX + vif

        expected = [
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-L'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True),
            mock.ANY,
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
                       'neutronMAC-%s' % vif, '-P', 'DROP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True),
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
                       'PREROUTING', '-i', vif, '-j', mac_chain],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True),
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
                       mac_chain, '-i', vif,
                       '--among-src', '%s' % ','.join(sorted(mac_addresses)),
                       '-j', 'RETURN'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True),
            mock.ANY,
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-N',
                       spoof_chain, '-P', 'DROP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True),
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-F',
                       spoof_chain],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True),
        ]
        for addr in sorted(ip_addresses):
            expected.extend([
                mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
                           spoof_chain, '-p', 'ARP',
                           '--arp-ip-src', addr, '-j', 'ACCEPT'],
                          check_exit_code=True, extra_ok_codes=None,
                          log_fail_as_error=True, run_as_root=True),
            ])
        expected.extend([
            mock.ANY,
            mock.call(['ebtables', '-t', 'nat', '--concurrent', '-A',
                       'PREROUTING', '-i', vif, '-j',
                       spoof_chain, '-p', 'ARP'],
                      check_exit_code=True, extra_ok_codes=None,
                      log_fail_as_error=True, run_as_root=True),
        ])

        arp_protect.setup_arp_spoofing_protection(vif, port)
        self.execute.assert_has_calls(expected)
Beispiel #14
0
 def test_port_trusted(self, dasp):
     arp_protect.setup_arp_spoofing_protection(VIF, PORT_TRUSTED)
     dasp.assert_called_with([VIF])
Beispiel #15
0
 def test_port_no_security(self, dasp):
     arp_protect.setup_arp_spoofing_protection(VIF, PORT_NO_SEC)
     dasp.assert_called_with([VIF])