commit d912c703e94c6320b66c220c2ad167719a48c26a Author: Rajat Dhasmana Date: Thu Sep 17 08:36:00 2020 +0000 Add support for system and domain scoped tokens Currently we request to keystone via the project scoped tokens only even if the context has system scope. This patch converts the keystone request to system/domain/project scoped tokens as requested in the context. Change-Id: Ie2f124d9ef7d4d69d69bc03880644612cd338e01 (cherry picked from commit 568b279a85fe40a7bd20359293c4c15874b90b63) diff --git a/cinder/quota_utils.py b/cinder/quota_utils.py index 3617fe4..5ac35df 100644 --- a/cinder/quota_utils.py +++ b/cinder/quota_utils.py @@ -228,10 +228,30 @@ def _keystone_client(context, version=(3, 0)): :param version: version of Keystone to request :return: keystoneclient.client.Client object """ - auth_plugin = identity.Token( - auth_url=CONF.keystone_authtoken.auth_url, - token=context.auth_token, - project_id=context.project_id) + if context.system_scope is not None: + auth_plugin = identity.Token( + auth_url=CONF.keystone_authtoken.auth_url, + token=context.auth_token, + system_scope=context.system_scope + ) + elif context.domain_id is not None: + auth_plugin = identity.Token( + auth_url=CONF.keystone_authtoken.auth_url, + token=context.auth_token, + domain_id=context.domain_id + ) + elif context.project_id is not None: + auth_plugin = identity.Token( + auth_url=CONF.keystone_authtoken.auth_url, + token=context.auth_token, + project_id=context.project_id + ) + else: + # We're dealing with an unscoped token from keystone that doesn't + # carry any authoritative power outside of the user simplify proving + # they know their own password. This token isn't associated with any + # authorization target (e.g., system, domain, or project). + auth_plugin = context.get_auth_plugin() client_session = ka_loading.session.Session().load_from_options( auth=auth_plugin, diff --git a/cinder/tests/unit/test_quota_utils.py b/cinder/tests/unit/test_quota_utils.py index 977f45f..1fad96d 100644 --- a/cinder/tests/unit/test_quota_utils.py +++ b/cinder/tests/unit/test_quota_utils.py @@ -22,6 +22,7 @@ from oslo_config import fixture as config_fixture from cinder import context from cinder import exception from cinder import quota_utils +from cinder.tests.unit import fake_constants as fake from cinder.tests.unit import test @@ -55,6 +56,42 @@ class QuotaUtilsTest(test.TestCase): version=(3, 0)) @mock.patch('keystoneclient.client.Client') + @mock.patch('keystoneauth1.session.Session') + @mock.patch('keystoneauth1.identity.Token') + def test_keystone_client_instantiation_system_scope( + self, ks_token, ksclient_session, ksclient_class): + system_context = context.RequestContext( + 'fake_user', 'fake_proj_id', system_scope='all') + quota_utils._keystone_client(system_context) + ks_token.assert_called_once_with( + auth_url=self.auth_url, token=system_context.auth_token, + system_scope=system_context.system_scope) + + @mock.patch('keystoneclient.client.Client') + @mock.patch('keystoneauth1.session.Session') + @mock.patch('keystoneauth1.identity.Token') + def test_keystone_client_instantiation_domain_scope( + self, ks_token, ksclient_session, ksclient_class): + domain_context = context.RequestContext( + 'fake_user', 'fake_proj_id', domain_id='default') + quota_utils._keystone_client(domain_context) + ks_token.assert_called_once_with( + auth_url=self.auth_url, token=domain_context.auth_token, + domain_id=domain_context.domain_id) + + @mock.patch('keystoneclient.client.Client') + @mock.patch('keystoneauth1.session.Session') + @mock.patch('keystoneauth1.identity.Token') + def test_keystone_client_instantiation_project_scope( + self, ks_token, ksclient_session, ksclient_class): + project_context = context.RequestContext( + 'fake_user', project_id=fake.PROJECT_ID) + quota_utils._keystone_client(project_context) + ks_token.assert_called_once_with( + auth_url=self.auth_url, token=project_context.auth_token, + project_id=project_context.project_id) + + @mock.patch('keystoneclient.client.Client') def test_get_project_keystoneclient_v2(self, ksclient_class): keystoneclient = ksclient_class.return_value keystoneclient.version = 'v2.0'