make sure default_project_id is not domain on user creation and update

Make sure user cannot accidentially set the default_project_id to a domain_id.
Invalid default_project_id is still allowed for backward compatibility.

Change-Id: I7dd33fdc299fa465333ca1d18819ef0537752f16
Closes-Bug: 1582376
This commit is contained in:
Guang Yee 2016-05-17 18:10:59 -07:00 committed by guang-yee
parent 92837a887c
commit 8a7133f950
2 changed files with 45 additions and 0 deletions

View File

@ -828,6 +828,19 @@ class Manager(manager.Manager):
return self._set_domain_id_and_mapping(
ref, domain_id, driver, mapping.EntityType.USER)
def _assert_default_project_id_is_not_domain(self, default_project_id):
if default_project_id:
# make sure project is not a domain
try:
project_ref = self.resource_api.get_project(default_project_id)
if project_ref['is_domain'] is True:
msg = _("User's default project ID cannot be a domain ID.")
raise exception.ValidationError(message=msg)
except exception.ProjectNotFound:
# should be idempotent if project is not found so that it is
# backward compatible
pass
@domains_configured
@exception_translated('user')
def create_user(self, user_ref, initiator=None):
@ -838,6 +851,9 @@ class Manager(manager.Manager):
domain_id = user['domain_id']
self.resource_api.get_domain(domain_id)
self._assert_default_project_id_is_not_domain(
user_ref.get('default_project_id'))
# For creating a user, the domain is in the object itself
domain_id = user_ref['domain_id']
driver = self._select_identity_driver(domain_id)
@ -928,6 +944,9 @@ class Manager(manager.Manager):
# public ID not the local ID
user.pop('id')
self._assert_default_project_id_is_not_domain(
user_ref.get('default_project_id'))
domain_id, driver, entity_id = (
self._get_domain_driver_and_entity_id(user_id))
user = self._clear_domain_id_if_domain_unaware(driver, user)

View File

@ -624,6 +624,32 @@ class IdentityTestCase(test_v3.RestfulTestCase):
self.assertNotIn(new_password, log_fix.output)
def test_setting_default_project_id_to_domain_failed(self):
"""Call ``POST and PATCH /users`` default_project_id=domain_id.
Make sure we validate the default_project_id if it is specified.
It cannot be set to a domain_id, even for a project acting as domain
right now. That's because we haven't sort out the issuing
project-scoped token for project acting as domain bit yet. Once we
got that sorted out, we can relax this constraint.
"""
# creating a new user with default_project_id set to a
# domain_id should result in HTTP 400
ref = unit.new_user_ref(domain_id=self.domain_id,
project_id=self.domain_id)
self.post('/users', body={'user': ref}, token=CONF.admin_token,
expected_status=http_client.BAD_REQUEST)
# updating user's default_project_id to a domain_id should result
# in HTTP 400
user = {'default_project_id': self.domain_id}
self.patch('/users/%(user_id)s' % {
'user_id': self.user['id']},
body={'user': user},
token=CONF.admin_token,
expected_status=http_client.BAD_REQUEST)
class IdentityV3toV2MethodsTestCase(unit.TestCase):
"""Test users V3 to V2 conversion methods."""