Bay can not be deleted by other users in the same project

Trust can only be deleted by the user who creates it. So when
other users in the same project want to delete the bay, we need
use the trustee which can impersonate the trustor to delete the
trust.

Change-Id: I9f87cdf07066d316722e798cd0755f0fff5c2a02
Closes-Bug: #1552457
This commit is contained in:
Hua Wang 2016-03-16 18:54:51 +08:00
parent ee059477be
commit e79d4a182f
5 changed files with 38 additions and 14 deletions

View File

@ -187,16 +187,30 @@ class KeystoneClientV3(object):
trustee_user_id=trustee_user) trustee_user_id=trustee_user)
return trust return trust
def delete_trust(self, trust_id): def delete_trust(self, context, bay):
if trust_id is None: if bay.trust_id is None:
return return
# Trust can only be deleted by the user who creates it. So when
# other users in the same project want to delete the bay, we need
# use the trustee which can impersonate the trustor to delete the
# trust.
if context.user_id == bay.user_id:
client = self.client
else:
auth = ka_v3.Password(auth_url=self.auth_url,
user_id=bay.trustee_user_id,
password=bay.trustee_password,
trust_id=bay.trust_id)
sess = ka_session.Session(auth=auth)
client = kc_v3.Client(session=sess)
try: try:
self.client.trusts.delete(trust_id) client.trusts.delete(bay.trust_id)
except kc_exception.NotFound: except kc_exception.NotFound:
pass pass
except Exception: except Exception:
LOG.exception(_LE('Failed to delete trust')) LOG.exception(_LE('Failed to delete trust'))
raise exception.TrustDeleteFailed(trust_id=trust_id) raise exception.TrustDeleteFailed(trust_id=bay.trust_id)
def create_trustee(self, username, password, domain_id): def create_trustee(self, username, password, domain_id):
try: try:

View File

@ -199,7 +199,7 @@ class Handler(object):
LOG.info(_LI('The stack %s was not be found during bay' LOG.info(_LI('The stack %s was not be found during bay'
' deletion.'), stack_id) ' deletion.'), stack_id)
try: try:
trust_manager.delete_trustee_and_trust(osc, bay) trust_manager.delete_trustee_and_trust(osc, context, bay)
cert_manager.delete_certificates_from_bay(bay) cert_manager.delete_certificates_from_bay(bay)
bay.destroy() bay.destroy()
except exception.BayNotFound: except exception.BayNotFound:
@ -282,6 +282,7 @@ class HeatPoller(object):
% self.bay.stack_id) % self.bay.stack_id)
try: try:
trust_manager.delete_trustee_and_trust(self.openstack_client, trust_manager.delete_trustee_and_trust(self.openstack_client,
self.context,
self.bay) self.bay)
cert_manager.delete_certificates_from_bay(self.bay) cert_manager.delete_certificates_from_bay(self.bay)
self.bay.destroy() self.bay.destroy()

View File

@ -42,11 +42,11 @@ def create_trustee_and_trust(osc, bay):
raise exception.TrusteeOrTrustToBayFailed(bay_uuid=bay.uuid) raise exception.TrusteeOrTrustToBayFailed(bay_uuid=bay.uuid)
def delete_trustee_and_trust(osc, bay): def delete_trustee_and_trust(osc, context, bay):
try: try:
# The bay which is upgraded from Liberty doesn't have trust_id # The bay which is upgraded from Liberty doesn't have trust_id
if bay.trust_id: if bay.trust_id:
osc.keystone().delete_trust(bay.trust_id) osc.keystone().delete_trust(context, bay)
except Exception: except Exception:
# Exceptions are already logged by keystone().delete_trust # Exceptions are already logged by keystone().delete_trust
pass pass

View File

