diff --git a/neutron/db/securitygroups_db.py b/neutron/db/securitygroups_db.py index de5019ccc13..79ef88b062a 100644 --- a/neutron/db/securitygroups_db.py +++ b/neutron/db/securitygroups_db.py @@ -915,6 +915,10 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase, :returns: the default security group id for given tenant. """ + # Do not allow a tenant to create a default SG for another one. + # See Bug 1987410. + if tenant_id != context.tenant_id and not context.is_admin: + return if not extensions.is_extension_supported(self, 'security-group'): return default_group_id = self._get_default_sg_id(context, tenant_id) diff --git a/neutron/tests/unit/db/test_securitygroups_db.py b/neutron/tests/unit/db/test_securitygroups_db.py index 98dc5a60bf9..e3e781e52e7 100644 --- a/neutron/tests/unit/db/test_securitygroups_db.py +++ b/neutron/tests/unit/db/test_securitygroups_db.py @@ -617,3 +617,15 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase): self.mixin._ensure_default_security_group(self.ctx, 'tenant_1') create_sg.assert_not_called() get_default_sg_id.assert_not_called() + + def test__ensure_default_security_group_tenant_mismatch(self): + with mock.patch.object( + self.mixin, '_get_default_sg_id') as get_default_sg_id,\ + mock.patch.object( + self.mixin, 'create_security_group') as create_sg: + context = mock.Mock() + context.tenant_id = 'tenant_0' + context.is_admin = False + self.mixin._ensure_default_security_group(context, 'tenant_1') + create_sg.assert_not_called() + get_default_sg_id.assert_not_called()