summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-07-13 02:20:20 +0000
committerGerrit Code Review <review@openstack.org>2018-07-13 02:20:20 +0000
commit13631ff187b6c2c6eec4f356a917288560dc5886 (patch)
tree321a78934d9553874e10188aba2897e6d44b8ba9
parent14a22799f54bcd2617aa30fe851518a146f90833 (diff)
parent54aa6e81cb17b33ce4d5d469cc11dec2869c762d (diff)
Merge "Disallow router interface out of subnet IP range"
-rw-r--r--neutron/db/l3_db.py26
-rw-r--r--neutron/tests/unit/extensions/test_l3.py56
2 files changed, 82 insertions, 0 deletions
diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py
index 3fe4c95..bc79d7a 100644
--- a/neutron/db/l3_db.py
+++ b/neutron/db/l3_db.py
@@ -692,6 +692,27 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
692 raise n_exc.BadRequest(resource='router', msg=msg) 692 raise n_exc.BadRequest(resource='router', msg=msg)
693 return port 693 return port
694 694
695 def _validate_port_in_range_or_admin(self, context, subnets, port):
696 if context.is_admin:
697 return
698 subnets_by_id = {}
699 for s in subnets:
700 addr_set = netaddr.IPSet()
701 for range in s['allocation_pools']:
702 addr_set.add(netaddr.IPRange(netaddr.IPAddress(range['start']),
703 netaddr.IPAddress(range['end'])))
704 subnets_by_id[s['id']] = (addr_set, s['project_id'],)
705 for subnet_id, ip in [(fix_ip['subnet_id'], fix_ip['ip_address'],)
706 for fix_ip in port['fixed_ips']]:
707 if (ip not in subnets_by_id[subnet_id][0] and
708 context.project_id != subnets_by_id[subnet_id][1]):
709 msg = (_('Cannot add interface to router because specified '
710 'port %(port)s has an IP address out of the '
711 'allocation pool of subnet %(subnet)s, which is not '
712 'owned by the project making the request') %
713 {'port': port['id'], 'subnet': subnet_id})
714 raise n_exc.BadRequest(resource='router', msg=msg)
715
695 def _validate_router_port_info(self, context, router, port_id): 716 def _validate_router_port_info(self, context, router, port_id):
696 with db_api.autonested_transaction(context.session): 717 with db_api.autonested_transaction(context.session):
697 # check again within transaction to mitigate race 718 # check again within transaction to mitigate race
@@ -727,6 +748,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
727 msg = _("Cannot have multiple " 748 msg = _("Cannot have multiple "
728 "IPv4 subnets on router port") 749 "IPv4 subnets on router port")
729 raise n_exc.BadRequest(resource='router', msg=msg) 750 raise n_exc.BadRequest(resource='router', msg=msg)
751 self._validate_port_in_range_or_admin(context, subnets, port)
730 return port, subnets 752 return port, subnets
731 753
732 def _notify_attaching_interface(self, context, router_db, port, 754 def _notify_attaching_interface(self, context, router_db, port,
@@ -788,6 +810,10 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
788 if not subnet['gateway_ip']: 810 if not subnet['gateway_ip']:
789 msg = _('Subnet for router interface must have a gateway IP') 811 msg = _('Subnet for router interface must have a gateway IP')
790 raise n_exc.BadRequest(resource='router', msg=msg) 812 raise n_exc.BadRequest(resource='router', msg=msg)
813 if subnet['project_id'] != context.project_id and not context.is_admin:
814 msg = (_('Cannot add interface to router because subnet %s is not '
815 'owned by project making the request') % subnet_id)
816 raise n_exc.BadRequest(resource='router', msg=msg)
791 if (subnet['ip_version'] == 6 and subnet['ipv6_ra_mode'] is None and 817 if (subnet['ip_version'] == 6 and subnet['ipv6_ra_mode'] is None and
792 subnet['ipv6_address_mode'] is not None): 818 subnet['ipv6_address_mode'] is not None):
793 msg = (_('IPv6 subnet %s configured to receive RAs from an ' 819 msg = (_('IPv6 subnet %s configured to receive RAs from an '
diff --git a/neutron/tests/unit/extensions/test_l3.py b/neutron/tests/unit/extensions/test_l3.py
index 6490195..e6a949c 100644
--- a/neutron/tests/unit/extensions/test_l3.py
+++ b/neutron/tests/unit/extensions/test_l3.py
@@ -1265,6 +1265,62 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
1265 expected_code=err_code, 1265 expected_code=err_code,
1266 tenant_id='bad_tenant') 1266 tenant_id='bad_tenant')
1267 1267
1268 def test_router_add_interface_by_subnet_other_tenant_subnet_returns_400(
1269 self):
1270 router_tenant_id = _uuid()
1271 with self.router(tenant_id=router_tenant_id, set_context=True) as r:
1272 with self.network(shared=True) as n:
1273 with self.subnet(network=n) as s:
1274 err_code = exc.HTTPBadRequest.code
1275 self._router_interface_action('add',
1276 r['router']['id'],
1277 s['subnet']['id'],
1278 None,
1279 expected_code=err_code,
1280 tenant_id=router_tenant_id)
1281
1282 def _test_router_add_interface_by_port_allocation_pool(
1283 self, out_of_pool=False, router_action_as_admin=False,
1284 expected_code=exc.HTTPOk.code):
1285 router_tenant_id = _uuid()
1286 with self.router(tenant_id=router_tenant_id, set_context=True) as r:
1287 with self.network(shared=True) as n:
1288 with self.subnet(network=n) as s1, (
1289 self.subnet(network=n, cidr='fd00::/64',
1290 ip_version=6)) as s2, (
1291 self.subnet(network=n, cidr='fd01::/64',
1292 ip_version=6)) as s3:
1293 fixed_ips = [{'subnet_id': s1['subnet']['id']},
1294 {'subnet_id': s2['subnet']['id']},
1295 {'subnet_id': s3['subnet']['id']}]
1296 if out_of_pool:
1297 fixed_ips[1] = {'subnet_id': s2['subnet']['id'],
1298 'ip_address':
1299 s2['subnet']['gateway_ip']}
1300 with self.port(subnet=s1, fixed_ips=fixed_ips,
1301 tenant_id=router_tenant_id,
1302 set_context=True) as p:
1303 kwargs = {'expected_code': expected_code}
1304 if not router_action_as_admin:
1305 kwargs['tenant_id'] = router_tenant_id
1306 self._router_interface_action(
1307 'add', r['router']['id'], None, p['port']['id'],
1308 **kwargs)
1309
1310 def test_router_add_interface_by_port_other_tenant_address_in_pool(
1311 self):
1312 self._test_router_add_interface_by_port_allocation_pool()
1313
1314 def test_router_add_interface_by_port_other_tenant_address_out_of_pool(
1315 self):
1316 self._test_router_add_interface_by_port_allocation_pool(
1317 out_of_pool=True, expected_code=exc.HTTPBadRequest.code)
1318
1319 def test_router_add_interface_by_port_admin_address_out_of_pool(
1320 self):
1321 self._test_router_add_interface_by_port_allocation_pool(
1322 out_of_pool=True, router_action_as_admin=True)
1323
1268 def test_router_add_interface_subnet_with_port_from_other_tenant(self): 1324 def test_router_add_interface_subnet_with_port_from_other_tenant(self):
1269 tenant_id = _uuid() 1325 tenant_id = _uuid()
1270 other_tenant_id = _uuid() 1326 other_tenant_id = _uuid()