diff options
-rw-r--r-- | openstack_auth/plugin/base.py | 38 | ||||
-rw-r--r-- | openstack_auth/tests/tests.py | 63 |
2 files changed, 83 insertions, 18 deletions
diff --git a/openstack_auth/plugin/base.py b/openstack_auth/plugin/base.py index 5172329..4b520b4 100644 --- a/openstack_auth/plugin/base.py +++ b/openstack_auth/plugin/base.py @@ -98,6 +98,18 @@ class BasePlugin(object): msg = _('Unable to retrieve authorized projects.') raise exceptions.KeystoneAuthException(msg) + def list_domains(self, session, auth_plugin, auth_ref=None): + try: + if self.keystone_version >= 3: + client = v3_client.Client(session=session, auth=auth_plugin) + return client.auth.domains() + else: + return [] + except (keystone_exceptions.ClientException, + keystone_exceptions.AuthorizationFailure): + msg = _('Unable to retrieve authorized domains.') + raise exceptions.KeystoneAuthException(msg) + def get_access_info(self, keystone_auth): """Get the access info from an unscoped auth @@ -190,22 +202,36 @@ class BasePlugin(object): session = utils.get_session() auth_url = unscoped_auth.auth_url - if not domain_name or utils.get_keystone_version() < 3: + if utils.get_keystone_version() < 3: return None, None + if domain_name: + domains = [domain_name] + else: + domains = self.list_domains(session, + unscoped_auth, + unscoped_auth_ref) + domains = [domain.name for domain in domains if domain.enabled] # domain support can require domain scoped tokens to perform # identity operations depending on the policy files being used # for keystone. domain_auth = None domain_auth_ref = None - try: + for domain_name in domains: token = unscoped_auth_ref.auth_token domain_auth = utils.get_token_auth_plugin( auth_url, token, domain_name=domain_name) - domain_auth_ref = domain_auth.get_access(session) - except (keystone_exceptions.ClientException, - keystone_exceptions.AuthorizationFailure): - LOG.debug('Error getting domain scoped token.', exc_info=True) + try: + domain_auth_ref = domain_auth.get_access(session) + except (keystone_exceptions.ClientException, + keystone_exceptions.AuthorizationFailure): + pass + else: + if len(domains) > 1: + LOG.info("More than one valid domain found for user %s," + " scoping to %s" % + (unscoped_auth_ref.user_id, domain_name)) + break return domain_auth, domain_auth_ref diff --git a/openstack_auth/tests/tests.py b/openstack_auth/tests/tests.py index 45adf2e..4790f73 100644 --- a/openstack_auth/tests/tests.py +++ b/openstack_auth/tests/tests.py @@ -108,25 +108,45 @@ class OpenStackAuthFederatedTestsMixin(object): client.federation.projects = self.mox.CreateMockAnything() client.federation.projects.list().AndReturn(projects) + def _mock_unscoped_list_domains(self, client, domains): + client.auth = self.mox.CreateMockAnything() + client.auth.domains().AndReturn(domains) + def _mock_unscoped_token_client(self, unscoped, auth_url=None, - client=True): + client=True, plugin=None): if not auth_url: auth_url = settings.OPENSTACK_KEYSTONE_URL - plugin = self._create_token_auth( - None, - token=unscoped.auth_token, - url=auth_url) - plugin.get_access(mox.IsA(session.Session)).AndReturn(unscoped) + if unscoped and not plugin: + plugin = self._create_token_auth( + None, + token=unscoped.auth_token, + url=auth_url) + plugin.get_access(mox.IsA(session.Session)).AndReturn(unscoped) plugin.auth_url = auth_url if client: return self.ks_client_module.Client( session=mox.IsA(session.Session), auth=plugin) - def _mock_federated_client_list_projects(self, unscoped, projects): - client = self._mock_unscoped_token_client(unscoped) + def _mock_plugin(self, unscoped, auth_url=None): + if not auth_url: + auth_url = settings.OPENSTACK_KEYSTONE_URL + plugin = self._create_token_auth( + None, + token=unscoped.auth_token, + url=auth_url) + plugin.get_access(mox.IsA(session.Session)).AndReturn(unscoped) + plugin.auth_url = settings.OPENSTACK_KEYSTONE_URL + return plugin + + def _mock_federated_client_list_projects(self, unscoped_auth, projects): + client = self._mock_unscoped_token_client(None, plugin=unscoped_auth) self._mock_unscoped_federated_list_projects(client, projects) + def _mock_federated_client_list_domains(self, unscoped_auth, domains): + client = self._mock_unscoped_token_client(None, plugin=unscoped_auth) + self._mock_unscoped_list_domains(client, domains) + class OpenStackAuthTestsV2(OpenStackAuthTestsMixin, test.TestCase): @@ -885,6 +905,7 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin, self.data = data_v3.generate_test_data(service_providers=True) self.sp_data = data_v3.generate_test_data(endpoint='http://sp2') projects = [self.data.project_one, self.data.project_two] + domains = [] user = self.data.user unscoped = self.data.unscoped_access_info form_data = self.get_form_data(user) @@ -925,7 +946,13 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin, # mock authenticate for service provider sp_projects = [self.sp_data.project_one, self.sp_data.project_two] sp_unscoped = self.sp_data.federated_unscoped_access_info - client = self._mock_unscoped_token_client(sp_unscoped, plugin.auth_url) + sp_unscoped_auth = self._mock_plugin(sp_unscoped, + auth_url=plugin.auth_url) + client = self._mock_unscoped_token_client(None, plugin.auth_url, + plugin=sp_unscoped_auth) + self._mock_unscoped_list_domains(client, domains) + client = self._mock_unscoped_token_client(None, plugin.auth_url, + plugin=sp_unscoped_auth) self._mock_unscoped_federated_list_projects(client, sp_projects) self._mock_scoped_client_for_tenant(sp_unscoped, self.sp_data.project_one.id, @@ -961,6 +988,7 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin, self.data = data_v3.generate_test_data(service_providers=True) keystone_provider = 'localkeystone' projects = [self.data.project_one, self.data.project_two] + domains = [] user = self.data.user unscoped = self.data.unscoped_access_info form_data = self.get_form_data(user) @@ -971,7 +999,12 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin, self._mock_unscoped_token_client(unscoped, auth_url=auth_url, client=False) - client = self._mock_unscoped_token_client(unscoped, auth_url) + unscoped_auth = self._mock_plugin(unscoped) + client = self._mock_unscoped_token_client(None, auth_url=auth_url, + plugin=unscoped_auth) + self._mock_unscoped_list_domains(client, domains) + client = self._mock_unscoped_token_client(None, auth_url=auth_url, + plugin=unscoped_auth) self._mock_unscoped_list_projects(client, user, projects) self._mock_scoped_client_for_tenant(unscoped, self.data.project_one.id) @@ -1154,11 +1187,14 @@ class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin, def test_websso_login(self): projects = [self.data.project_one, self.data.project_two] + domains = [] unscoped = self.data.federated_unscoped_access_info token = unscoped.auth_token + unscoped_auth = self._mock_plugin(unscoped) form_data = {'token': token} - self._mock_federated_client_list_projects(unscoped, projects) + self._mock_federated_client_list_domains(unscoped_auth, domains) + self._mock_federated_client_list_projects(unscoped_auth, projects) self._mock_scoped_client_for_tenant(unscoped, self.data.project_one.id) self.mox.ReplayAll() @@ -1173,11 +1209,14 @@ class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin, settings.OPENSTACK_KEYSTONE_URL = 'http://auth.openstack.org:5000/v3' projects = [self.data.project_one, self.data.project_two] + domains = [] unscoped = self.data.federated_unscoped_access_info token = unscoped.auth_token + unscoped_auth = self._mock_plugin(unscoped) form_data = {'token': token} - self._mock_federated_client_list_projects(unscoped, projects) + self._mock_federated_client_list_domains(unscoped_auth, domains) + self._mock_federated_client_list_projects(unscoped_auth, projects) self._mock_scoped_client_for_tenant(unscoped, self.data.project_one.id) self.mox.ReplayAll() |