From 99817ff46b71ff389e218f240115d7c2ea40785b Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Wed, 14 May 2014 15:15:05 -0700 Subject: [PATCH] Ensure tenant owns devices when creating a gateway This patch adds an ownership check in the create_gateway method. This kind of check can hardly be enforced leveraging the policy engine. Change-Id: Iffdc9c570d688f824374281b37efd23761883d26 Closes-Bug: 1319583 --- neutron/plugins/vmware/dbexts/networkgw_db.py | 34 +++++++++++------- .../unit/vmware/extensions/test_networkgw.py | 35 +++++++++++++++---- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/neutron/plugins/vmware/dbexts/networkgw_db.py b/neutron/plugins/vmware/dbexts/networkgw_db.py index dd1ec85f8..67a40c255 100644 --- a/neutron/plugins/vmware/dbexts/networkgw_db.py +++ b/neutron/plugins/vmware/dbexts/networkgw_db.py @@ -259,9 +259,12 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): tenant_id=tenant_id, name=gw_data.get('name')) # Device list is guaranteed to be a valid list - # TODO(salv-orlando): Enforce that gateway device identifiers - # in this list are among the tenant's NSX network gateway devices - # to avoid risk a tenant 'guessing' other tenant's network devices + device_query = self._query_gateway_devices( + context, filters={'id': [device['id'] + for device in gw_data['devices']]}) + for device in device_query: + if device['tenant_id'] != tenant_id: + raise GatewayDeviceNotFound(device_id=device['id']) gw_db.devices.extend([NetworkGatewayDeviceReference(**device) for device in gw_data['devices']]) context.session.add(gw_db) @@ -443,18 +446,25 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): self._get_gateway_device(context, device_id), fields, include_nsx_id) + def _query_gateway_devices(self, context, + filters=None, sorts=None, + limit=None, marker=None, + page_reverse=None): + marker_obj = self._get_marker_obj( + context, 'gateway_device', limit, marker) + return self._get_collection_query(context, + NetworkGatewayDevice, + filters=filters, + sorts=sorts, + limit=limit, + marker_obj=marker_obj, + page_reverse=page_reverse) + def get_gateway_devices(self, context, filters=None, fields=None, sorts=None, limit=None, marker=None, page_reverse=False, include_nsx_id=False): - marker_obj = self._get_marker_obj( - context, 'gateway_device', limit, marker) - query = self._get_collection_query(context, - NetworkGatewayDevice, - filters=filters, - sorts=sorts, - limit=limit, - marker_obj=marker_obj, - page_reverse=page_reverse) + query = self._query_gateway_devices(context, filters, sorts, limit, + marker, page_reverse) return [self._make_gateway_device_dict(row, fields, include_nsx_id) for row in query] diff --git a/neutron/tests/unit/vmware/extensions/test_networkgw.py b/neutron/tests/unit/vmware/extensions/test_networkgw.py index a7371dada..6b0df2fa4 100644 --- a/neutron/tests/unit/vmware/extensions/test_networkgw.py +++ b/neutron/tests/unit/vmware/extensions/test_networkgw.py @@ -513,37 +513,58 @@ class NetworkGatewayDbTestCase(test_db_plugin.NeutronDbPluginV2TestCase): expected_code=exc.HTTPNotFound.code) def test_create_network_gateway(self): + tenant_id = _uuid() with contextlib.nested( - self._gateway_device(name='dev_1'), - self._gateway_device(name='dev_2')) as (dev_1, dev_2): + self._gateway_device(name='dev_1', + tenant_id=tenant_id), + self._gateway_device(name='dev_2', + tenant_id=tenant_id)) as (dev_1, dev_2): name = 'test-gw' dev_1_id = dev_1[self.dev_resource]['id'] dev_2_id = dev_2[self.dev_resource]['id'] devices = [{'id': dev_1_id, 'interface_name': 'xxx'}, {'id': dev_2_id, 'interface_name': 'yyy'}] keys = [('devices', devices), ('name', name)] - with self._network_gateway(name=name, devices=devices) as gw: + with self._network_gateway(name=name, + devices=devices, + tenant_id=tenant_id) as gw: for k, v in keys: self.assertEqual(gw[self.gw_resource][k], v) def test_create_network_gateway_no_interface_name(self): - with self._gateway_device() as dev: + tenant_id = _uuid() + with self._gateway_device(tenant_id=tenant_id) as dev: name = 'test-gw' devices = [{'id': dev[self.dev_resource]['id']}] exp_devices = devices exp_devices[0]['interface_name'] = 'breth0' keys = [('devices', exp_devices), ('name', name)] - with self._network_gateway(name=name, devices=devices) as gw: + with self._network_gateway(name=name, + devices=devices, + tenant_id=tenant_id) as gw: for k, v in keys: self.assertEqual(gw[self.gw_resource][k], v) + def test_create_network_gateway_not_owned_device_raises_404(self): + # Create a device with a different tenant identifier + with self._gateway_device(name='dev', tenant_id=_uuid()) as dev: + name = 'test-gw' + dev_id = dev[self.dev_resource]['id'] + devices = [{'id': dev_id, 'interface_name': 'xxx'}] + res = self._create_network_gateway( + 'json', _uuid(), name=name, devices=devices) + self.assertEqual(404, res.status_int) + def test_delete_network_gateway(self): - with self._gateway_device() as dev: + tenant_id = _uuid() + with self._gateway_device(tenant_id=tenant_id) as dev: name = 'test-gw' device_id = dev[self.dev_resource]['id'] devices = [{'id': device_id, 'interface_name': 'xxx'}] - with self._network_gateway(name=name, devices=devices) as gw: + with self._network_gateway(name=name, + devices=devices, + tenant_id=tenant_id) as gw: # Nothing to do here - just let the gateway go gw_id = gw[self.gw_resource]['id'] # Verify nothing left on db -- 2.45.2