Allow user list without specifying domain

With a single domain environment, users can be listed without
specifying a domain. When moving to a multiple domain environment,
this remains true for domain-scoped tokens but not for project-scoped
tokens. Project-scoped tokens currently only work if the domain_id
query parameter is specified. This has been a source of pain to many
users, and is unnecessary. Just as the desired domain is assumed to be
that to which the token is scoped when the token is domain-scoped,
keystone can assume the desired domain is that of the project's domain
when the token is project-scoped.

Change-Id: I1d06935c06661109a523c5b4547ff01f23235a89
Closes-Bug: 1479578
This commit is contained in:
Matthew Edmonds 2016-02-18 17:02:09 -05:00 committed by Steve Martinelli
parent c0dbace500
commit c73a81e61d
2 changed files with 25 additions and 11 deletions

View File

@ -728,6 +728,8 @@ class V3Controller(wsgi.Application):
if token_ref.domain_scoped:
return token_ref.domain_id
elif token_ref.project_scoped:
return token_ref.project_domain_id
else:
LOG.warning(
_LW('No domain information specified as part of list request'))

View File

@ -236,26 +236,42 @@ class IdentityTestCase(test_v3.RestfulTestCase):
self.config_fixture.config(group='identity',
domain_specific_drivers_enabled=True)
# Create a user with a role on the domain so we can get a
# domain scoped token
# Create a new domain with a new project and user
domain = unit.new_domain_ref()
self.resource_api.create_domain(domain['id'], domain)
project = unit.new_project_ref(domain_id=domain['id'])
self.resource_api.create_project(project['id'], project)
user = unit.create_user(self.identity_api, domain_id=domain['id'])
# Create both project and domain role grants for the user so we
# can get both project and domain scoped tokens
self.assignment_api.create_grant(
role_id=self.role_id, user_id=user['id'],
domain_id=domain['id'])
self.assignment_api.create_grant(
role_id=self.role_id, user_id=user['id'],
project_id=project['id'])
ref = unit.new_user_ref(domain_id=domain['id'])
ref_nd = ref.copy()
ref_nd.pop('domain_id')
auth = self.build_authentication_request(
dom_auth = self.build_authentication_request(
user_id=user['id'],
password=user['password'],
domain_id=domain['id'])
project_auth = self.build_authentication_request(
user_id=user['id'],
password=user['password'],
project_id=project['id'])
# First try using a domain scoped token
resource_url = '/users'
r = self.get(resource_url, auth=auth)
r = self.get(resource_url, auth=dom_auth)
self.assertValidUserListResponse(r, ref=user,
resource_url=resource_url)
# Now try using a project scoped token
resource_url = '/users'
r = self.get(resource_url, auth=project_auth)
self.assertValidUserListResponse(r, ref=user,
resource_url=resource_url)
@ -266,10 +282,6 @@ class IdentityTestCase(test_v3.RestfulTestCase):
self.assertValidUserListResponse(r, ref=user,
resource_url=resource_url)
# Now try the same thing without a domain token or filter,
# which should fail
r = self.get('/users', expected_status=exception.Unauthorized.code)
def test_list_users_no_default_project(self):
"""Call ``GET /users`` making sure no default_project_id."""
user = unit.new_user_ref(self.domain_id)