Merge "Allow federated users to auth with domain scope"

This commit is contained in:
Jenkins 2017-01-27 16:19:26 +00:00 committed by Gerrit Code Review
commit 8afdc7c80e
2 changed files with 83 additions and 18 deletions

View File

@ -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

View File

@ -108,8 +108,27 @@ 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
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_plugin(self, unscoped, auth_url=None):
if not auth_url:
auth_url = settings.OPENSTACK_KEYSTONE_URL
plugin = self._create_token_auth(
@ -117,16 +136,17 @@ class OpenStackAuthFederatedTestsMixin(object):
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)
plugin.auth_url = settings.OPENSTACK_KEYSTONE_URL
return plugin
def _mock_federated_client_list_projects(self, unscoped, projects):
client = self._mock_unscoped_token_client(unscoped)
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()