@ -112,14 +112,18 @@ class KeystoneClientTest(base.TestCase):
def test_delete_trust(self, mock_ks): def test_delete_trust(self, mock_ks):
mock_ks.return_value.trusts.delete.return_value = None mock_ks.return_value.trusts.delete.return_value = None
ks_client = keystone.KeystoneClientV3(self.ctx) ks_client = keystone.KeystoneClientV3(self.ctx)
self.assertIsNone(ks_client.delete_trust(trust_id='atrust123')) bay = mock.MagicMock()
bay.trust_id = 'atrust123'
self.assertIsNone(ks_client.delete_trust(self.ctx, bay))
mock_ks.return_value.trusts.delete.assert_called_once_with('atrust123') mock_ks.return_value.trusts.delete.assert_called_once_with('atrust123')
def test_delete_trust_not_found(self, mock_ks): def test_delete_trust_not_found(self, mock_ks):
mock_delete = mock_ks.return_value.trusts.delete mock_delete = mock_ks.return_value.trusts.delete
mock_delete.side_effect = kc_exception.NotFound() mock_delete.side_effect = kc_exception.NotFound()
ks_client = keystone.KeystoneClientV3(self.ctx) ks_client = keystone.KeystoneClientV3(self.ctx)
self.assertIsNone(ks_client.delete_trust(trust_id='atrust123')) bay = mock.MagicMock()
bay.trust_id = 'atrust123'
self.assertIsNone(ks_client.delete_trust(self.ctx, bay))
@mock.patch('magnum.common.keystone.ka_session.Session') @mock.patch('magnum.common.keystone.ka_session.Session')
def test_create_trust_with_all_roles(self, mock_session, mock_ks): def test_create_trust_with_all_roles(self, mock_session, mock_ks):

View File

@ -84,11 +84,13 @@ class TrustManagerTestCase(base.BaseTestCase):
mock_bay.trustee_user_id = 'trustee_user_id' mock_bay.trustee_user_id = 'trustee_user_id'
mock_keystone = mock.MagicMock() mock_keystone = mock.MagicMock()
self.osc.keystone.return_value = mock_keystone self.osc.keystone.return_value = mock_keystone
context = mock.MagicMock()
trust_manager.delete_trustee_and_trust(self.osc, mock_bay) trust_manager.delete_trustee_and_trust(self.osc, context,
mock_bay)
mock_keystone.delete_trust.assert_called_once_with( mock_keystone.delete_trust.assert_called_once_with(
mock_bay.trust_id, context, mock_bay
) )
mock_keystone.delete_trustee.assert_called_once_with( mock_keystone.delete_trustee.assert_called_once_with(
mock_bay.trustee_user_id, mock_bay.trustee_user_id,
@ -100,8 +102,10 @@ class TrustManagerTestCase(base.BaseTestCase):
mock_bay.trustee_user_id = 'trustee_user_id' mock_bay.trustee_user_id = 'trustee_user_id'
mock_keystone = mock.MagicMock() mock_keystone = mock.MagicMock()
self.osc.keystone.return_value = mock_keystone self.osc.keystone.return_value = mock_keystone
context = mock.MagicMock()
trust_manager.delete_trustee_and_trust(self.osc, mock_bay) trust_manager.delete_trustee_and_trust(self.osc, context,
mock_bay)
self.assertEqual(0, mock_keystone.delete_trust.call_count) self.assertEqual(0, mock_keystone.delete_trust.call_count)
mock_keystone.delete_trustee.assert_called_once_with( mock_keystone.delete_trustee.assert_called_once_with(
@ -114,10 +118,11 @@ class TrustManagerTestCase(base.BaseTestCase):
mock_bay.trustee_user_id = None mock_bay.trustee_user_id = None
mock_keystone = mock.MagicMock() mock_keystone = mock.MagicMock()
self.osc.keystone.return_value = mock_keystone self.osc.keystone.return_value = mock_keystone
context = mock.MagicMock()
trust_manager.delete_trustee_and_trust(self.osc, mock_bay) trust_manager.delete_trustee_and_trust(self.osc, context, mock_bay)
mock_keystone.delete_trust.assert_called_once_with( mock_keystone.delete_trust.assert_called_once_with(
mock_bay.trust_id, context, mock_bay
) )
self.assertEqual(0, mock_keystone.delete_trustee.call_count) self.assertEqual(0, mock_keystone.delete_trustee.call_count)