[RBAC] Fix setting network as not shared

In case when network was shared with specified project
by RBAC rule and it was also set as "shared" there was
a bug which forbid to set such network as not shared even
if only projects which still used network was owner and
project with specified RBAC rule.

This patch fixes it by adding additional check in
NeutronDbPluginV2._validate_shared_update() in such case.

Change-Id: I6ab05a8f0ece454f5bef8ba978af05f5fa1354d8
Closes-Bug: #1764330
This commit is contained in:
Sławek Kapłoński 2018-04-16 13:17:17 +02:00
parent fb75ce0319
commit 7aa941cc09
2 changed files with 49 additions and 2 deletions

View File

@ -278,8 +278,23 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
# raise if multiple tenants found or if the only tenant found
# is not the owner of the network
if (len(tenant_ids) > 1 or len(tenant_ids) == 1 and
tenant_ids.pop() != original.tenant_id):
raise n_exc.InvalidSharedSetting(network=original.name)
original.tenant_id not in tenant_ids):
self._validate_projects_have_access_to_network(
original, tenant_ids)
def _validate_projects_have_access_to_network(self, network, project_ids):
ctx_admin = ctx.get_admin_context()
rb_model = rbac_db.NetworkRBAC
other_rbac_entries = model_query.query_with_hooks(
ctx_admin, rb_model).filter(
and_(rb_model.object_id == network.id,
rb_model.action == 'access_as_shared',
rb_model.target_tenant != "*"))
allowed_projects = {entry['target_tenant']
for entry in other_rbac_entries}
allowed_projects.add(network.project_id)
if project_ids - allowed_projects:
raise n_exc.InvalidSharedSetting(network=network.name)
def _validate_ipv6_attributes(self, subnet, cur_subnet):
if cur_subnet:

View File

@ -2684,6 +2684,38 @@ class TestNetworksV2(NeutronDbPluginV2TestCase):
port1 = self.deserialize(self.fmt, res1)
self._delete('ports', port1['port']['id'])
def test_update_network_set_not_shared_other_tenant_access_via_rbac(self):
with self.network(shared=True) as network:
ctx = context.get_admin_context()
with db_api.context_manager.writer.using(ctx):
ctx.session.add(
rbac_db_models.NetworkRBAC(
object_id=network['network']['id'],
action='access_as_shared',
tenant_id=network['network']['tenant_id'],
target_tenant='somebody_else')
)
ctx.session.add(
rbac_db_models.NetworkRBAC(
object_id=network['network']['id'],
action='access_as_shared',
tenant_id=network['network']['tenant_id'],
target_tenant='one_more_somebody_else')
)
res1 = self._create_port(self.fmt,
network['network']['id'],
webob.exc.HTTPCreated.code,
tenant_id='somebody_else',
set_context=True)
data = {'network': {'shared': False}}
req = self.new_update_request('networks',
data,
network['network']['id'])
res = self.deserialize(self.fmt, req.get_response(self.api))
self.assertFalse(res['network']['shared'])
port1 = self.deserialize(self.fmt, res1)
self._delete('ports', port1['port']['id'])
def test_update_network_set_not_shared_multi_tenants_returns_409(self):
with self.network(shared=True) as network:
res1 = self._create_port(self.fmt,