"Fossies" - the Fresh Open Source Software Archive

Member "keystone-17.0.0/keystone/tests/unit/test_v3_assignment.py" (13 May 2020, 175764 Bytes) of package /linux/misc/openstack/keystone-17.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_v3_assignment.py": 16.0.1_vs_17.0.0.

    1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
    2 # not use this file except in compliance with the License. You may obtain
    3 # a copy of the License at
    4 #
    5 #      http://www.apache.org/licenses/LICENSE-2.0
    6 #
    7 # Unless required by applicable law or agreed to in writing, software
    8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   10 # License for the specific language governing permissions and limitations
   11 # under the License.
   12 
   13 import datetime
   14 import random
   15 import uuid
   16 
   17 import freezegun
   18 import http.client
   19 from testtools import matchers
   20 
   21 from keystone.common import provider_api
   22 import keystone.conf
   23 from keystone import exception
   24 from keystone.resource.backends import base as resource_base
   25 from keystone.tests import unit
   26 from keystone.tests.unit import test_v3
   27 from keystone.tests.unit import utils as test_utils
   28 
   29 
   30 CONF = keystone.conf.CONF
   31 PROVIDERS = provider_api.ProviderAPIs
   32 
   33 
   34 class SystemRoleAssignmentMixin(object):
   35 
   36     def _create_new_role(self):
   37         """Create a role available for use anywhere and return the ID."""
   38         ref = unit.new_role_ref()
   39         response = self.post('/roles', body={'role': ref})
   40         # We only really need the role ID, so omit the rest of the response and
   41         # return the ID of the role we just created.
   42         return response.json_body['role']['id']
   43 
   44     def _create_group(self):
   45         body = {
   46             'group': {
   47                 'domain_id': self.domain_id,
   48                 'name': uuid.uuid4().hex
   49             }
   50         }
   51         response = self.post('/groups/', body=body)
   52         return response.json_body['group']
   53 
   54     def _create_user(self):
   55         body = {
   56             'user': {
   57                 'domain_id': self.domain_id,
   58                 'name': uuid.uuid4().hex
   59             }
   60         }
   61         response = self.post('/users/', body=body)
   62         return response.json_body['user']
   63 
   64 
   65 class AssignmentTestCase(test_v3.RestfulTestCase,
   66                          test_v3.AssignmentTestMixin,
   67                          SystemRoleAssignmentMixin):
   68     """Test roles and role assignments."""
   69 
   70     def setUp(self):
   71         super(AssignmentTestCase, self).setUp()
   72 
   73         self.group = unit.new_group_ref(domain_id=self.domain_id)
   74         self.group = PROVIDERS.identity_api.create_group(self.group)
   75         self.group_id = self.group['id']
   76 
   77     # Role CRUD tests
   78 
   79     def test_create_role(self):
   80         """Call ``POST /roles``."""
   81         ref = unit.new_role_ref()
   82         r = self.post(
   83             '/roles',
   84             body={'role': ref})
   85         return self.assertValidRoleResponse(r, ref)
   86 
   87     def test_create_role_bad_request(self):
   88         """Call ``POST /roles``."""
   89         self.post('/roles', body={'role': {}},
   90                   expected_status=http.client.BAD_REQUEST)
   91 
   92     def test_list_head_roles(self):
   93         """Call ``GET & HEAD /roles``."""
   94         resource_url = '/roles'
   95         r = self.get(resource_url)
   96         self.assertValidRoleListResponse(r, ref=self.role,
   97                                          resource_url=resource_url)
   98         self.head(resource_url, expected_status=http.client.OK)
   99 
  100     def test_get_head_role(self):
  101         """Call ``GET & HEAD /roles/{role_id}``."""
  102         resource_url = '/roles/%(role_id)s' % {
  103             'role_id': self.role_id}
  104         r = self.get(resource_url)
  105         self.assertValidRoleResponse(r, self.role)
  106         self.head(resource_url, expected_status=http.client.OK)
  107 
  108     def test_update_role(self):
  109         """Call ``PATCH /roles/{role_id}``."""
  110         ref = unit.new_role_ref()
  111         del ref['id']
  112         r = self.patch('/roles/%(role_id)s' % {
  113             'role_id': self.role_id},
  114             body={'role': ref})
  115         self.assertValidRoleResponse(r, ref)
  116 
  117     def test_delete_role(self):
  118         """Call ``DELETE /roles/{role_id}``."""
  119         self.delete('/roles/%(role_id)s' % {
  120             'role_id': self.role_id})
  121 
  122     # Role Grants tests
  123 
  124     def test_crud_user_project_role_grants(self):
  125         role = unit.new_role_ref()
  126         PROVIDERS.role_api.create_role(role['id'], role)
  127 
  128         collection_url = (
  129             '/projects/%(project_id)s/users/%(user_id)s/roles' % {
  130                 'project_id': self.project['id'],
  131                 'user_id': self.user['id']})
  132         member_url = '%(collection_url)s/%(role_id)s' % {
  133             'collection_url': collection_url,
  134             'role_id': role['id']}
  135 
  136         # There is a role assignment for self.user on self.project
  137         r = self.get(collection_url)
  138         self.assertValidRoleListResponse(r, ref=self.role,
  139                                          expected_length=1)
  140 
  141         self.put(member_url)
  142         self.head(member_url)
  143         self.get(member_url, expected_status=http.client.NO_CONTENT)
  144         r = self.get(collection_url)
  145         self.assertValidRoleListResponse(r, ref=role,
  146                                          resource_url=collection_url,
  147                                          expected_length=2)
  148         self.head(collection_url, expected_status=http.client.OK)
  149 
  150         self.delete(member_url)
  151         r = self.get(collection_url)
  152         self.assertValidRoleListResponse(r, ref=self.role, expected_length=1)
  153         self.assertIn(collection_url, r.result['links']['self'])
  154         self.head(collection_url, expected_status=http.client.OK)
  155 
  156     def test_crud_user_project_role_grants_no_user(self):
  157         """Grant role on a project to a user that doesn't exist.
  158 
  159         When grant a role on a project to a user that doesn't exist, the server
  160         returns Not Found for the user.
  161 
  162         """
  163         user_id = uuid.uuid4().hex
  164 
  165         collection_url = (
  166             '/projects/%(project_id)s/users/%(user_id)s/roles' % {
  167                 'project_id': self.project['id'], 'user_id': user_id})
  168         member_url = '%(collection_url)s/%(role_id)s' % {
  169             'collection_url': collection_url,
  170             'role_id': self.role_id}
  171 
  172         self.put(member_url, expected_status=http.client.NOT_FOUND)
  173         self.head(member_url, expected_status=http.client.NOT_FOUND)
  174         self.get(member_url, expected_status=http.client.NOT_FOUND)
  175 
  176     def test_crud_user_domain_role_grants(self):
  177         time = datetime.datetime.utcnow()
  178         with freezegun.freeze_time(time) as frozen_datetime:
  179             collection_url = (
  180                 '/domains/%(domain_id)s/users/%(user_id)s/roles' % {
  181                     'domain_id': self.domain_id,
  182                     'user_id': self.user['id']})
  183             member_url = '%(collection_url)s/%(role_id)s' % {
  184                 'collection_url': collection_url,
  185                 'role_id': self.role_id}
  186 
  187             self.put(member_url)
  188             self.head(member_url)
  189             self.get(member_url, expected_status=http.client.NO_CONTENT)
  190             r = self.get(collection_url)
  191             self.assertValidRoleListResponse(r, ref=self.role,
  192                                              resource_url=collection_url)
  193             self.head(collection_url, expected_status=http.client.OK)
  194 
  195             self.delete(member_url)
  196             # NOTE(lbragstad): Make sure we wait a second before we ask for the
  197             # roles. This ensures the token we use isn't considered revoked
  198             # because it was issued within the same second as a revocation
  199             # event.
  200             frozen_datetime.tick(delta=datetime.timedelta(seconds=1))
  201             r = self.get(collection_url)
  202             self.assertValidRoleListResponse(r, expected_length=0,
  203                                              resource_url=collection_url)
  204             self.head(collection_url, expected_status=http.client.OK)
  205 
  206     def test_crud_user_domain_role_grants_no_user(self):
  207         """Grant role on a domain to a user that doesn't exist.
  208 
  209         When grant a role on a domain to a user that doesn't exist, the server
  210         returns 404 Not Found for the user.
  211 
  212         """
  213         user_id = uuid.uuid4().hex
  214 
  215         collection_url = (
  216             '/domains/%(domain_id)s/users/%(user_id)s/roles' % {
  217                 'domain_id': self.domain_id, 'user_id': user_id})
  218         member_url = '%(collection_url)s/%(role_id)s' % {
  219             'collection_url': collection_url,
  220             'role_id': self.role_id}
  221 
  222         self.put(member_url, expected_status=http.client.NOT_FOUND)
  223         self.head(member_url, expected_status=http.client.NOT_FOUND)
  224         self.get(member_url, expected_status=http.client.NOT_FOUND)
  225 
  226     def test_crud_group_project_role_grants(self):
  227         time = datetime.datetime.utcnow()
  228         with freezegun.freeze_time(time) as frozen_datetime:
  229             collection_url = (
  230                 '/projects/%(project_id)s/groups/%(group_id)s/roles' % {
  231                     'project_id': self.project_id,
  232                     'group_id': self.group_id})
  233             member_url = '%(collection_url)s/%(role_id)s' % {
  234                 'collection_url': collection_url,
  235                 'role_id': self.role_id}
  236 
  237             self.put(member_url)
  238             self.head(member_url)
  239             self.get(member_url, expected_status=http.client.NO_CONTENT)
  240             r = self.get(collection_url)
  241             self.assertValidRoleListResponse(r, ref=self.role,
  242                                              resource_url=collection_url)
  243             self.head(collection_url, expected_status=http.client.OK)
  244 
  245             self.delete(member_url)
  246             # NOTE(lbragstad): Make sure we wait a second before we ask for the
  247             # roles. This ensures the token we use isn't considered revoked
  248             # because it was issued within the same second as a revocation
  249             # event.
  250             frozen_datetime.tick(delta=datetime.timedelta(seconds=1))
  251             r = self.get(collection_url)
  252             self.assertValidRoleListResponse(r, expected_length=0,
  253                                              resource_url=collection_url)
  254             self.head(collection_url, expected_status=http.client.OK)
  255 
  256     def test_crud_group_project_role_grants_no_group(self):
  257         """Grant role on a project to a group that doesn't exist.
  258 
  259         When grant a role on a project to a group that doesn't exist, the
  260         server returns 404 Not Found for the group.
  261 
  262         """
  263         group_id = uuid.uuid4().hex
  264 
  265         collection_url = (
  266             '/projects/%(project_id)s/groups/%(group_id)s/roles' % {
  267                 'project_id': self.project_id,
  268                 'group_id': group_id})
  269         member_url = '%(collection_url)s/%(role_id)s' % {
  270             'collection_url': collection_url,
  271             'role_id': self.role_id}
  272 
  273         self.put(member_url, expected_status=http.client.NOT_FOUND)
  274         self.head(member_url, expected_status=http.client.NOT_FOUND)
  275         self.get(member_url, expected_status=http.client.NOT_FOUND)
  276 
  277     def test_crud_group_domain_role_grants(self):
  278         time = datetime.datetime.utcnow()
  279         with freezegun.freeze_time(time) as frozen_datetime:
  280             collection_url = (
  281                 '/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
  282                     'domain_id': self.domain_id,
  283                     'group_id': self.group_id})
  284             member_url = '%(collection_url)s/%(role_id)s' % {
  285                 'collection_url': collection_url,
  286                 'role_id': self.role_id}
  287 
  288             self.put(member_url)
  289             self.head(member_url)
  290             self.get(member_url, expected_status=http.client.NO_CONTENT)
  291             r = self.get(collection_url)
  292             self.assertValidRoleListResponse(r, ref=self.role,
  293                                              resource_url=collection_url)
  294             self.head(collection_url, expected_status=http.client.OK)
  295 
  296             self.delete(member_url)
  297             # NOTE(lbragstad): Make sure we wait a second before we ask for the
  298             # roles. This ensures the token we use isn't considered revoked
  299             # because it was issued within the same second as a revocation
  300             # event.
  301             frozen_datetime.tick(delta=datetime.timedelta(seconds=1))
  302             r = self.get(collection_url)
  303             self.assertValidRoleListResponse(r, expected_length=0,
  304                                              resource_url=collection_url)
  305             self.head(collection_url, expected_status=http.client.OK)
  306 
  307     def test_crud_group_domain_role_grants_no_group(self):
  308         """Grant role on a domain to a group that doesn't exist.
  309 
  310         When grant a role on a domain to a group that doesn't exist, the server
  311         returns 404 Not Found for the group.
  312 
  313         """
  314         group_id = uuid.uuid4().hex
  315 
  316         collection_url = (
  317             '/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
  318                 'domain_id': self.domain_id,
  319                 'group_id': group_id})
  320         member_url = '%(collection_url)s/%(role_id)s' % {
  321             'collection_url': collection_url,
  322             'role_id': self.role_id}
  323 
  324         self.put(member_url, expected_status=http.client.NOT_FOUND)
  325         self.head(member_url, expected_status=http.client.NOT_FOUND)
  326         self.get(member_url, expected_status=http.client.NOT_FOUND)
  327 
  328     def _create_new_user_and_assign_role_on_project(self):
  329         """Create a new user and assign user a role on a project."""
  330         # Create a new user
  331         new_user = unit.new_user_ref(domain_id=self.domain_id)
  332         user_ref = PROVIDERS.identity_api.create_user(new_user)
  333         # Assign the user a role on the project
  334         collection_url = (
  335             '/projects/%(project_id)s/users/%(user_id)s/roles' % {
  336                 'project_id': self.project_id,
  337                 'user_id': user_ref['id']})
  338         member_url = ('%(collection_url)s/%(role_id)s' % {
  339             'collection_url': collection_url,
  340             'role_id': self.role_id})
  341         self.put(member_url)
  342         # Check the user has the role assigned
  343         self.head(member_url)
  344         self.get(member_url, expected_status=http.client.NO_CONTENT)
  345         return member_url, user_ref
  346 
  347     def test_delete_user_before_removing_role_assignment_succeeds(self):
  348         """Call ``DELETE`` on the user before the role assignment."""
  349         member_url, user = self._create_new_user_and_assign_role_on_project()
  350         # Delete the user from identity backend
  351         PROVIDERS.identity_api.driver.delete_user(user['id'])
  352         # Clean up the role assignment
  353         self.delete(member_url)
  354         # Make sure the role is gone
  355         self.head(member_url, expected_status=http.client.NOT_FOUND)
  356 
  357     def test_delete_group_before_removing_role_assignment_succeeds(self):
  358         # Disable the cache so that we perform a fresh check of the identity
  359         # backend when attempting to remove the role assignment.
  360         self.config_fixture.config(group='cache', enabled=False)
  361 
  362         # Create a new group
  363         group = unit.new_group_ref(domain_id=self.domain_id)
  364         group_ref = PROVIDERS.identity_api.create_group(group)
  365 
  366         # Assign the user a role on the project
  367         collection_url = (
  368             '/projects/%(project_id)s/groups/%(group_id)s/roles' % {
  369                 'project_id': self.project_id,
  370                 'group_id': group_ref['id']})
  371         member_url = ('%(collection_url)s/%(role_id)s' % {
  372             'collection_url': collection_url,
  373             'role_id': self.role_id})
  374         self.put(member_url)
  375 
  376         # Check the user has the role assigned
  377         self.head(member_url)
  378         self.get(member_url, expected_status=http.client.NO_CONTENT)
  379 
  380         # Simulate removing the group via LDAP by directly removing it from the
  381         # identity backend.
  382         PROVIDERS.identity_api.driver.delete_group(group_ref['id'])
  383 
  384         # Ensure we can clean up the role assignment even though the group
  385         # doesn't exist
  386         self.delete(member_url)
  387 
  388     def test_delete_user_before_removing_system_assignments_succeeds(self):
  389         system_role = self._create_new_role()
  390         user = self._create_user()
  391         path = (
  392             '/system/users/%(user_id)s/roles/%(role_id)s' %
  393             {'user_id': user['id'], 'role_id': system_role}
  394         )
  395         self.put(path)
  396 
  397         response = self.get('/role_assignments')
  398         number_of_assignments = len(response.json_body['role_assignments'])
  399 
  400         path = '/users/%(user_id)s' % {'user_id': user['id']}
  401         self.delete(path)
  402 
  403         # The user with the system role assignment is a new user and only has
  404         # one role on the system. We should expect one less role assignment in
  405         # the list.
  406         response = self.get('/role_assignments')
  407         self.assertValidRoleAssignmentListResponse(
  408             response, expected_length=number_of_assignments - 1
  409         )
  410 
  411     def test_delete_user_and_check_role_assignment_fails(self):
  412         """Call ``DELETE`` on the user and check the role assignment."""
  413         member_url, user = self._create_new_user_and_assign_role_on_project()
  414         # Delete the user from identity backend
  415         PROVIDERS.identity_api.delete_user(user['id'])
  416         # We should get a 404 Not Found when looking for the user in the
  417         # identity backend because we're not performing a delete operation on
  418         # the role.
  419         self.head(member_url, expected_status=http.client.NOT_FOUND)
  420 
  421     def test_token_revoked_once_group_role_grant_revoked(self):
  422         """Test token invalid when direct & indirect role on user is revoked.
  423 
  424         When a role granted to a group is revoked for a given scope,
  425         and user direct role is revoked, then tokens created
  426         by user will be invalid.
  427 
  428         """
  429         time = datetime.datetime.utcnow()
  430         with freezegun.freeze_time(time) as frozen_datetime:
  431             # creates grant from group on project.
  432             PROVIDERS.assignment_api.create_grant(
  433                 role_id=self.role['id'], project_id=self.project['id'],
  434                 group_id=self.group['id']
  435             )
  436 
  437             # adds user to the group.
  438             PROVIDERS.identity_api.add_user_to_group(
  439                 user_id=self.user['id'], group_id=self.group['id']
  440             )
  441 
  442             # creates a token for the user
  443             auth_body = self.build_authentication_request(
  444                 user_id=self.user['id'],
  445                 password=self.user['password'],
  446                 project_id=self.project['id'])
  447             token_resp = self.post('/auth/tokens', body=auth_body)
  448             token = token_resp.headers.get('x-subject-token')
  449 
  450             # validates the returned token; it should be valid.
  451             self.head('/auth/tokens',
  452                       headers={'x-subject-token': token},
  453                       expected_status=http.client.OK)
  454 
  455             frozen_datetime.tick(delta=datetime.timedelta(seconds=1))
  456             # revokes the grant from group on project.
  457             PROVIDERS.assignment_api.delete_grant(
  458                 role_id=self.role['id'], project_id=self.project['id'],
  459                 group_id=self.group['id'])
  460             # revokes the direct role form user on project
  461             PROVIDERS.assignment_api.delete_grant(
  462                 role_id=self.role['id'], project_id=self.project['id'],
  463                 user_id=self.user['id']
  464             )
  465 
  466             frozen_datetime.tick(delta=datetime.timedelta(seconds=1))
  467             # validates the same token again; it should not longer be valid.
  468             self.head('/auth/tokens', token=token,
  469                       expected_status=http.client.UNAUTHORIZED)
  470 
  471     def test_delete_group_before_removing_system_assignments_succeeds(self):
  472         system_role = self._create_new_role()
  473         group = self._create_group()
  474         path = (
  475             '/system/groups/%(group_id)s/roles/%(role_id)s' %
  476             {'group_id': group['id'], 'role_id': system_role}
  477         )
  478         self.put(path)
  479 
  480         response = self.get('/role_assignments')
  481         number_of_assignments = len(response.json_body['role_assignments'])
  482 
  483         path = '/groups/%(group_id)s' % {'group_id': group['id']}
  484         self.delete(path)
  485 
  486         # The group with the system role assignment is a new group and only has
  487         # one role on the system. We should expect one less role assignment in
  488         # the list.
  489         response = self.get('/role_assignments')
  490         self.assertValidRoleAssignmentListResponse(
  491             response, expected_length=number_of_assignments - 1
  492         )
  493 
  494     @unit.skip_if_cache_disabled('assignment')
  495     def test_delete_grant_from_user_and_project_invalidate_cache(self):
  496         # create a new project
  497         new_project = unit.new_project_ref(domain_id=self.domain_id)
  498         PROVIDERS.resource_api.create_project(new_project['id'], new_project)
  499 
  500         collection_url = (
  501             '/projects/%(project_id)s/users/%(user_id)s/roles' % {
  502                 'project_id': new_project['id'],
  503                 'user_id': self.user['id']})
  504         member_url = '%(collection_url)s/%(role_id)s' % {
  505             'collection_url': collection_url,
  506             'role_id': self.role_id}
  507 
  508         # create the user a grant on the new project
  509         self.put(member_url)
  510 
  511         # check the grant that was just created
  512         self.head(member_url)
  513         self.get(member_url, expected_status=http.client.NO_CONTENT)
  514         resp = self.get(collection_url)
  515         self.assertValidRoleListResponse(resp, ref=self.role,
  516                                          resource_url=collection_url)
  517 
  518         # delete the grant
  519         self.delete(member_url)
  520 
  521         # get the collection and ensure there are no roles on the project
  522         resp = self.get(collection_url)
  523         self.assertListEqual(resp.json_body['roles'], [])
  524 
  525     @unit.skip_if_cache_disabled('assignment')
  526     def test_delete_grant_from_user_and_domain_invalidates_cache(self):
  527         # create a new domain
  528         new_domain = unit.new_domain_ref()
  529         PROVIDERS.resource_api.create_domain(new_domain['id'], new_domain)
  530 
  531         collection_url = (
  532             '/domains/%(domain_id)s/users/%(user_id)s/roles' % {
  533                 'domain_id': new_domain['id'],
  534                 'user_id': self.user['id']})
  535         member_url = '%(collection_url)s/%(role_id)s' % {
  536             'collection_url': collection_url,
  537             'role_id': self.role_id}
  538 
  539         # create the user a grant on the new domain
  540         self.put(member_url)
  541 
  542         # check the grant that was just created
  543         self.head(member_url)
  544         self.get(member_url, expected_status=http.client.NO_CONTENT)
  545         resp = self.get(collection_url)
  546         self.assertValidRoleListResponse(resp, ref=self.role,
  547                                          resource_url=collection_url)
  548 
  549         # delete the grant
  550         self.delete(member_url)
  551 
  552         # get the collection and ensure there are no roles on the domain
  553         resp = self.get(collection_url)
  554         self.assertListEqual(resp.json_body['roles'], [])
  555 
  556     @unit.skip_if_cache_disabled('assignment')
  557     def test_delete_grant_from_group_and_project_invalidates_cache(self):
  558         # create a new project
  559         new_project = unit.new_project_ref(domain_id=self.domain_id)
  560         PROVIDERS.resource_api.create_project(new_project['id'], new_project)
  561 
  562         collection_url = (
  563             '/projects/%(project_id)s/groups/%(group_id)s/roles' % {
  564                 'project_id': new_project['id'],
  565                 'group_id': self.group['id']})
  566         member_url = '%(collection_url)s/%(role_id)s' % {
  567             'collection_url': collection_url,
  568             'role_id': self.role_id}
  569 
  570         # create the group a grant on the new project
  571         self.put(member_url)
  572 
  573         # check the grant that was just created
  574         self.head(member_url)
  575         self.get(member_url, expected_status=http.client.NO_CONTENT)
  576         resp = self.get(collection_url)
  577         self.assertValidRoleListResponse(resp, ref=self.role,
  578                                          resource_url=collection_url)
  579 
  580         # delete the grant
  581         self.delete(member_url)
  582 
  583         # get the collection and ensure there are no roles on the project
  584         resp = self.get(collection_url)
  585         self.assertListEqual(resp.json_body['roles'], [])
  586 
  587     @unit.skip_if_cache_disabled('assignment')
  588     def test_delete_grant_from_group_and_domain_invalidates_cache(self):
  589         # create a new domain
  590         new_domain = unit.new_domain_ref()
  591         PROVIDERS.resource_api.create_domain(new_domain['id'], new_domain)
  592 
  593         collection_url = (
  594             '/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
  595                 'domain_id': new_domain['id'],
  596                 'group_id': self.group['id']})
  597         member_url = '%(collection_url)s/%(role_id)s' % {
  598             'collection_url': collection_url,
  599             'role_id': self.role_id}
  600 
  601         # create the group a grant on the new domain
  602         self.put(member_url)
  603 
  604         # check the grant that was just created
  605         self.head(member_url)
  606         self.get(member_url, expected_status=http.client.NO_CONTENT)
  607         resp = self.get(collection_url)
  608         self.assertValidRoleListResponse(resp, ref=self.role,
  609                                          resource_url=collection_url)
  610 
  611         # delete the grant
  612         self.delete(member_url)
  613 
  614         # get the collection and ensure there are no roles on the domain
  615         resp = self.get(collection_url)
  616         self.assertListEqual(resp.json_body['roles'], [])
  617 
  618     # Role Assignments tests
  619 
  620     def test_get_head_role_assignments(self):
  621         """Call ``GET & HEAD /role_assignments``.
  622 
  623         The sample data set up already has a user, group and project
  624         that is part of self.domain. We use these plus a new user
  625         we create as our data set, making sure we ignore any
  626         role assignments that are already in existence.
  627 
  628         Since we don't yet support a first class entity for role
  629         assignments, we are only testing the LIST API.  To create
  630         and delete the role assignments we use the old grant APIs.
  631 
  632         Test Plan:
  633 
  634         - Create extra user for tests
  635         - Get a list of all existing role assignments
  636         - Add a new assignment for each of the four combinations, i.e.
  637           group+domain, user+domain, group+project, user+project, using
  638           the same role each time
  639         - Get a new list of all role assignments, checking these four new
  640           ones have been added
  641         - Then delete the four we added
  642         - Get a new list of all role assignments, checking the four have
  643           been removed
  644 
  645         """
  646         time = datetime.datetime.utcnow()
  647         with freezegun.freeze_time(time) as frozen_datetime:
  648             # Since the default fixtures already assign some roles to the
  649             # user it creates, we also need a new user that will not have any
  650             # existing assignments
  651             user1 = unit.new_user_ref(domain_id=self.domain['id'])
  652             user1 = PROVIDERS.identity_api.create_user(user1)
  653 
  654             role = unit.new_role_ref()
  655             PROVIDERS.role_api.create_role(role['id'], role)
  656 
  657             collection_url = '/role_assignments'
  658             r = self.get(collection_url)
  659             self.assertValidRoleAssignmentListResponse(
  660                 r, resource_url=collection_url)
  661             self.head(collection_url, expected_status=http.client.OK)
  662             existing_assignments = len(r.result.get('role_assignments'))
  663 
  664             # Now add one of each of the four types of assignment, making sure
  665             # that we get them all back.
  666             gd_entity = self.build_role_assignment_entity(
  667                 domain_id=self.domain_id,
  668                 group_id=self.group_id,
  669                 role_id=role['id'])
  670             self.put(gd_entity['links']['assignment'])
  671             r = self.get(collection_url)
  672             self.assertValidRoleAssignmentListResponse(
  673                 r,
  674                 expected_length=existing_assignments + 1,
  675                 resource_url=collection_url)
  676             self.assertRoleAssignmentInListResponse(r, gd_entity)
  677             self.head(collection_url, expected_status=http.client.OK)
  678 
  679             ud_entity = self.build_role_assignment_entity(
  680                 domain_id=self.domain_id,
  681                 user_id=user1['id'],
  682                 role_id=role['id'])
  683             self.put(ud_entity['links']['assignment'])
  684             r = self.get(collection_url)
  685             self.assertValidRoleAssignmentListResponse(
  686                 r,
  687                 expected_length=existing_assignments + 2,
  688                 resource_url=collection_url)
  689             self.assertRoleAssignmentInListResponse(r, ud_entity)
  690             self.head(collection_url, expected_status=http.client.OK)
  691 
  692             gp_entity = self.build_role_assignment_entity(
  693                 project_id=self.project_id, group_id=self.group_id,
  694                 role_id=role['id'])
  695             self.put(gp_entity['links']['assignment'])
  696             r = self.get(collection_url)
  697             self.assertValidRoleAssignmentListResponse(
  698                 r,
  699                 expected_length=existing_assignments + 3,
  700                 resource_url=collection_url)
  701             self.assertRoleAssignmentInListResponse(r, gp_entity)
  702             self.head(collection_url, expected_status=http.client.OK)
  703 
  704             up_entity = self.build_role_assignment_entity(
  705                 project_id=self.project_id, user_id=user1['id'],
  706                 role_id=role['id'])
  707             self.put(up_entity['links']['assignment'])
  708             r = self.get(collection_url)
  709             self.assertValidRoleAssignmentListResponse(
  710                 r,
  711                 expected_length=existing_assignments + 4,
  712                 resource_url=collection_url)
  713             self.assertRoleAssignmentInListResponse(r, up_entity)
  714             self.head(collection_url, expected_status=http.client.OK)
  715 
  716             # Now delete the four we added and make sure they are removed
  717             # from the collection.
  718 
  719             self.delete(gd_entity['links']['assignment'])
  720             self.delete(ud_entity['links']['assignment'])
  721             self.delete(gp_entity['links']['assignment'])
  722             self.delete(up_entity['links']['assignment'])
  723             frozen_datetime.tick(delta=datetime.timedelta(seconds=1))
  724             r = self.get(collection_url)
  725             self.assertValidRoleAssignmentListResponse(
  726                 r,
  727                 expected_length=existing_assignments,
  728                 resource_url=collection_url)
  729             self.assertRoleAssignmentNotInListResponse(r, gd_entity)
  730             self.assertRoleAssignmentNotInListResponse(r, ud_entity)
  731             self.assertRoleAssignmentNotInListResponse(r, gp_entity)
  732             self.assertRoleAssignmentNotInListResponse(r, up_entity)
  733             self.head(collection_url, expected_status=http.client.OK)
  734 
  735     def test_get_effective_role_assignments(self):
  736         """Call ``GET /role_assignments?effective``.
  737 
  738         Test Plan:
  739 
  740         - Create two extra user for tests
  741         - Add these users to a group
  742         - Add a role assignment for the group on a domain
  743         - Get a list of all role assignments, checking one has been added
  744         - Then get a list of all effective role assignments - the group
  745           assignment should have turned into assignments on the domain
  746           for each of the group members.
  747 
  748         """
  749         user1 = unit.create_user(PROVIDERS.identity_api,
  750                                  domain_id=self.domain['id'])
  751         user2 = unit.create_user(PROVIDERS.identity_api,
  752                                  domain_id=self.domain['id'])
  753 
  754         PROVIDERS.identity_api.add_user_to_group(user1['id'], self.group['id'])
  755         PROVIDERS.identity_api.add_user_to_group(user2['id'], self.group['id'])
  756 
  757         collection_url = '/role_assignments'
  758         r = self.get(collection_url)
  759         self.assertValidRoleAssignmentListResponse(r,
  760                                                    resource_url=collection_url)
  761         existing_assignments = len(r.result.get('role_assignments'))
  762 
  763         gd_entity = self.build_role_assignment_entity(domain_id=self.domain_id,
  764                                                       group_id=self.group_id,
  765                                                       role_id=self.role_id)
  766         self.put(gd_entity['links']['assignment'])
  767         r = self.get(collection_url)
  768         self.assertValidRoleAssignmentListResponse(
  769             r,
  770             expected_length=existing_assignments + 1,
  771             resource_url=collection_url)
  772         self.assertRoleAssignmentInListResponse(r, gd_entity)
  773 
  774         # Now re-read the collection asking for effective roles - this
  775         # should mean the group assignment is translated into the two
  776         # member user assignments
  777         collection_url = '/role_assignments?effective'
  778         r = self.get(collection_url)
  779         self.assertValidRoleAssignmentListResponse(
  780             r,
  781             expected_length=existing_assignments + 2,
  782             resource_url=collection_url)
  783         ud_entity = self.build_role_assignment_entity(
  784             link=gd_entity['links']['assignment'], domain_id=self.domain_id,
  785             user_id=user1['id'], role_id=self.role_id)
  786         self.assertRoleAssignmentInListResponse(r, ud_entity)
  787         ud_entity = self.build_role_assignment_entity(
  788             link=gd_entity['links']['assignment'], domain_id=self.domain_id,
  789             user_id=user2['id'], role_id=self.role_id)
  790         self.assertRoleAssignmentInListResponse(r, ud_entity)
  791 
  792     def test_check_effective_values_for_role_assignments(self):
  793         """Call ``GET & HEAD /role_assignments?effective=value``.
  794 
  795         Check the various ways of specifying the 'effective'
  796         query parameter.  If the 'effective' query parameter
  797         is included then this should always be treated as meaning 'True'
  798         unless it is specified as:
  799 
  800         {url}?effective=0
  801 
  802         This is by design to match the agreed way of handling
  803         policy checking on query/filter parameters.
  804 
  805         Test Plan:
  806 
  807         - Create two extra user for tests
  808         - Add these users to a group
  809         - Add a role assignment for the group on a domain
  810         - Get a list of all role assignments, checking one has been added
  811         - Then issue various request with different ways of defining
  812           the 'effective' query parameter. As we have tested the
  813           correctness of the data coming back when we get effective roles
  814           in other tests, here we just use the count of entities to
  815           know if we are getting effective roles or not
  816 
  817         """
  818         user1 = unit.create_user(PROVIDERS.identity_api,
  819                                  domain_id=self.domain['id'])
  820         user2 = unit.create_user(PROVIDERS.identity_api,
  821                                  domain_id=self.domain['id'])
  822 
  823         PROVIDERS.identity_api.add_user_to_group(user1['id'], self.group['id'])
  824         PROVIDERS.identity_api.add_user_to_group(user2['id'], self.group['id'])
  825 
  826         collection_url = '/role_assignments'
  827         r = self.get(collection_url, expected_status=http.client.OK)
  828         self.head(collection_url, expected_status=http.client.OK)
  829         self.assertValidRoleAssignmentListResponse(r,
  830                                                    resource_url=collection_url)
  831         existing_assignments = len(r.result.get('role_assignments'))
  832 
  833         gd_entity = self.build_role_assignment_entity(domain_id=self.domain_id,
  834                                                       group_id=self.group_id,
  835                                                       role_id=self.role_id)
  836         self.put(gd_entity['links']['assignment'])
  837         r = self.get(collection_url, expected_status=http.client.OK)
  838         self.head(collection_url, expected_status=http.client.OK)
  839         self.assertValidRoleAssignmentListResponse(
  840             r,
  841             expected_length=existing_assignments + 1,
  842             resource_url=collection_url)
  843         self.assertRoleAssignmentInListResponse(r, gd_entity)
  844 
  845         # Now re-read the collection asking for effective roles,
  846         # using the most common way of defining "effective'. This
  847         # should mean the group assignment is translated into the two
  848         # member user assignments
  849         collection_url = '/role_assignments?effective'
  850         r = self.get(collection_url, expected_status=http.client.OK)
  851         self.head(collection_url, expected_status=http.client.OK)
  852         self.assertValidRoleAssignmentListResponse(
  853             r,
  854             expected_length=existing_assignments + 2,
  855             resource_url=collection_url)
  856         # Now set 'effective' to false explicitly - should get
  857         # back the regular roles
  858         collection_url = '/role_assignments?effective=0'
  859         r = self.get(collection_url, expected_status=http.client.OK)
  860         self.head(collection_url, expected_status=http.client.OK)
  861         self.assertValidRoleAssignmentListResponse(
  862             r,
  863             expected_length=existing_assignments + 1,
  864             resource_url=collection_url)
  865         # Now try setting  'effective' to 'False' explicitly- this is
  866         # NOT supported as a way of setting a query or filter
  867         # parameter to false by design. Hence we should get back
  868         # effective roles.
  869         collection_url = '/role_assignments?effective=False'
  870         r = self.get(collection_url, expected_status=http.client.OK)
  871         self.head(collection_url, expected_status=http.client.OK)
  872         self.assertValidRoleAssignmentListResponse(
  873             r,
  874             expected_length=existing_assignments + 2,
  875             resource_url=collection_url)
  876         # Now set 'effective' to True explicitly
  877         collection_url = '/role_assignments?effective=True'
  878         r = self.get(collection_url, expected_status=http.client.OK)
  879         self.head(collection_url, expected_status=http.client.OK)
  880         self.assertValidRoleAssignmentListResponse(
  881             r,
  882             expected_length=existing_assignments + 2,
  883             resource_url=collection_url)
  884 
  885     def test_filtered_role_assignments(self):
  886         """Call ``GET /role_assignments?filters``.
  887 
  888         Test Plan:
  889 
  890         - Create extra users, group, role and project for tests
  891         - Make the following assignments:
  892           Give group1, role1 on project1 and domain
  893           Give user1, role2 on project1 and domain
  894           Make User1 a member of Group1
  895         - Test a series of single filter list calls, checking that
  896           the correct results are obtained
  897         - Test a multi-filtered list call
  898         - Test listing all effective roles for a given user
  899         - Test the equivalent of the list of roles in a project scoped
  900           token (all effective roles for a user on a project)
  901 
  902         """
  903         # Since the default fixtures already assign some roles to the
  904         # user it creates, we also need a new user that will not have any
  905         # existing assignments
  906         user1 = unit.create_user(PROVIDERS.identity_api,
  907                                  domain_id=self.domain['id'])
  908         user2 = unit.create_user(PROVIDERS.identity_api,
  909                                  domain_id=self.domain['id'])
  910 
  911         group1 = unit.new_group_ref(domain_id=self.domain['id'])
  912         group1 = PROVIDERS.identity_api.create_group(group1)
  913         PROVIDERS.identity_api.add_user_to_group(user1['id'], group1['id'])
  914         PROVIDERS.identity_api.add_user_to_group(user2['id'], group1['id'])
  915         project1 = unit.new_project_ref(domain_id=self.domain['id'])
  916         PROVIDERS.resource_api.create_project(project1['id'], project1)
  917         self.role1 = unit.new_role_ref()
  918         PROVIDERS.role_api.create_role(self.role1['id'], self.role1)
  919         self.role2 = unit.new_role_ref()
  920         PROVIDERS.role_api.create_role(self.role2['id'], self.role2)
  921 
  922         # Now add one of each of the six types of assignment
  923 
  924         gd_entity = self.build_role_assignment_entity(
  925             domain_id=self.domain_id, group_id=group1['id'],
  926             role_id=self.role1['id'])
  927         self.put(gd_entity['links']['assignment'])
  928 
  929         ud_entity = self.build_role_assignment_entity(domain_id=self.domain_id,
  930                                                       user_id=user1['id'],
  931                                                       role_id=self.role2['id'])
  932         self.put(ud_entity['links']['assignment'])
  933 
  934         gp_entity = self.build_role_assignment_entity(
  935             project_id=project1['id'],
  936             group_id=group1['id'],
  937             role_id=self.role1['id'])
  938         self.put(gp_entity['links']['assignment'])
  939 
  940         up_entity = self.build_role_assignment_entity(
  941             project_id=project1['id'],
  942             user_id=user1['id'],
  943             role_id=self.role2['id'])
  944         self.put(up_entity['links']['assignment'])
  945 
  946         gs_entity = self.build_role_assignment_entity(
  947             system='all',
  948             group_id=group1['id'],
  949             role_id=self.role1['id'])
  950         self.put(gs_entity['links']['assignment'])
  951         us_entity = self.build_role_assignment_entity(
  952             system='all',
  953             user_id=user1['id'],
  954             role_id=self.role2['id'])
  955         self.put(us_entity['links']['assignment'])
  956         us2_entity = self.build_role_assignment_entity(
  957             system='all',
  958             user_id=user2['id'],
  959             role_id=self.role2['id'])
  960         self.put(us2_entity['links']['assignment'])
  961 
  962         # Now list by various filters to make sure we get back the right ones
  963 
  964         collection_url = ('/role_assignments?scope.project.id=%s' %
  965                           project1['id'])
  966         r = self.get(collection_url, expected_status=http.client.OK)
  967         self.head(collection_url, expected_status=http.client.OK)
  968         self.assertValidRoleAssignmentListResponse(r,
  969                                                    expected_length=2,
  970                                                    resource_url=collection_url)
  971         self.assertRoleAssignmentInListResponse(r, up_entity)
  972         self.assertRoleAssignmentInListResponse(r, gp_entity)
  973 
  974         collection_url = ('/role_assignments?scope.domain.id=%s' %
  975                           self.domain['id'])
  976         r = self.get(collection_url, expected_status=http.client.OK)
  977         self.head(collection_url, expected_status=http.client.OK)
  978         self.assertValidRoleAssignmentListResponse(r,
  979                                                    expected_length=2,
  980                                                    resource_url=collection_url)
  981         self.assertRoleAssignmentInListResponse(r, ud_entity)
  982         self.assertRoleAssignmentInListResponse(r, gd_entity)
  983 
  984         collection_url = '/role_assignments?user.id=%s' % user1['id']
  985         r = self.get(collection_url, expected_status=http.client.OK)
  986         self.head(collection_url, expected_status=http.client.OK)
  987         self.assertValidRoleAssignmentListResponse(r,
  988                                                    expected_length=3,
  989                                                    resource_url=collection_url)
  990         self.assertRoleAssignmentInListResponse(r, up_entity)
  991         self.assertRoleAssignmentInListResponse(r, ud_entity)
  992 
  993         collection_url = '/role_assignments?group.id=%s' % group1['id']
  994         r = self.get(collection_url, expected_status=http.client.OK)
  995         self.head(collection_url, expected_status=http.client.OK)
  996         self.assertValidRoleAssignmentListResponse(r,
  997                                                    expected_length=3,
  998                                                    resource_url=collection_url)
  999         self.assertRoleAssignmentInListResponse(r, gd_entity)
 1000         self.assertRoleAssignmentInListResponse(r, gp_entity)
 1001 
 1002         collection_url = '/role_assignments?role.id=%s' % self.role1['id']
 1003         r = self.get(collection_url, expected_status=http.client.OK)
 1004         self.head(collection_url, expected_status=http.client.OK)
 1005         self.assertValidRoleAssignmentListResponse(r,
 1006                                                    expected_length=3,
 1007                                                    resource_url=collection_url)
 1008         self.assertRoleAssignmentInListResponse(r, gd_entity)
 1009         self.assertRoleAssignmentInListResponse(r, gp_entity)
 1010         self.assertRoleAssignmentInListResponse(r, gs_entity)
 1011 
 1012         collection_url = '/role_assignments?role.id=%s' % self.role2['id']
 1013         r = self.get(collection_url, expected_status=http.client.OK)
 1014         self.head(collection_url, expected_status=http.client.OK)
 1015         self.assertValidRoleAssignmentListResponse(r,
 1016                                                    expected_length=4,
 1017                                                    resource_url=collection_url)
 1018         self.assertRoleAssignmentInListResponse(r, ud_entity)
 1019         self.assertRoleAssignmentInListResponse(r, up_entity)
 1020         self.assertRoleAssignmentInListResponse(r, us_entity)
 1021 
 1022         # Let's try combining two filers together....
 1023 
 1024         collection_url = (
 1025             '/role_assignments?user.id=%(user_id)s'
 1026             '&scope.project.id=%(project_id)s' % {
 1027                 'user_id': user1['id'],
 1028                 'project_id': project1['id']})
 1029         r = self.get(collection_url, expected_status=http.client.OK)
 1030         self.head(collection_url, expected_status=http.client.OK)
 1031         self.assertValidRoleAssignmentListResponse(r,
 1032                                                    expected_length=1,
 1033                                                    resource_url=collection_url)
 1034         self.assertRoleAssignmentInListResponse(r, up_entity)
 1035 
 1036         # Now for a harder one - filter for user with effective
 1037         # roles - this should return role assignment that were directly
 1038         # assigned as well as by virtue of group membership
 1039 
 1040         collection_url = ('/role_assignments?effective&user.id=%s' %
 1041                           user1['id'])
 1042         r = self.get(collection_url, expected_status=http.client.OK)
 1043         self.head(collection_url, expected_status=http.client.OK)
 1044         self.assertValidRoleAssignmentListResponse(r,
 1045                                                    expected_length=4,
 1046                                                    resource_url=collection_url)
 1047         # Should have the two direct roles...
 1048         self.assertRoleAssignmentInListResponse(r, up_entity)
 1049         self.assertRoleAssignmentInListResponse(r, ud_entity)
 1050         # ...and the two via group membership...
 1051         gp1_link = self.build_role_assignment_link(
 1052             project_id=project1['id'],
 1053             group_id=group1['id'],
 1054             role_id=self.role1['id'])
 1055         gd1_link = self.build_role_assignment_link(domain_id=self.domain_id,
 1056                                                    group_id=group1['id'],
 1057                                                    role_id=self.role1['id'])
 1058 
 1059         up1_entity = self.build_role_assignment_entity(
 1060             link=gp1_link, project_id=project1['id'],
 1061             user_id=user1['id'], role_id=self.role1['id'])
 1062         ud1_entity = self.build_role_assignment_entity(
 1063             link=gd1_link, domain_id=self.domain_id, user_id=user1['id'],
 1064             role_id=self.role1['id'])
 1065         self.assertRoleAssignmentInListResponse(r, up1_entity)
 1066         self.assertRoleAssignmentInListResponse(r, ud1_entity)
 1067 
 1068         # ...and for the grand-daddy of them all, simulate the request
 1069         # that would generate the list of effective roles in a project
 1070         # scoped token.
 1071 
 1072         collection_url = (
 1073             '/role_assignments?effective&user.id=%(user_id)s'
 1074             '&scope.project.id=%(project_id)s' % {
 1075                 'user_id': user1['id'],
 1076                 'project_id': project1['id']})
 1077         r = self.get(collection_url, expected_status=http.client.OK)
 1078         self.head(collection_url, expected_status=http.client.OK)
 1079         self.assertValidRoleAssignmentListResponse(r,
 1080                                                    expected_length=2,
 1081                                                    resource_url=collection_url)
 1082         # Should have one direct role and one from group membership...
 1083         self.assertRoleAssignmentInListResponse(r, up_entity)
 1084         self.assertRoleAssignmentInListResponse(r, up1_entity)
 1085 
 1086     def test_list_system_role_assignments(self):
 1087         # create a bunch of roles
 1088         user_system_role_id = self._create_new_role()
 1089         user_domain_role_id = self._create_new_role()
 1090         user_project_role_id = self._create_new_role()
 1091         group_system_role_id = self._create_new_role()
 1092         group_domain_role_id = self._create_new_role()
 1093         group_project_role_id = self._create_new_role()
 1094 
 1095         # create a user and grant the user a role on the system, domain, and
 1096         # project
 1097         user = self._create_user()
 1098         url = '/system/users/%s/roles/%s' % (user['id'], user_system_role_id)
 1099         self.put(url)
 1100         url = '/domains/%s/users/%s/roles/%s' % (
 1101             self.domain_id, user['id'], user_domain_role_id
 1102         )
 1103         self.put(url)
 1104         url = '/projects/%s/users/%s/roles/%s' % (
 1105             self.project_id, user['id'], user_project_role_id
 1106         )
 1107         self.put(url)
 1108 
 1109         # create a group and grant the group a role on the system, domain, and
 1110         # project
 1111         group = self._create_group()
 1112         url = '/system/groups/%s/roles/%s' % (
 1113             group['id'], group_system_role_id
 1114         )
 1115         self.put(url)
 1116         url = '/domains/%s/groups/%s/roles/%s' % (
 1117             self.domain_id, group['id'], group_domain_role_id
 1118         )
 1119         self.put(url)
 1120         url = '/projects/%s/groups/%s/roles/%s' % (
 1121             self.project_id, group['id'], group_project_role_id
 1122         )
 1123         self.put(url)
 1124 
 1125         # /v3/role_assignments?scope.system=all should return two assignments
 1126         response = self.get('/role_assignments?scope.system=all')
 1127         self.assertValidRoleAssignmentListResponse(response, expected_length=2)
 1128         for assignment in response.json_body['role_assignments']:
 1129             self.assertTrue(assignment['scope']['system']['all'])
 1130             if assignment.get('user'):
 1131                 self.assertEqual(user_system_role_id, assignment['role']['id'])
 1132             if assignment.get('group'):
 1133                 self.assertEqual(
 1134                     group_system_role_id,
 1135                     assignment['role']['id']
 1136                 )
 1137 
 1138         # /v3/role_assignments?scope_system=all&user.id=$USER_ID should return
 1139         # one role assignment
 1140         url = '/role_assignments?scope.system=all&user.id=%s' % user['id']
 1141         response = self.get(url)
 1142         self.assertValidRoleAssignmentListResponse(response, expected_length=1)
 1143         self.assertEqual(
 1144             user_system_role_id,
 1145             response.json_body['role_assignments'][0]['role']['id']
 1146         )
 1147 
 1148         # /v3/role_assignments?scope_system=all&group.id=$GROUP_ID should
 1149         # return one role assignment
 1150         url = '/role_assignments?scope.system=all&group.id=%s' % group['id']
 1151         response = self.get(url)
 1152         self.assertValidRoleAssignmentListResponse(response, expected_length=1)
 1153         self.assertEqual(
 1154             group_system_role_id,
 1155             response.json_body['role_assignments'][0]['role']['id']
 1156         )
 1157 
 1158         # /v3/role_assignments?user.id=$USER_ID should return 3 assignments
 1159         # and system should be in that list of assignments
 1160         url = '/role_assignments?user.id=%s' % user['id']
 1161         response = self.get(url)
 1162         self.assertValidRoleAssignmentListResponse(response, expected_length=3)
 1163         for assignment in response.json_body['role_assignments']:
 1164             if 'system' in assignment['scope']:
 1165                 self.assertEqual(
 1166                     user_system_role_id, assignment['role']['id']
 1167                 )
 1168             if 'domain' in assignment['scope']:
 1169                 self.assertEqual(
 1170                     user_domain_role_id, assignment['role']['id']
 1171                 )
 1172             if 'project' in assignment['scope']:
 1173                 self.assertEqual(
 1174                     user_project_role_id, assignment['role']['id']
 1175                 )
 1176 
 1177         # /v3/role_assignments?group.id=$GROUP_ID should return 3 assignments
 1178         # and system should be in that list of assignments
 1179         url = '/role_assignments?group.id=%s' % group['id']
 1180         response = self.get(url)
 1181         self.assertValidRoleAssignmentListResponse(response, expected_length=3)
 1182         for assignment in response.json_body['role_assignments']:
 1183             if 'system' in assignment['scope']:
 1184                 self.assertEqual(
 1185                     group_system_role_id, assignment['role']['id']
 1186                 )
 1187             if 'domain' in assignment['scope']:
 1188                 self.assertEqual(
 1189                     group_domain_role_id, assignment['role']['id']
 1190                 )
 1191             if 'project' in assignment['scope']:
 1192                 self.assertEqual(
 1193                     group_project_role_id, assignment['role']['id']
 1194                 )
 1195 
 1196 
 1197 class RoleAssignmentBaseTestCase(test_v3.RestfulTestCase,
 1198                                  test_v3.AssignmentTestMixin):
 1199     """Base class for testing /v3/role_assignments API behavior."""
 1200 
 1201     MAX_HIERARCHY_BREADTH = 3
 1202     MAX_HIERARCHY_DEPTH = CONF.max_project_tree_depth - 1
 1203 
 1204     def load_sample_data(self):
 1205         """Create sample data to be used on tests.
 1206 
 1207         Created data are i) a role and ii) a domain containing: a project
 1208         hierarchy and 3 users within 3 groups.
 1209 
 1210         """
 1211         def create_project_hierarchy(parent_id, depth):
 1212             """Create a random project hierarchy."""
 1213             if depth == 0:
 1214                 return
 1215 
 1216             breadth = random.randint(1, self.MAX_HIERARCHY_BREADTH)
 1217 
 1218             subprojects = []
 1219             for i in range(breadth):
 1220                 subprojects.append(unit.new_project_ref(
 1221                     domain_id=self.domain_id, parent_id=parent_id))
 1222                 PROVIDERS.resource_api.create_project(
 1223                     subprojects[-1]['id'], subprojects[-1]
 1224                 )
 1225 
 1226             new_parent = subprojects[random.randint(0, breadth - 1)]
 1227             create_project_hierarchy(new_parent['id'], depth - 1)
 1228 
 1229         super(RoleAssignmentBaseTestCase, self).load_sample_data()
 1230 
 1231         # Create a domain
 1232         self.domain = unit.new_domain_ref()
 1233         self.domain_id = self.domain['id']
 1234         PROVIDERS.resource_api.create_domain(self.domain_id, self.domain)
 1235 
 1236         # Create a project hierarchy
 1237         self.project = unit.new_project_ref(domain_id=self.domain_id)
 1238         self.project_id = self.project['id']
 1239         PROVIDERS.resource_api.create_project(self.project_id, self.project)
 1240 
 1241         # Create a random project hierarchy
 1242         create_project_hierarchy(self.project_id,
 1243                                  random.randint(1, self.MAX_HIERARCHY_DEPTH))
 1244 
 1245         # Create 3 users
 1246         self.user_ids = []
 1247         for i in range(3):
 1248             user = unit.new_user_ref(domain_id=self.domain_id)
 1249             user = PROVIDERS.identity_api.create_user(user)
 1250             self.user_ids.append(user['id'])
 1251 
 1252         # Create 3 groups
 1253         self.group_ids = []
 1254         for i in range(3):
 1255             group = unit.new_group_ref(domain_id=self.domain_id)
 1256             group = PROVIDERS.identity_api.create_group(group)
 1257             self.group_ids.append(group['id'])
 1258 
 1259             # Put 2 members on each group
 1260             PROVIDERS.identity_api.add_user_to_group(
 1261                 user_id=self.user_ids[i], group_id=group['id']
 1262             )
 1263             PROVIDERS.identity_api.add_user_to_group(
 1264                 user_id=self.user_ids[i % 2], group_id=group['id']
 1265             )
 1266 
 1267         PROVIDERS.assignment_api.create_grant(
 1268             user_id=self.user_id, project_id=self.project_id,
 1269             role_id=self.role_id
 1270         )
 1271 
 1272         # Create a role
 1273         self.role = unit.new_role_ref()
 1274         self.role_id = self.role['id']
 1275         PROVIDERS.role_api.create_role(self.role_id, self.role)
 1276 
 1277         # Set default user and group to be used on tests
 1278         self.default_user_id = self.user_ids[0]
 1279         self.default_group_id = self.group_ids[0]
 1280 
 1281     def get_role_assignments(self, expected_status=http.client.OK, **filters):
 1282         """Return the result from querying role assignment API + queried URL.
 1283 
 1284         Calls GET /v3/role_assignments?<params> and returns its result, where
 1285         <params> is the HTTP query parameters form of effective option plus
 1286         filters, if provided. Queried URL is returned as well.
 1287 
 1288         :returns: a tuple containing the list role assignments API response and
 1289                   queried URL.
 1290 
 1291         """
 1292         query_url = self._get_role_assignments_query_url(**filters)
 1293         response = self.get(query_url, expected_status=expected_status)
 1294 
 1295         return (response, query_url)
 1296 
 1297     def _get_role_assignments_query_url(self, **filters):
 1298         """Return non-effective role assignments query URL from given filters.
 1299 
 1300         :param filters: query parameters are created with the provided filters
 1301                         on role assignments attributes. Valid filters are:
 1302                         role_id, domain_id, project_id, group_id, user_id and
 1303                         inherited_to_projects.
 1304 
 1305         :returns: role assignments query URL.
 1306 
 1307         """
 1308         return self.build_role_assignment_query_url(**filters)
 1309 
 1310 
 1311 class RoleAssignmentFailureTestCase(RoleAssignmentBaseTestCase):
 1312     """Class for testing invalid query params on /v3/role_assignments API.
 1313 
 1314     Querying domain and project, or user and group results in a HTTP 400 Bad
 1315     Request, since a role assignment must contain only a single pair of (actor,
 1316     target). In addition, since filtering on role assignments applies only to
 1317     the final result, effective mode cannot be combined with i) group or ii)
 1318     domain and inherited, because it would always result in an empty list.
 1319 
 1320     """
 1321 
 1322     def test_get_role_assignments_by_domain_and_project(self):
 1323         self.get_role_assignments(domain_id=self.domain_id,
 1324                                   project_id=self.project_id,
 1325                                   expected_status=http.client.BAD_REQUEST)
 1326 
 1327     def test_get_role_assignments_by_user_and_group(self):
 1328         self.get_role_assignments(user_id=self.default_user_id,
 1329                                   group_id=self.default_group_id,
 1330                                   expected_status=http.client.BAD_REQUEST)
 1331 
 1332     def test_get_role_assignments_by_effective_and_inherited(self):
 1333         self.get_role_assignments(domain_id=self.domain_id, effective=True,
 1334                                   inherited_to_projects=True,
 1335                                   expected_status=http.client.BAD_REQUEST)
 1336 
 1337     def test_get_role_assignments_by_effective_and_group(self):
 1338         self.get_role_assignments(effective=True,
 1339                                   group_id=self.default_group_id,
 1340                                   expected_status=http.client.BAD_REQUEST)
 1341 
 1342 
 1343 class RoleAssignmentDirectTestCase(RoleAssignmentBaseTestCase):
 1344     """Class for testing direct assignments on /v3/role_assignments API.
 1345 
 1346     Direct assignments on a domain or project have effect on them directly,
 1347     instead of on their project hierarchy, i.e they are non-inherited. In
 1348     addition, group direct assignments are not expanded to group's users.
 1349 
 1350     Tests on this class make assertions on the representation and API filtering
 1351     of direct assignments.
 1352 
 1353     """
 1354 
 1355     def _test_get_role_assignments(self, **filters):
 1356         """Generic filtering test method.
 1357 
 1358         According to the provided filters, this method:
 1359         - creates a new role assignment;
 1360         - asserts that list role assignments API reponds correctly;
 1361         - deletes the created role assignment.
 1362 
 1363         :param filters: filters to be considered when listing role assignments.
 1364                         Valid filters are: role_id, domain_id, project_id,
 1365                         group_id, user_id and inherited_to_projects.
 1366 
 1367         """
 1368         # Fills default assignment with provided filters
 1369         test_assignment = self._set_default_assignment_attributes(**filters)
 1370 
 1371         # Create new role assignment for this test
 1372         PROVIDERS.assignment_api.create_grant(**test_assignment)
 1373 
 1374         # Get expected role assignments
 1375         expected_assignments = self._list_expected_role_assignments(
 1376             **test_assignment)
 1377 
 1378         # Get role assignments from API
 1379         response, query_url = self.get_role_assignments(**test_assignment)
 1380         self.assertValidRoleAssignmentListResponse(response,
 1381                                                    resource_url=query_url)
 1382         self.assertEqual(len(expected_assignments),
 1383                          len(response.result.get('role_assignments')))
 1384 
 1385         # Assert that expected role assignments were returned by the API call
 1386         for assignment in expected_assignments:
 1387             self.assertRoleAssignmentInListResponse(response, assignment)
 1388 
 1389         # Delete created role assignment
 1390         PROVIDERS.assignment_api.delete_grant(**test_assignment)
 1391 
 1392     def _set_default_assignment_attributes(self, **attribs):
 1393         """Insert default values for missing attributes of role assignment.
 1394 
 1395         If no actor, target or role are provided, they will default to values
 1396         from sample data.
 1397 
 1398         :param attribs: info from a role assignment entity. Valid attributes
 1399                         are: role_id, domain_id, project_id, group_id, user_id
 1400                         and inherited_to_projects.
 1401 
 1402         """
 1403         if not any(target in attribs
 1404                    for target in ('domain_id', 'projects_id')):
 1405             attribs['project_id'] = self.project_id
 1406 
 1407         if not any(actor in attribs for actor in ('user_id', 'group_id')):
 1408             attribs['user_id'] = self.default_user_id
 1409 
 1410         if 'role_id' not in attribs:
 1411             attribs['role_id'] = self.role_id
 1412 
 1413         return attribs
 1414 
 1415     def _list_expected_role_assignments(self, **filters):
 1416         """Given the filters, it returns expected direct role assignments.
 1417 
 1418         :param filters: filters that will be considered when listing role
 1419                         assignments. Valid filters are: role_id, domain_id,
 1420                         project_id, group_id, user_id and
 1421                         inherited_to_projects.
 1422 
 1423         :returns: the list of the expected role assignments.
 1424 
 1425         """
 1426         return [self.build_role_assignment_entity(**filters)]
 1427 
 1428     # Test cases below call the generic test method, providing different filter
 1429     # combinations. Filters are provided as specified in the method name, after
 1430     # 'by'. For example, test_get_role_assignments_by_project_user_and_role
 1431     # calls the generic test method with project_id, user_id and role_id.
 1432 
 1433     def test_get_role_assignments_by_domain(self, **filters):
 1434         self._test_get_role_assignments(domain_id=self.domain_id, **filters)
 1435 
 1436     def test_get_role_assignments_by_project(self, **filters):
 1437         self._test_get_role_assignments(project_id=self.project_id, **filters)
 1438 
 1439     def test_get_role_assignments_by_user(self, **filters):
 1440         self._test_get_role_assignments(user_id=self.default_user_id,
 1441                                         **filters)
 1442 
 1443     def test_get_role_assignments_by_group(self, **filters):
 1444         self._test_get_role_assignments(group_id=self.default_group_id,
 1445                                         **filters)
 1446 
 1447     def test_get_role_assignments_by_role(self, **filters):
 1448         self._test_get_role_assignments(role_id=self.role_id, **filters)
 1449 
 1450     def test_get_role_assignments_by_domain_and_user(self, **filters):
 1451         self.test_get_role_assignments_by_domain(user_id=self.default_user_id,
 1452                                                  **filters)
 1453 
 1454     def test_get_role_assignments_by_domain_and_group(self, **filters):
 1455         self.test_get_role_assignments_by_domain(
 1456             group_id=self.default_group_id, **filters)
 1457 
 1458     def test_get_role_assignments_by_project_and_user(self, **filters):
 1459         self.test_get_role_assignments_by_project(user_id=self.default_user_id,
 1460                                                   **filters)
 1461 
 1462     def test_get_role_assignments_by_project_and_group(self, **filters):
 1463         self.test_get_role_assignments_by_project(
 1464             group_id=self.default_group_id, **filters)
 1465 
 1466     def test_get_role_assignments_by_domain_user_and_role(self, **filters):
 1467         self.test_get_role_assignments_by_domain_and_user(role_id=self.role_id,
 1468                                                           **filters)
 1469 
 1470     def test_get_role_assignments_by_domain_group_and_role(self, **filters):
 1471         self.test_get_role_assignments_by_domain_and_group(
 1472             role_id=self.role_id, **filters)
 1473 
 1474     def test_get_role_assignments_by_project_user_and_role(self, **filters):
 1475         self.test_get_role_assignments_by_project_and_user(
 1476             role_id=self.role_id, **filters)
 1477 
 1478     def test_get_role_assignments_by_project_group_and_role(self, **filters):
 1479         self.test_get_role_assignments_by_project_and_group(
 1480             role_id=self.role_id, **filters)
 1481 
 1482 
 1483 class RoleAssignmentInheritedTestCase(RoleAssignmentDirectTestCase):
 1484     """Class for testing inherited assignments on /v3/role_assignments API.
 1485 
 1486     Inherited assignments on a domain or project have no effect on them
 1487     directly, but on the projects under them instead.
 1488 
 1489     Tests on this class do not make assertions on the effect of inherited
 1490     assignments, but in their representation and API filtering.
 1491 
 1492     """
 1493 
 1494     def _test_get_role_assignments(self, **filters):
 1495         """Add inherited_to_project filter to expected entity in tests."""
 1496         super(RoleAssignmentInheritedTestCase,
 1497               self)._test_get_role_assignments(inherited_to_projects=True,
 1498                                                **filters)
 1499 
 1500 
 1501 class RoleAssignmentEffectiveTestCase(RoleAssignmentInheritedTestCase):
 1502     """Class for testing inheritance effects on /v3/role_assignments API.
 1503 
 1504     Inherited assignments on a domain or project have no effect on them
 1505     directly, but on the projects under them instead.
 1506 
 1507     Tests on this class make assertions on the effect of inherited assignments
 1508     and API filtering.
 1509 
 1510     """
 1511 
 1512     def _get_role_assignments_query_url(self, **filters):
 1513         """Return effective role assignments query URL from given filters.
 1514 
 1515         For test methods in this class, effetive will always be true. As in
 1516         effective mode, inherited_to_projects, group_id, domain_id and
 1517         project_id will always be desconsidered from provided filters.
 1518 
 1519         :param filters: query parameters are created with the provided filters.
 1520                         Valid filters are: role_id, domain_id, project_id,
 1521                         group_id, user_id and inherited_to_projects.
 1522 
 1523         :returns: role assignments query URL.
 1524 
 1525         """
 1526         query_filters = filters.copy()
 1527         query_filters.pop('inherited_to_projects')
 1528 
 1529         query_filters.pop('group_id', None)
 1530         query_filters.pop('domain_id', None)
 1531         query_filters.pop('project_id', None)
 1532 
 1533         return self.build_role_assignment_query_url(effective=True,
 1534                                                     **query_filters)
 1535 
 1536     def _list_expected_role_assignments(self, **filters):
 1537         """Given the filters, it returns expected direct role assignments.
 1538 
 1539         :param filters: filters that will be considered when listing role
 1540                         assignments. Valid filters are: role_id, domain_id,
 1541                         project_id, group_id, user_id and
 1542                         inherited_to_projects.
 1543 
 1544         :returns: the list of the expected role assignments.
 1545 
 1546         """
 1547         # Get assignment link, to be put on 'links': {'assignment': link}
 1548         assignment_link = self.build_role_assignment_link(**filters)
 1549 
 1550         # Expand group membership
 1551         user_ids = [None]
 1552         if filters.get('group_id'):
 1553             user_ids = [user['id'] for user in
 1554                         PROVIDERS.identity_api.list_users_in_group(
 1555                             filters['group_id'])]
 1556         else:
 1557             user_ids = [self.default_user_id]
 1558 
 1559         # Expand role inheritance
 1560         project_ids = [None]
 1561         if filters.get('domain_id'):
 1562             project_ids = [project['id'] for project in
 1563                            PROVIDERS.resource_api.list_projects_in_domain(
 1564                                filters.pop('domain_id'))]
 1565         else:
 1566             project_ids = [project['id'] for project in
 1567                            PROVIDERS.resource_api.list_projects_in_subtree(
 1568                                self.project_id)]
 1569 
 1570         # Compute expected role assignments
 1571         assignments = []
 1572         for project_id in project_ids:
 1573             filters['project_id'] = project_id
 1574             for user_id in user_ids:
 1575                 filters['user_id'] = user_id
 1576                 assignments.append(self.build_role_assignment_entity(
 1577                     link=assignment_link, **filters))
 1578 
 1579         return assignments
 1580 
 1581 
 1582 class AssignmentInheritanceTestCase(test_v3.RestfulTestCase,
 1583                                     test_v3.AssignmentTestMixin):
 1584     """Test inheritance crud and its effects."""
 1585 
 1586     def test_get_token_from_inherited_user_domain_role_grants(self):
 1587         # Create a new user to ensure that no grant is loaded from sample data
 1588         user = unit.create_user(
 1589             PROVIDERS.identity_api, domain_id=self.domain_id
 1590         )
 1591 
 1592         # Define domain and project authentication data
 1593         domain_auth_data = self.build_authentication_request(
 1594             user_id=user['id'],
 1595             password=user['password'],
 1596             domain_id=self.domain_id)
 1597         project_auth_data = self.build_authentication_request(
 1598             user_id=user['id'],
 1599             password=user['password'],
 1600             project_id=self.project_id)
 1601 
 1602         # Check the user cannot get a domain nor a project token
 1603         self.v3_create_token(domain_auth_data,
 1604                              expected_status=http.client.UNAUTHORIZED)
 1605         self.v3_create_token(project_auth_data,
 1606                              expected_status=http.client.UNAUTHORIZED)
 1607 
 1608         # Grant non-inherited role for user on domain
 1609         non_inher_ud_link = self.build_role_assignment_link(
 1610             domain_id=self.domain_id, user_id=user['id'], role_id=self.role_id)
 1611         self.put(non_inher_ud_link)
 1612 
 1613         # Check the user can get only a domain token
 1614         self.v3_create_token(domain_auth_data)
 1615         self.v3_create_token(project_auth_data,
 1616                              expected_status=http.client.UNAUTHORIZED)
 1617 
 1618         # Create inherited role
 1619         inherited_role = unit.new_role_ref(name='inherited')
 1620         PROVIDERS.role_api.create_role(inherited_role['id'], inherited_role)
 1621 
 1622         # Grant inherited role for user on domain
 1623         inher_ud_link = self.build_role_assignment_link(
 1624             domain_id=self.domain_id, user_id=user['id'],
 1625             role_id=inherited_role['id'], inherited_to_projects=True)
 1626         self.put(inher_ud_link)
 1627 
 1628         # Check the user can get both a domain and a project token
 1629         self.v3_create_token(domain_auth_data)
 1630         self.v3_create_token(project_auth_data)
 1631 
 1632         # Delete inherited grant
 1633         self.delete(inher_ud_link)
 1634 
 1635         # Check the user can only get a domain token
 1636         self.v3_create_token(domain_auth_data)
 1637         self.v3_create_token(project_auth_data,
 1638                              expected_status=http.client.UNAUTHORIZED)
 1639 
 1640         # Delete non-inherited grant
 1641         self.delete(non_inher_ud_link)
 1642 
 1643         # Check the user cannot get a domain token anymore
 1644         self.v3_create_token(domain_auth_data,
 1645                              expected_status=http.client.UNAUTHORIZED)
 1646 
 1647     def test_get_token_from_inherited_group_domain_role_grants(self):
 1648         # Create a new group and put a new user in it to
 1649         # ensure that no grant is loaded from sample data
 1650         user = unit.create_user(
 1651             PROVIDERS.identity_api, domain_id=self.domain_id
 1652         )
 1653 
 1654         group = unit.new_group_ref(domain_id=self.domain['id'])
 1655         group = PROVIDERS.identity_api.create_group(group)
 1656         PROVIDERS.identity_api.add_user_to_group(user['id'], group['id'])
 1657 
 1658         # Define domain and project authentication data
 1659         domain_auth_data = self.build_authentication_request(
 1660             user_id=user['id'],
 1661             password=user['password'],
 1662             domain_id=self.domain_id)
 1663         project_auth_data = self.build_authentication_request(
 1664             user_id=user['id'],
 1665             password=user['password'],
 1666             project_id=self.project_id)
 1667 
 1668         # Check the user cannot get a domain nor a project token
 1669         self.v3_create_token(domain_auth_data,
 1670                              expected_status=http.client.UNAUTHORIZED)
 1671         self.v3_create_token(project_auth_data,
 1672                              expected_status=http.client.UNAUTHORIZED)
 1673 
 1674         # Grant non-inherited role for user on domain
 1675         non_inher_gd_link = self.build_role_assignment_link(
 1676             domain_id=self.domain_id, user_id=user['id'], role_id=self.role_id)
 1677         self.put(non_inher_gd_link)
 1678 
 1679         # Check the user can get only a domain token
 1680         self.v3_create_token(domain_auth_data)
 1681         self.v3_create_token(project_auth_data,
 1682                              expected_status=http.client.UNAUTHORIZED)
 1683 
 1684         # Create inherited role
 1685         inherited_role = unit.new_role_ref(name='inherited')
 1686         PROVIDERS.role_api.create_role(inherited_role['id'], inherited_role)
 1687 
 1688         # Grant inherited role for user on domain
 1689         inher_gd_link = self.build_role_assignment_link(
 1690             domain_id=self.domain_id, user_id=user['id'],
 1691             role_id=inherited_role['id'], inherited_to_projects=True)
 1692         self.put(inher_gd_link)
 1693 
 1694         # Check the user can get both a domain and a project token
 1695         self.v3_create_token(domain_auth_data)
 1696         self.v3_create_token(project_auth_data)
 1697 
 1698         # Delete inherited grant
 1699         self.delete(inher_gd_link)
 1700 
 1701         # Check the user can only get a domain token
 1702         self.v3_create_token(domain_auth_data)
 1703         self.v3_create_token(project_auth_data,
 1704                              expected_status=http.client.UNAUTHORIZED)
 1705 
 1706         # Delete non-inherited grant
 1707         self.delete(non_inher_gd_link)
 1708 
 1709         # Check the user cannot get a domain token anymore
 1710         self.v3_create_token(domain_auth_data,
 1711                              expected_status=http.client.UNAUTHORIZED)
 1712 
 1713     def _test_crud_inherited_and_direct_assignment_on_target(self, target_url):
 1714         time = datetime.datetime.utcnow()
 1715         with freezegun.freeze_time(time) as frozen_datetime:
 1716             # Create a new role to avoid assignments loaded from sample data
 1717             role = unit.new_role_ref()
 1718             PROVIDERS.role_api.create_role(role['id'], role)
 1719 
 1720             # Define URLs
 1721             direct_url = '%s/users/%s/roles/%s' % (
 1722                 target_url, self.user_id, role['id'])
 1723             inherited_url = ('/OS-INHERIT/%s/inherited_to_projects' %
 1724                              direct_url.lstrip('/'))
 1725 
 1726             # Create the direct assignment
 1727             self.put(direct_url)
 1728             # Check the direct assignment exists, but the inherited one does
 1729             # not
 1730             self.head(direct_url)
 1731             self.head(inherited_url, expected_status=http.client.NOT_FOUND)
 1732 
 1733             # Now add the inherited assignment
 1734             self.put(inherited_url)
 1735             # Check both the direct and inherited assignment exist
 1736             self.head(direct_url)
 1737             self.head(inherited_url)
 1738 
 1739             # Delete indirect assignment
 1740             self.delete(inherited_url)
 1741             frozen_datetime.tick(delta=datetime.timedelta(seconds=1))
 1742             # Check the direct assignment exists, but the inherited one does
 1743             # not
 1744             self.head(direct_url)
 1745             self.head(inherited_url, expected_status=http.client.NOT_FOUND)
 1746 
 1747             # Now delete the inherited assignment
 1748             self.delete(direct_url)
 1749             # Check that none of them exist
 1750             self.head(direct_url, expected_status=http.client.NOT_FOUND)
 1751             self.head(inherited_url, expected_status=http.client.NOT_FOUND)
 1752 
 1753     def test_crud_inherited_and_direct_assignment_on_domains(self):
 1754         self._test_crud_inherited_and_direct_assignment_on_target(
 1755             '/domains/%s' % self.domain_id)
 1756 
 1757     def test_crud_inherited_and_direct_assignment_on_projects(self):
 1758         self._test_crud_inherited_and_direct_assignment_on_target(
 1759             '/projects/%s' % self.project_id)
 1760 
 1761     def test_crud_user_inherited_domain_role_grants(self):
 1762         role_list = []
 1763         for _ in range(2):
 1764             role = unit.new_role_ref()
 1765             PROVIDERS.role_api.create_role(role['id'], role)
 1766             role_list.append(role)
 1767 
 1768         # Create a non-inherited role as a spoiler
 1769         PROVIDERS.assignment_api.create_grant(
 1770             role_list[1]['id'], user_id=self.user['id'],
 1771             domain_id=self.domain_id)
 1772 
 1773         base_collection_url = (
 1774             '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
 1775                 'domain_id': self.domain_id,
 1776                 'user_id': self.user['id']})
 1777         member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
 1778             'collection_url': base_collection_url,
 1779             'role_id': role_list[0]['id']}
 1780         collection_url = base_collection_url + '/inherited_to_projects'
 1781 
 1782         self.put(member_url)
 1783 
 1784         # Check we can read it back
 1785         self.head(member_url)
 1786         self.get(member_url, expected_status=http.client.NO_CONTENT)
 1787         r = self.get(collection_url)
 1788         self.assertValidRoleListResponse(r, ref=role_list[0],
 1789                                          resource_url=collection_url)
 1790 
 1791         # Now delete and check its gone
 1792         self.delete(member_url)
 1793         r = self.get(collection_url)
 1794         self.assertValidRoleListResponse(r, expected_length=0,
 1795                                          resource_url=collection_url)
 1796 
 1797     def test_list_role_assignments_for_inherited_domain_grants(self):
 1798         """Call ``GET /role_assignments with inherited domain grants``.
 1799 
 1800         Test Plan:
 1801 
 1802         - Create 4 roles
 1803         - Create a domain with a user and two projects
 1804         - Assign two direct roles to project1
 1805         - Assign a spoiler role to project2
 1806         - Issue the URL to add inherited role to the domain
 1807         - Issue the URL to check it is indeed on the domain
 1808         - Issue the URL to check effective roles on project1 - this
 1809           should return 3 roles.
 1810 
 1811         """
 1812         role_list = []
 1813         for _ in range(4):
 1814             role = unit.new_role_ref()
 1815             PROVIDERS.role_api.create_role(role['id'], role)
 1816             role_list.append(role)
 1817 
 1818         domain = unit.new_domain_ref()
 1819         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 1820         user1 = unit.create_user(
 1821             PROVIDERS.identity_api, domain_id=domain['id']
 1822         )
 1823         project1 = unit.new_project_ref(domain_id=domain['id'])
 1824         PROVIDERS.resource_api.create_project(project1['id'], project1)
 1825         project2 = unit.new_project_ref(domain_id=domain['id'])
 1826         PROVIDERS.resource_api.create_project(project2['id'], project2)
 1827         # Add some roles to the project
 1828         PROVIDERS.assignment_api.add_role_to_user_and_project(
 1829             user1['id'], project1['id'], role_list[0]['id'])
 1830         PROVIDERS.assignment_api.add_role_to_user_and_project(
 1831             user1['id'], project1['id'], role_list[1]['id'])
 1832         # ..and one on a different project as a spoiler
 1833         PROVIDERS.assignment_api.add_role_to_user_and_project(
 1834             user1['id'], project2['id'], role_list[2]['id'])
 1835 
 1836         # Now create our inherited role on the domain
 1837         base_collection_url = (
 1838             '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
 1839                 'domain_id': domain['id'],
 1840                 'user_id': user1['id']})
 1841         member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
 1842             'collection_url': base_collection_url,
 1843             'role_id': role_list[3]['id']}
 1844         collection_url = base_collection_url + '/inherited_to_projects'
 1845 
 1846         self.put(member_url)
 1847         self.head(member_url)
 1848         self.get(member_url, expected_status=http.client.NO_CONTENT)
 1849         r = self.get(collection_url)
 1850         self.assertValidRoleListResponse(r, ref=role_list[3],
 1851                                          resource_url=collection_url)
 1852 
 1853         # Now use the list domain role assignments api to check if this
 1854         # is included
 1855         collection_url = (
 1856             '/role_assignments?user.id=%(user_id)s'
 1857             '&scope.domain.id=%(domain_id)s' % {
 1858                 'user_id': user1['id'],
 1859                 'domain_id': domain['id']})
 1860         r = self.get(collection_url)
 1861         self.assertValidRoleAssignmentListResponse(r,
 1862                                                    expected_length=1,
 1863                                                    resource_url=collection_url)
 1864         ud_entity = self.build_role_assignment_entity(
 1865             domain_id=domain['id'], user_id=user1['id'],
 1866             role_id=role_list[3]['id'], inherited_to_projects=True)
 1867         self.assertRoleAssignmentInListResponse(r, ud_entity)
 1868 
 1869         # Now ask for effective list role assignments - the role should
 1870         # turn into a project role, along with the two direct roles that are
 1871         # on the project
 1872         collection_url = (
 1873             '/role_assignments?effective&user.id=%(user_id)s'
 1874             '&scope.project.id=%(project_id)s' % {
 1875                 'user_id': user1['id'],
 1876                 'project_id': project1['id']})
 1877         r = self.get(collection_url)
 1878         self.assertValidRoleAssignmentListResponse(r,
 1879                                                    expected_length=3,
 1880                                                    resource_url=collection_url)
 1881         # An effective role for an inherited role will be a project
 1882         # entity, with a domain link to the inherited assignment
 1883         ud_url = self.build_role_assignment_link(
 1884             domain_id=domain['id'], user_id=user1['id'],
 1885             role_id=role_list[3]['id'], inherited_to_projects=True)
 1886         up_entity = self.build_role_assignment_entity(
 1887             link=ud_url, project_id=project1['id'],
 1888             user_id=user1['id'], role_id=role_list[3]['id'],
 1889             inherited_to_projects=True)
 1890         self.assertRoleAssignmentInListResponse(r, up_entity)
 1891 
 1892     def _test_list_role_assignments_include_names(self, role1):
 1893         """Call ``GET /role_assignments with include names``.
 1894 
 1895         Test Plan:
 1896 
 1897         - Create a domain with a group and a user
 1898         - Create a project with a group and a user
 1899 
 1900         """
 1901         role1 = unit.new_role_ref()
 1902         PROVIDERS.role_api.create_role(role1['id'], role1)
 1903         user1 = unit.create_user(
 1904             PROVIDERS.identity_api, domain_id=self.domain_id
 1905         )
 1906         group = unit.new_group_ref(domain_id=self.domain_id)
 1907         group = PROVIDERS.identity_api.create_group(group)
 1908         project1 = unit.new_project_ref(domain_id=self.domain_id)
 1909         PROVIDERS.resource_api.create_project(project1['id'], project1)
 1910 
 1911         expected_entity1 = self.build_role_assignment_entity_include_names(
 1912             role_ref=role1,
 1913             project_ref=project1,
 1914             user_ref=user1)
 1915         self.put(expected_entity1['links']['assignment'])
 1916         expected_entity2 = self.build_role_assignment_entity_include_names(
 1917             role_ref=role1,
 1918             domain_ref=self.domain,
 1919             group_ref=group)
 1920         self.put(expected_entity2['links']['assignment'])
 1921         expected_entity3 = self.build_role_assignment_entity_include_names(
 1922             role_ref=role1,
 1923             domain_ref=self.domain,
 1924             user_ref=user1)
 1925         self.put(expected_entity3['links']['assignment'])
 1926         expected_entity4 = self.build_role_assignment_entity_include_names(
 1927             role_ref=role1,
 1928             project_ref=project1,
 1929             group_ref=group)
 1930         self.put(expected_entity4['links']['assignment'])
 1931 
 1932         collection_url_domain = (
 1933             '/role_assignments?include_names&scope.domain.id=%(domain_id)s' % {
 1934                 'domain_id': self.domain_id})
 1935         rs_domain = self.get(collection_url_domain)
 1936         collection_url_project = (
 1937             '/role_assignments?include_names&'
 1938             'scope.project.id=%(project_id)s' % {
 1939                 'project_id': project1['id']})
 1940         rs_project = self.get(collection_url_project)
 1941         collection_url_group = (
 1942             '/role_assignments?include_names&group.id=%(group_id)s' % {
 1943                 'group_id': group['id']})
 1944         rs_group = self.get(collection_url_group)
 1945         collection_url_user = (
 1946             '/role_assignments?include_names&user.id=%(user_id)s' % {
 1947                 'user_id': user1['id']})
 1948         rs_user = self.get(collection_url_user)
 1949         collection_url_role = (
 1950             '/role_assignments?include_names&role.id=%(role_id)s' % {
 1951                 'role_id': role1['id']})
 1952         rs_role = self.get(collection_url_role)
 1953         # Make sure all entities were created successfully
 1954         self.assertEqual(http.client.OK, rs_domain.status_int)
 1955         self.assertEqual(http.client.OK, rs_project.status_int)
 1956         self.assertEqual(http.client.OK, rs_group.status_int)
 1957         self.assertEqual(http.client.OK, rs_user.status_int)
 1958         # Make sure we can get back the correct number of entities
 1959         self.assertValidRoleAssignmentListResponse(
 1960             rs_domain,
 1961             expected_length=2,
 1962             resource_url=collection_url_domain)
 1963         self.assertValidRoleAssignmentListResponse(
 1964             rs_project,
 1965             expected_length=2,
 1966             resource_url=collection_url_project)
 1967         self.assertValidRoleAssignmentListResponse(
 1968             rs_group,
 1969             expected_length=2,
 1970             resource_url=collection_url_group)
 1971         self.assertValidRoleAssignmentListResponse(
 1972             rs_user,
 1973             expected_length=2,
 1974             resource_url=collection_url_user)
 1975         self.assertValidRoleAssignmentListResponse(
 1976             rs_role,
 1977             expected_length=4,
 1978             resource_url=collection_url_role)
 1979         # Verify all types of entities have the correct format
 1980         self.assertRoleAssignmentInListResponse(rs_domain, expected_entity2)
 1981         self.assertRoleAssignmentInListResponse(rs_project, expected_entity1)
 1982         self.assertRoleAssignmentInListResponse(rs_group, expected_entity4)
 1983         self.assertRoleAssignmentInListResponse(rs_user, expected_entity3)
 1984         self.assertRoleAssignmentInListResponse(rs_role, expected_entity1)
 1985 
 1986     def test_list_role_assignments_include_names_global_role(self):
 1987         role = unit.new_role_ref()
 1988         PROVIDERS.role_api.create_role(role['id'], role)
 1989 
 1990         self._test_list_role_assignments_include_names(role)
 1991 
 1992     def test_list_role_assignments_include_names_domain_role(self):
 1993         role = unit.new_role_ref(domain_id=self.domain['id'])
 1994         PROVIDERS.role_api.create_role(role['id'], role)
 1995 
 1996         self._test_list_role_assignments_include_names(role)
 1997 
 1998     @test_utils.wip("Skipped until Bug 1754677 is resolved")
 1999     def test_remove_assignment_for_project_acting_as_domain(self):
 2000         """Test goal: remove assignment for project acting as domain.
 2001 
 2002         Ensure when we have two role assignments for the project
 2003         acting as domain, one dealing with it as a domain and other as a
 2004         project, we still able to remove those assignments later.
 2005 
 2006         Test plan:
 2007         - Create a role and a domain with a user;
 2008         - Grant a role for this user in this domain;
 2009         - Grant a role for this user in the same entity as a project;
 2010         - Ensure that both assignments were created and it was valid;
 2011         - Remove the domain assignment for the user and show that the project
 2012         assignment for him still valid
 2013 
 2014         """
 2015         role = unit.new_role_ref()
 2016         PROVIDERS.role_api.create_role(role['id'], role)
 2017         domain = unit.new_domain_ref()
 2018         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 2019         user = unit.create_user(PROVIDERS.identity_api, domain_id=domain['id'])
 2020 
 2021         assignment_domain = self.build_role_assignment_entity(
 2022             role_id=role['id'], domain_id=domain['id'], user_id=user['id'],
 2023             inherited_to_projects=False)
 2024         assignment_project = self.build_role_assignment_entity(
 2025             role_id=role['id'], project_id=domain['id'], user_id=user['id'],
 2026             inherited_to_projects=False)
 2027 
 2028         self.put(assignment_domain['links']['assignment'])
 2029         self.put(assignment_project['links']['assignment'])
 2030 
 2031         collection_url = '/role_assignments?user.id=%(user_id)s' % (
 2032                          {'user_id': user['id']})
 2033         result = self.get(collection_url)
 2034         # We have two role assignments based in both roles for the domain and
 2035         # project scope
 2036         self.assertValidRoleAssignmentListResponse(
 2037             result, expected_length=2, resource_url=collection_url)
 2038         self.assertRoleAssignmentInListResponse(result, assignment_domain)
 2039 
 2040         domain_url = '/domains/%s/users/%s/roles/%s' % (
 2041             domain['id'], user['id'], role['id'])
 2042         self.delete(domain_url)
 2043 
 2044         collection_url = '/role_assignments?user.id=%(user_id)s' % (
 2045                          {'user_id': user['id']})
 2046         result = self.get(collection_url)
 2047         # Now we only have one assignment for the project scope since the
 2048         # domain scope was removed.
 2049         self.assertValidRoleAssignmentListResponse(
 2050             result, expected_length=1, resource_url=collection_url)
 2051         self.assertRoleAssignmentInListResponse(result, assignment_project)
 2052 
 2053     def test_list_inherited_role_assignments_include_names(self):
 2054         """Call ``GET /role_assignments?include_names``.
 2055 
 2056         Test goal: ensure calling list role assignments including names
 2057         honors the inherited role assignments flag.
 2058 
 2059         Test plan:
 2060         - Create a role and a domain with a user;
 2061         - Create a inherited role assignment;
 2062         - List role assignments for that user;
 2063         - List role assignments for that user including names.
 2064 
 2065         """
 2066         role = unit.new_role_ref()
 2067         PROVIDERS.role_api.create_role(role['id'], role)
 2068         domain = unit.new_domain_ref()
 2069         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 2070         user = unit.create_user(PROVIDERS.identity_api, domain_id=domain['id'])
 2071 
 2072         # Create and store expected assignment refs
 2073         assignment = self.build_role_assignment_entity(
 2074             role_id=role['id'], domain_id=domain['id'], user_id=user['id'],
 2075             inherited_to_projects=True)
 2076         assignment_names = self.build_role_assignment_entity_include_names(
 2077             role_ref=role, domain_ref=domain, user_ref=user,
 2078             inherited_assignment=True)
 2079 
 2080         # Ensure expected assignment refs are inherited and have the same URL
 2081         self.assertEqual('projects',
 2082                          assignment['scope']['OS-INHERIT:inherited_to'])
 2083         self.assertEqual('projects',
 2084                          assignment_names['scope']['OS-INHERIT:inherited_to'])
 2085         self.assertEqual(assignment['links']['assignment'],
 2086                          assignment_names['links']['assignment'])
 2087 
 2088         self.put(assignment['links']['assignment'])
 2089 
 2090         collection_url = '/role_assignments?user.id=%(user_id)s' % (
 2091                          {'user_id': user['id']})
 2092         result = self.get(collection_url)
 2093         self.assertValidRoleAssignmentListResponse(
 2094             result, expected_length=1, resource_url=collection_url)
 2095         self.assertRoleAssignmentInListResponse(result, assignment)
 2096 
 2097         collection_url = ('/role_assignments?include_names&'
 2098                           'user.id=%(user_id)s' % {'user_id': user['id']})
 2099         result = self.get(collection_url)
 2100         self.assertValidRoleAssignmentListResponse(
 2101             result, expected_length=1, resource_url=collection_url)
 2102         self.assertRoleAssignmentInListResponse(result, assignment_names)
 2103 
 2104     def test_list_role_assignments_for_disabled_inheritance_extension(self):
 2105         """Call ``GET /role_assignments with inherited domain grants``.
 2106 
 2107         Test Plan:
 2108 
 2109         - Issue the URL to add inherited role to the domain
 2110         - Issue the URL to check effective roles on project include the
 2111           inherited role
 2112         - Disable the extension
 2113         - Re-check the effective roles, proving the inherited role no longer
 2114           shows up.
 2115 
 2116         """
 2117         role_list = []
 2118         for _ in range(4):
 2119             role = unit.new_role_ref()
 2120             PROVIDERS.role_api.create_role(role['id'], role)
 2121             role_list.append(role)
 2122 
 2123         domain = unit.new_domain_ref()
 2124         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 2125         user1 = unit.create_user(
 2126             PROVIDERS.identity_api, domain_id=domain['id']
 2127         )
 2128         project1 = unit.new_project_ref(domain_id=domain['id'])
 2129         PROVIDERS.resource_api.create_project(project1['id'], project1)
 2130         project2 = unit.new_project_ref(domain_id=domain['id'])
 2131         PROVIDERS.resource_api.create_project(project2['id'], project2)
 2132         # Add some roles to the project
 2133         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2134             user1['id'], project1['id'], role_list[0]['id'])
 2135         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2136             user1['id'], project1['id'], role_list[1]['id'])
 2137         # ..and one on a different project as a spoiler
 2138         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2139             user1['id'], project2['id'], role_list[2]['id'])
 2140 
 2141         # Now create our inherited role on the domain
 2142         base_collection_url = (
 2143             '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
 2144                 'domain_id': domain['id'],
 2145                 'user_id': user1['id']})
 2146         member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
 2147             'collection_url': base_collection_url,
 2148             'role_id': role_list[3]['id']}
 2149         collection_url = base_collection_url + '/inherited_to_projects'
 2150 
 2151         self.put(member_url)
 2152         self.head(member_url)
 2153         self.get(member_url, expected_status=http.client.NO_CONTENT)
 2154         r = self.get(collection_url)
 2155         self.assertValidRoleListResponse(r, ref=role_list[3],
 2156                                          resource_url=collection_url)
 2157 
 2158         # Get effective list role assignments - the role should
 2159         # turn into a project role, along with the two direct roles that are
 2160         # on the project
 2161         collection_url = (
 2162             '/role_assignments?effective&user.id=%(user_id)s'
 2163             '&scope.project.id=%(project_id)s' % {
 2164                 'user_id': user1['id'],
 2165                 'project_id': project1['id']})
 2166         r = self.get(collection_url)
 2167         self.assertValidRoleAssignmentListResponse(r,
 2168                                                    expected_length=3,
 2169                                                    resource_url=collection_url)
 2170 
 2171         ud_url = self.build_role_assignment_link(
 2172             domain_id=domain['id'], user_id=user1['id'],
 2173             role_id=role_list[3]['id'], inherited_to_projects=True)
 2174         up_entity = self.build_role_assignment_entity(
 2175             link=ud_url, project_id=project1['id'],
 2176             user_id=user1['id'], role_id=role_list[3]['id'],
 2177             inherited_to_projects=True)
 2178 
 2179         self.assertRoleAssignmentInListResponse(r, up_entity)
 2180 
 2181     def test_list_role_assignments_for_inherited_group_domain_grants(self):
 2182         """Call ``GET /role_assignments with inherited group domain grants``.
 2183 
 2184         Test Plan:
 2185 
 2186         - Create 4 roles
 2187         - Create a domain with a user and two projects
 2188         - Assign two direct roles to project1
 2189         - Assign a spoiler role to project2
 2190         - Issue the URL to add inherited role to the domain
 2191         - Issue the URL to check it is indeed on the domain
 2192         - Issue the URL to check effective roles on project1 - this
 2193           should return 3 roles.
 2194 
 2195         """
 2196         role_list = []
 2197         for _ in range(4):
 2198             role = unit.new_role_ref()
 2199             PROVIDERS.role_api.create_role(role['id'], role)
 2200             role_list.append(role)
 2201 
 2202         domain = unit.new_domain_ref()
 2203         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 2204         user1 = unit.create_user(
 2205             PROVIDERS.identity_api, domain_id=domain['id']
 2206         )
 2207         user2 = unit.create_user(
 2208             PROVIDERS.identity_api, domain_id=domain['id']
 2209         )
 2210         group1 = unit.new_group_ref(domain_id=domain['id'])
 2211         group1 = PROVIDERS.identity_api.create_group(group1)
 2212         PROVIDERS.identity_api.add_user_to_group(
 2213             user1['id'], group1['id']
 2214         )
 2215         PROVIDERS.identity_api.add_user_to_group(
 2216             user2['id'], group1['id']
 2217         )
 2218         project1 = unit.new_project_ref(domain_id=domain['id'])
 2219         PROVIDERS.resource_api.create_project(project1['id'], project1)
 2220         project2 = unit.new_project_ref(domain_id=domain['id'])
 2221         PROVIDERS.resource_api.create_project(project2['id'], project2)
 2222         # Add some roles to the project
 2223         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2224             user1['id'], project1['id'], role_list[0]['id'])
 2225         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2226             user1['id'], project1['id'], role_list[1]['id'])
 2227         # ..and one on a different project as a spoiler
 2228         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2229             user1['id'], project2['id'], role_list[2]['id'])
 2230 
 2231         # Now create our inherited role on the domain
 2232         base_collection_url = (
 2233             '/OS-INHERIT/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
 2234                 'domain_id': domain['id'],
 2235                 'group_id': group1['id']})
 2236         member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
 2237             'collection_url': base_collection_url,
 2238             'role_id': role_list[3]['id']}
 2239         collection_url = base_collection_url + '/inherited_to_projects'
 2240 
 2241         self.put(member_url)
 2242         self.head(member_url)
 2243         self.get(member_url, expected_status=http.client.NO_CONTENT)
 2244         r = self.get(collection_url)
 2245         self.assertValidRoleListResponse(r, ref=role_list[3],
 2246                                          resource_url=collection_url)
 2247 
 2248         # Now use the list domain role assignments api to check if this
 2249         # is included
 2250         collection_url = (
 2251             '/role_assignments?group.id=%(group_id)s'
 2252             '&scope.domain.id=%(domain_id)s' % {
 2253                 'group_id': group1['id'],
 2254                 'domain_id': domain['id']})
 2255         r = self.get(collection_url)
 2256         self.assertValidRoleAssignmentListResponse(r,
 2257                                                    expected_length=1,
 2258                                                    resource_url=collection_url)
 2259         gd_entity = self.build_role_assignment_entity(
 2260             domain_id=domain['id'], group_id=group1['id'],
 2261             role_id=role_list[3]['id'], inherited_to_projects=True)
 2262         self.assertRoleAssignmentInListResponse(r, gd_entity)
 2263 
 2264         # Now ask for effective list role assignments - the role should
 2265         # turn into a user project role, along with the two direct roles
 2266         # that are on the project
 2267         collection_url = (
 2268             '/role_assignments?effective&user.id=%(user_id)s'
 2269             '&scope.project.id=%(project_id)s' % {
 2270                 'user_id': user1['id'],
 2271                 'project_id': project1['id']})
 2272         r = self.get(collection_url)
 2273         self.assertValidRoleAssignmentListResponse(r,
 2274                                                    expected_length=3,
 2275                                                    resource_url=collection_url)
 2276         # An effective role for an inherited role will be a project
 2277         # entity, with a domain link to the inherited assignment
 2278         up_entity = self.build_role_assignment_entity(
 2279             link=gd_entity['links']['assignment'], project_id=project1['id'],
 2280             user_id=user1['id'], role_id=role_list[3]['id'],
 2281             inherited_to_projects=True)
 2282         self.assertRoleAssignmentInListResponse(r, up_entity)
 2283 
 2284     def test_filtered_role_assignments_for_inherited_grants(self):
 2285         """Call ``GET /role_assignments?scope.OS-INHERIT:inherited_to``.
 2286 
 2287         Test Plan:
 2288 
 2289         - Create 5 roles
 2290         - Create a domain with a user, group and two projects
 2291         - Assign three direct spoiler roles to projects
 2292         - Issue the URL to add an inherited user role to the domain
 2293         - Issue the URL to add an inherited group role to the domain
 2294         - Issue the URL to filter by inherited roles - this should
 2295           return just the 2 inherited roles.
 2296 
 2297         """
 2298         role_list = []
 2299         for _ in range(5):
 2300             role = unit.new_role_ref()
 2301             PROVIDERS.role_api.create_role(role['id'], role)
 2302             role_list.append(role)
 2303 
 2304         domain = unit.new_domain_ref()
 2305         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 2306         user1 = unit.create_user(
 2307             PROVIDERS.identity_api, domain_id=domain['id']
 2308         )
 2309         group1 = unit.new_group_ref(domain_id=domain['id'])
 2310         group1 = PROVIDERS.identity_api.create_group(group1)
 2311         project1 = unit.new_project_ref(domain_id=domain['id'])
 2312         PROVIDERS.resource_api.create_project(project1['id'], project1)
 2313         project2 = unit.new_project_ref(domain_id=domain['id'])
 2314         PROVIDERS.resource_api.create_project(project2['id'], project2)
 2315         # Add some spoiler roles to the projects
 2316         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2317             user1['id'], project1['id'], role_list[0]['id'])
 2318         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2319             user1['id'], project2['id'], role_list[1]['id'])
 2320         # Create a non-inherited role as a spoiler
 2321         PROVIDERS.assignment_api.create_grant(
 2322             role_list[2]['id'], user_id=user1['id'], domain_id=domain['id'])
 2323 
 2324         # Now create two inherited roles on the domain, one for a user
 2325         # and one for a domain
 2326         base_collection_url = (
 2327             '/OS-INHERIT/domains/%(domain_id)s/users/%(user_id)s/roles' % {
 2328                 'domain_id': domain['id'],
 2329                 'user_id': user1['id']})
 2330         member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
 2331             'collection_url': base_collection_url,
 2332             'role_id': role_list[3]['id']}
 2333         collection_url = base_collection_url + '/inherited_to_projects'
 2334 
 2335         self.put(member_url)
 2336         self.head(member_url)
 2337         self.get(member_url, expected_status=http.client.NO_CONTENT)
 2338         r = self.get(collection_url)
 2339         self.assertValidRoleListResponse(r, ref=role_list[3],
 2340                                          resource_url=collection_url)
 2341 
 2342         base_collection_url = (
 2343             '/OS-INHERIT/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
 2344                 'domain_id': domain['id'],
 2345                 'group_id': group1['id']})
 2346         member_url = '%(collection_url)s/%(role_id)s/inherited_to_projects' % {
 2347             'collection_url': base_collection_url,
 2348             'role_id': role_list[4]['id']}
 2349         collection_url = base_collection_url + '/inherited_to_projects'
 2350 
 2351         self.put(member_url)
 2352         self.head(member_url)
 2353         self.get(member_url, expected_status=http.client.NO_CONTENT)
 2354         r = self.get(collection_url)
 2355         self.assertValidRoleListResponse(r, ref=role_list[4],
 2356                                          resource_url=collection_url)
 2357 
 2358         # Now use the list role assignments api to get a list of inherited
 2359         # roles on the domain - should get back the two roles
 2360         collection_url = (
 2361             '/role_assignments?scope.OS-INHERIT:inherited_to=projects')
 2362         r = self.get(collection_url)
 2363         self.assertValidRoleAssignmentListResponse(r,
 2364                                                    expected_length=2,
 2365                                                    resource_url=collection_url)
 2366         ud_entity = self.build_role_assignment_entity(
 2367             domain_id=domain['id'], user_id=user1['id'],
 2368             role_id=role_list[3]['id'], inherited_to_projects=True)
 2369         gd_entity = self.build_role_assignment_entity(
 2370             domain_id=domain['id'], group_id=group1['id'],
 2371             role_id=role_list[4]['id'], inherited_to_projects=True)
 2372         self.assertRoleAssignmentInListResponse(r, ud_entity)
 2373         self.assertRoleAssignmentInListResponse(r, gd_entity)
 2374 
 2375     def _setup_hierarchical_projects_scenario(self):
 2376         """Create basic hierarchical projects scenario.
 2377 
 2378         This basic scenario contains a root with one leaf project and
 2379         two roles with the following names: non-inherited and inherited.
 2380 
 2381         """
 2382         # Create project hierarchy
 2383         root = unit.new_project_ref(domain_id=self.domain['id'])
 2384         leaf = unit.new_project_ref(domain_id=self.domain['id'],
 2385                                     parent_id=root['id'])
 2386 
 2387         PROVIDERS.resource_api.create_project(root['id'], root)
 2388         PROVIDERS.resource_api.create_project(leaf['id'], leaf)
 2389 
 2390         # Create 'non-inherited' and 'inherited' roles
 2391         non_inherited_role = unit.new_role_ref(name='non-inherited')
 2392         PROVIDERS.role_api.create_role(
 2393             non_inherited_role['id'], non_inherited_role
 2394         )
 2395         inherited_role = unit.new_role_ref(name='inherited')
 2396         PROVIDERS.role_api.create_role(inherited_role['id'], inherited_role)
 2397 
 2398         return (root['id'], leaf['id'],
 2399                 non_inherited_role['id'], inherited_role['id'])
 2400 
 2401     def test_get_token_from_inherited_user_project_role_grants(self):
 2402         # Create default scenario
 2403         root_id, leaf_id, non_inherited_role_id, inherited_role_id = (
 2404             self._setup_hierarchical_projects_scenario())
 2405 
 2406         # Define root and leaf projects authentication data
 2407         root_project_auth_data = self.build_authentication_request(
 2408             user_id=self.user['id'],
 2409             password=self.user['password'],
 2410             project_id=root_id)
 2411         leaf_project_auth_data = self.build_authentication_request(
 2412             user_id=self.user['id'],
 2413             password=self.user['password'],
 2414             project_id=leaf_id)
 2415 
 2416         # Check the user cannot get a token on root nor leaf project
 2417         self.v3_create_token(root_project_auth_data,
 2418                              expected_status=http.client.UNAUTHORIZED)
 2419         self.v3_create_token(leaf_project_auth_data,
 2420                              expected_status=http.client.UNAUTHORIZED)
 2421 
 2422         # Grant non-inherited role for user on leaf project
 2423         non_inher_up_link = self.build_role_assignment_link(
 2424             project_id=leaf_id, user_id=self.user['id'],
 2425             role_id=non_inherited_role_id)
 2426         self.put(non_inher_up_link)
 2427 
 2428         # Check the user can only get a token on leaf project
 2429         self.v3_create_token(root_project_auth_data,
 2430                              expected_status=http.client.UNAUTHORIZED)
 2431         self.v3_create_token(leaf_project_auth_data)
 2432 
 2433         # Grant inherited role for user on root project
 2434         inher_up_link = self.build_role_assignment_link(
 2435             project_id=root_id, user_id=self.user['id'],
 2436             role_id=inherited_role_id, inherited_to_projects=True)
 2437         self.put(inher_up_link)
 2438 
 2439         # Check the user still can get a token only on leaf project
 2440         self.v3_create_token(root_project_auth_data,
 2441                              expected_status=http.client.UNAUTHORIZED)
 2442         self.v3_create_token(leaf_project_auth_data)
 2443 
 2444         # Delete non-inherited grant
 2445         self.delete(non_inher_up_link)
 2446 
 2447         # Check the inherited role still applies for leaf project
 2448         self.v3_create_token(root_project_auth_data,
 2449                              expected_status=http.client.UNAUTHORIZED)
 2450         self.v3_create_token(leaf_project_auth_data)
 2451 
 2452         # Delete inherited grant
 2453         self.delete(inher_up_link)
 2454 
 2455         # Check the user cannot get a token on leaf project anymore
 2456         self.v3_create_token(leaf_project_auth_data,
 2457                              expected_status=http.client.UNAUTHORIZED)
 2458 
 2459     def test_get_token_from_inherited_group_project_role_grants(self):
 2460         # Create default scenario
 2461         root_id, leaf_id, non_inherited_role_id, inherited_role_id = (
 2462             self._setup_hierarchical_projects_scenario())
 2463 
 2464         # Create group and add user to it
 2465         group = unit.new_group_ref(domain_id=self.domain['id'])
 2466         group = PROVIDERS.identity_api.create_group(group)
 2467         PROVIDERS.identity_api.add_user_to_group(self.user['id'], group['id'])
 2468 
 2469         # Define root and leaf projects authentication data
 2470         root_project_auth_data = self.build_authentication_request(
 2471             user_id=self.user['id'],
 2472             password=self.user['password'],
 2473             project_id=root_id)
 2474         leaf_project_auth_data = self.build_authentication_request(
 2475             user_id=self.user['id'],
 2476             password=self.user['password'],
 2477             project_id=leaf_id)
 2478 
 2479         # Check the user cannot get a token on root nor leaf project
 2480         self.v3_create_token(root_project_auth_data,
 2481                              expected_status=http.client.UNAUTHORIZED)
 2482         self.v3_create_token(leaf_project_auth_data,
 2483                              expected_status=http.client.UNAUTHORIZED)
 2484 
 2485         # Grant non-inherited role for group on leaf project
 2486         non_inher_gp_link = self.build_role_assignment_link(
 2487             project_id=leaf_id, group_id=group['id'],
 2488             role_id=non_inherited_role_id)
 2489         self.put(non_inher_gp_link)
 2490 
 2491         # Check the user can only get a token on leaf project
 2492         self.v3_create_token(root_project_auth_data,
 2493                              expected_status=http.client.UNAUTHORIZED)
 2494         self.v3_create_token(leaf_project_auth_data)
 2495 
 2496         # Grant inherited role for group on root project
 2497         inher_gp_link = self.build_role_assignment_link(
 2498             project_id=root_id, group_id=group['id'],
 2499             role_id=inherited_role_id, inherited_to_projects=True)
 2500         self.put(inher_gp_link)
 2501 
 2502         # Check the user still can get a token only on leaf project
 2503         self.v3_create_token(root_project_auth_data,
 2504                              expected_status=http.client.UNAUTHORIZED)
 2505         self.v3_create_token(leaf_project_auth_data)
 2506 
 2507         # Delete no-inherited grant
 2508         self.delete(non_inher_gp_link)
 2509 
 2510         # Check the inherited role still applies for leaf project
 2511         self.v3_create_token(leaf_project_auth_data)
 2512 
 2513         # Delete inherited grant
 2514         self.delete(inher_gp_link)
 2515 
 2516         # Check the user cannot get a token on leaf project anymore
 2517         self.v3_create_token(leaf_project_auth_data,
 2518                              expected_status=http.client.UNAUTHORIZED)
 2519 
 2520     def test_get_role_assignments_for_project_hierarchy(self):
 2521         """Call ``GET /role_assignments``.
 2522 
 2523         Test Plan:
 2524 
 2525         - Create 2 roles
 2526         - Create a hierarchy of projects with one root and one leaf project
 2527         - Issue the URL to add a non-inherited user role to the root project
 2528         - Issue the URL to add an inherited user role to the root project
 2529         - Issue the URL to get all role assignments - this should return just
 2530           2 roles (non-inherited and inherited) in the root project.
 2531 
 2532         """
 2533         # Create default scenario
 2534         root_id, leaf_id, non_inherited_role_id, inherited_role_id = (
 2535             self._setup_hierarchical_projects_scenario())
 2536 
 2537         # Grant non-inherited role
 2538         non_inher_up_entity = self.build_role_assignment_entity(
 2539             project_id=root_id, user_id=self.user['id'],
 2540             role_id=non_inherited_role_id)
 2541         self.put(non_inher_up_entity['links']['assignment'])
 2542 
 2543         # Grant inherited role
 2544         inher_up_entity = self.build_role_assignment_entity(
 2545             project_id=root_id, user_id=self.user['id'],
 2546             role_id=inherited_role_id, inherited_to_projects=True)
 2547         self.put(inher_up_entity['links']['assignment'])
 2548 
 2549         # Get role assignments
 2550         collection_url = '/role_assignments'
 2551         r = self.get(collection_url)
 2552         self.assertValidRoleAssignmentListResponse(r,
 2553                                                    resource_url=collection_url)
 2554 
 2555         # Assert that the user has non-inherited role on root project
 2556         self.assertRoleAssignmentInListResponse(r, non_inher_up_entity)
 2557 
 2558         # Assert that the user has inherited role on root project
 2559         self.assertRoleAssignmentInListResponse(r, inher_up_entity)
 2560 
 2561         # Assert that the user does not have non-inherited role on leaf project
 2562         non_inher_up_entity = self.build_role_assignment_entity(
 2563             project_id=leaf_id, user_id=self.user['id'],
 2564             role_id=non_inherited_role_id)
 2565         self.assertRoleAssignmentNotInListResponse(r, non_inher_up_entity)
 2566 
 2567         # Assert that the user does not have inherited role on leaf project
 2568         inher_up_entity['scope']['project']['id'] = leaf_id
 2569         self.assertRoleAssignmentNotInListResponse(r, inher_up_entity)
 2570 
 2571     def test_get_effective_role_assignments_for_project_hierarchy(self):
 2572         """Call ``GET /role_assignments?effective``.
 2573 
 2574         Test Plan:
 2575 
 2576         - Create 2 roles
 2577         - Create a hierarchy of projects with one root and one leaf project
 2578         - Issue the URL to add a non-inherited user role to the root project
 2579         - Issue the URL to add an inherited user role to the root project
 2580         - Issue the URL to get effective role assignments - this should return
 2581           1 role (non-inherited) on the root project and 1 role (inherited) on
 2582           the leaf project.
 2583 
 2584         """
 2585         # Create default scenario
 2586         root_id, leaf_id, non_inherited_role_id, inherited_role_id = (
 2587             self._setup_hierarchical_projects_scenario())
 2588 
 2589         # Grant non-inherited role
 2590         non_inher_up_entity = self.build_role_assignment_entity(
 2591             project_id=root_id, user_id=self.user['id'],
 2592             role_id=non_inherited_role_id)
 2593         self.put(non_inher_up_entity['links']['assignment'])
 2594 
 2595         # Grant inherited role
 2596         inher_up_entity = self.build_role_assignment_entity(
 2597             project_id=root_id, user_id=self.user['id'],
 2598             role_id=inherited_role_id, inherited_to_projects=True)
 2599         self.put(inher_up_entity['links']['assignment'])
 2600 
 2601         # Get effective role assignments
 2602         collection_url = '/role_assignments?effective'
 2603         r = self.get(collection_url)
 2604         self.assertValidRoleAssignmentListResponse(r,
 2605                                                    resource_url=collection_url)
 2606 
 2607         # Assert that the user has non-inherited role on root project
 2608         self.assertRoleAssignmentInListResponse(r, non_inher_up_entity)
 2609 
 2610         # Assert that the user does not have inherited role on root project
 2611         self.assertRoleAssignmentNotInListResponse(r, inher_up_entity)
 2612 
 2613         # Assert that the user does not have non-inherited role on leaf project
 2614         non_inher_up_entity = self.build_role_assignment_entity(
 2615             project_id=leaf_id, user_id=self.user['id'],
 2616             role_id=non_inherited_role_id)
 2617         self.assertRoleAssignmentNotInListResponse(r, non_inher_up_entity)
 2618 
 2619         # Assert that the user has inherited role on leaf project
 2620         inher_up_entity['scope']['project']['id'] = leaf_id
 2621         self.assertRoleAssignmentInListResponse(r, inher_up_entity)
 2622 
 2623     def test_project_id_specified_if_include_subtree_specified(self):
 2624         """When using include_subtree, you must specify a project ID."""
 2625         r = self.get('/role_assignments?include_subtree=True',
 2626                      expected_status=http.client.BAD_REQUEST)
 2627         error_msg = ("scope.project.id must be specified if include_subtree "
 2628                      "is also specified")
 2629         self.assertEqual(error_msg, r.result['error']['message'])
 2630         r = self.get('/role_assignments?scope.project.id&'
 2631                      'include_subtree=True',
 2632                      expected_status=http.client.BAD_REQUEST)
 2633         self.assertEqual(error_msg, r.result['error']['message'])
 2634 
 2635     def test_get_role_assignments_for_project_tree(self):
 2636         """Get role_assignment?scope.project.id=X&include_subtree``.
 2637 
 2638         Test Plan:
 2639 
 2640         - Create 2 roles and a hierarchy of projects with one root and one leaf
 2641         - Issue the URL to add a non-inherited user role to the root project
 2642           and the leaf project
 2643         - Issue the URL to get role assignments for the root project but
 2644           not the subtree - this should return just the root assignment
 2645         - Issue the URL to get role assignments for the root project and
 2646           it's subtree - this should return both assignments
 2647         - Check that explicitly setting include_subtree to False is the
 2648           equivalent to not including it at all in the query.
 2649 
 2650         """
 2651         # Create default scenario
 2652         root_id, leaf_id, non_inherited_role_id, unused_role_id = (
 2653             self._setup_hierarchical_projects_scenario())
 2654 
 2655         # Grant non-inherited role to root and leaf projects
 2656         non_inher_entity_root = self.build_role_assignment_entity(
 2657             project_id=root_id, user_id=self.user['id'],
 2658             role_id=non_inherited_role_id)
 2659         self.put(non_inher_entity_root['links']['assignment'])
 2660         non_inher_entity_leaf = self.build_role_assignment_entity(
 2661             project_id=leaf_id, user_id=self.user['id'],
 2662             role_id=non_inherited_role_id)
 2663         self.put(non_inher_entity_leaf['links']['assignment'])
 2664 
 2665         # Without the subtree, we should get the one assignment on the
 2666         # root project
 2667         collection_url = (
 2668             '/role_assignments?scope.project.id=%(project)s' % {
 2669                 'project': root_id})
 2670         r = self.get(collection_url)
 2671         self.assertValidRoleAssignmentListResponse(
 2672             r, resource_url=collection_url)
 2673 
 2674         self.assertThat(r.result['role_assignments'], matchers.HasLength(1))
 2675         self.assertRoleAssignmentInListResponse(r, non_inher_entity_root)
 2676 
 2677         # With the subtree, we should get both assignments
 2678         collection_url = (
 2679             '/role_assignments?scope.project.id=%(project)s'
 2680             '&include_subtree=True' % {
 2681                 'project': root_id})
 2682         r = self.get(collection_url)
 2683         self.assertValidRoleAssignmentListResponse(
 2684             r, resource_url=collection_url)
 2685 
 2686         self.assertThat(r.result['role_assignments'], matchers.HasLength(2))
 2687         self.assertRoleAssignmentInListResponse(r, non_inher_entity_root)
 2688         self.assertRoleAssignmentInListResponse(r, non_inher_entity_leaf)
 2689 
 2690         # With subtree=0, we should also only get the one assignment on the
 2691         # root project
 2692         collection_url = (
 2693             '/role_assignments?scope.project.id=%(project)s'
 2694             '&include_subtree=0' % {
 2695                 'project': root_id})
 2696         r = self.get(collection_url)
 2697         self.assertValidRoleAssignmentListResponse(
 2698             r, resource_url=collection_url)
 2699 
 2700         self.assertThat(r.result['role_assignments'], matchers.HasLength(1))
 2701         self.assertRoleAssignmentInListResponse(r, non_inher_entity_root)
 2702 
 2703     def test_get_effective_role_assignments_for_project_tree(self):
 2704         """Get role_assignment ?project_id=X&include_subtree=True&effective``.
 2705 
 2706         Test Plan:
 2707 
 2708         - Create 2 roles and a hierarchy of projects with one root and 4 levels
 2709           of child project
 2710         - Issue the URL to add a non-inherited user role to the root project
 2711           and a level 1 project
 2712         - Issue the URL to add an inherited user role on the level 2 project
 2713         - Issue the URL to get effective role assignments for the level 1
 2714           project and it's subtree - this should return a role (non-inherited)
 2715           on the level 1 project and roles (inherited) on each of the level
 2716           2, 3 and 4 projects
 2717 
 2718         """
 2719         # Create default scenario
 2720         root_id, leaf_id, non_inherited_role_id, inherited_role_id = (
 2721             self._setup_hierarchical_projects_scenario())
 2722 
 2723         # Add some extra projects to the project hierarchy
 2724         level2 = unit.new_project_ref(domain_id=self.domain['id'],
 2725                                       parent_id=leaf_id)
 2726         level3 = unit.new_project_ref(domain_id=self.domain['id'],
 2727                                       parent_id=level2['id'])
 2728         level4 = unit.new_project_ref(domain_id=self.domain['id'],
 2729                                       parent_id=level3['id'])
 2730         PROVIDERS.resource_api.create_project(level2['id'], level2)
 2731         PROVIDERS.resource_api.create_project(level3['id'], level3)
 2732         PROVIDERS.resource_api.create_project(level4['id'], level4)
 2733 
 2734         # Grant non-inherited role to root (as a spoiler) and to
 2735         # the level 1 (leaf) project
 2736         non_inher_entity_root = self.build_role_assignment_entity(
 2737             project_id=root_id, user_id=self.user['id'],
 2738             role_id=non_inherited_role_id)
 2739         self.put(non_inher_entity_root['links']['assignment'])
 2740         non_inher_entity_leaf = self.build_role_assignment_entity(
 2741             project_id=leaf_id, user_id=self.user['id'],
 2742             role_id=non_inherited_role_id)
 2743         self.put(non_inher_entity_leaf['links']['assignment'])
 2744 
 2745         # Grant inherited role to level 2
 2746         inher_entity = self.build_role_assignment_entity(
 2747             project_id=level2['id'], user_id=self.user['id'],
 2748             role_id=inherited_role_id, inherited_to_projects=True)
 2749         self.put(inher_entity['links']['assignment'])
 2750 
 2751         # Get effective role assignments
 2752         collection_url = (
 2753             '/role_assignments?scope.project.id=%(project)s'
 2754             '&include_subtree=True&effective' % {
 2755                 'project': leaf_id})
 2756         r = self.get(collection_url)
 2757         self.assertValidRoleAssignmentListResponse(
 2758             r, resource_url=collection_url)
 2759 
 2760         # There should be three assignments returned in total
 2761         self.assertThat(r.result['role_assignments'], matchers.HasLength(3))
 2762 
 2763         # Assert that the user does not non-inherited role on root project
 2764         self.assertRoleAssignmentNotInListResponse(r, non_inher_entity_root)
 2765 
 2766         # Assert that the user does have non-inherited role on leaf project
 2767         self.assertRoleAssignmentInListResponse(r, non_inher_entity_leaf)
 2768 
 2769         # Assert that the user has inherited role on levels 3 and 4
 2770         inher_entity['scope']['project']['id'] = level3['id']
 2771         self.assertRoleAssignmentInListResponse(r, inher_entity)
 2772         inher_entity['scope']['project']['id'] = level4['id']
 2773         self.assertRoleAssignmentInListResponse(r, inher_entity)
 2774 
 2775     def test_get_inherited_role_assignments_for_project_hierarchy(self):
 2776         """Call ``GET /role_assignments?scope.OS-INHERIT:inherited_to``.
 2777 
 2778         Test Plan:
 2779 
 2780         - Create 2 roles
 2781         - Create a hierarchy of projects with one root and one leaf project
 2782         - Issue the URL to add a non-inherited user role to the root project
 2783         - Issue the URL to add an inherited user role to the root project
 2784         - Issue the URL to filter inherited to projects role assignments - this
 2785           should return 1 role (inherited) on the root project.
 2786 
 2787         """
 2788         # Create default scenario
 2789         root_id, leaf_id, non_inherited_role_id, inherited_role_id = (
 2790             self._setup_hierarchical_projects_scenario())
 2791 
 2792         # Grant non-inherited role
 2793         non_inher_up_entity = self.build_role_assignment_entity(
 2794             project_id=root_id, user_id=self.user['id'],
 2795             role_id=non_inherited_role_id)
 2796         self.put(non_inher_up_entity['links']['assignment'])
 2797 
 2798         # Grant inherited role
 2799         inher_up_entity = self.build_role_assignment_entity(
 2800             project_id=root_id, user_id=self.user['id'],
 2801             role_id=inherited_role_id, inherited_to_projects=True)
 2802         self.put(inher_up_entity['links']['assignment'])
 2803 
 2804         # Get inherited role assignments
 2805         collection_url = ('/role_assignments'
 2806                           '?scope.OS-INHERIT:inherited_to=projects')
 2807         r = self.get(collection_url)
 2808         self.assertValidRoleAssignmentListResponse(r,
 2809                                                    resource_url=collection_url)
 2810 
 2811         # Assert that the user does not have non-inherited role on root project
 2812         self.assertRoleAssignmentNotInListResponse(r, non_inher_up_entity)
 2813 
 2814         # Assert that the user has inherited role on root project
 2815         self.assertRoleAssignmentInListResponse(r, inher_up_entity)
 2816 
 2817         # Assert that the user does not have non-inherited role on leaf project
 2818         non_inher_up_entity = self.build_role_assignment_entity(
 2819             project_id=leaf_id, user_id=self.user['id'],
 2820             role_id=non_inherited_role_id)
 2821         self.assertRoleAssignmentNotInListResponse(r, non_inher_up_entity)
 2822 
 2823         # Assert that the user does not have inherited role on leaf project
 2824         inher_up_entity['scope']['project']['id'] = leaf_id
 2825         self.assertRoleAssignmentNotInListResponse(r, inher_up_entity)
 2826 
 2827 
 2828 class ImpliedRolesTests(test_v3.RestfulTestCase, test_v3.AssignmentTestMixin,
 2829                         unit.TestCase):
 2830     def _create_role(self):
 2831         """Call ``POST /roles``."""
 2832         ref = unit.new_role_ref()
 2833         r = self.post('/roles', body={'role': ref})
 2834         return self.assertValidRoleResponse(r, ref)
 2835 
 2836     def test_list_implied_roles_none(self):
 2837         self.prior = self._create_role()
 2838         url = '/roles/%s/implies' % (self.prior['id'])
 2839         response = self.get(url).json["role_inference"]
 2840         self.head(url, expected_status=http.client.OK)
 2841         self.assertEqual(self.prior['id'], response['prior_role']['id'])
 2842         self.assertEqual(0, len(response['implies']))
 2843 
 2844     def _create_implied_role(self, prior, implied):
 2845         self.put('/roles/%s/implies/%s' % (prior['id'], implied['id']),
 2846                  expected_status=http.client.CREATED)
 2847 
 2848     def _delete_implied_role(self, prior, implied):
 2849         self.delete('/roles/%s/implies/%s' % (prior['id'], implied['id']))
 2850 
 2851     def _setup_prior_two_implied(self):
 2852         self.prior = self._create_role()
 2853         self.implied1 = self._create_role()
 2854         self._create_implied_role(self.prior, self.implied1)
 2855         self.implied2 = self._create_role()
 2856         self._create_implied_role(self.prior, self.implied2)
 2857 
 2858     def _assert_expected_implied_role_response(
 2859             self, expected_prior_id, expected_implied_ids):
 2860         r = self.get('/roles/%s/implies' % expected_prior_id)
 2861         response = r.json
 2862         role_inference = response['role_inference']
 2863         self.assertEqual(expected_prior_id, role_inference['prior_role']['id'])
 2864         prior_link = '/v3/roles/' + expected_prior_id + '/implies'
 2865         self.assertThat(response['links']['self'],
 2866                         matchers.EndsWith(prior_link))
 2867 
 2868         actual_implied_ids = [implied['id']
 2869                               for implied in role_inference['implies']]
 2870 
 2871         self.assertItemsEqual(expected_implied_ids, actual_implied_ids)
 2872 
 2873         self.assertIsNotNone(role_inference['prior_role']['links']['self'])
 2874         for implied in role_inference['implies']:
 2875             self.assertIsNotNone(implied['links']['self'])
 2876 
 2877     def _assert_expected_role_inference_rule_response(
 2878             self, expected_prior_id, expected_implied_id):
 2879         url = '/roles/%s/implies/%s' % (expected_prior_id, expected_implied_id)
 2880         response = self.get(url).json
 2881         self.assertThat(response['links']['self'],
 2882                         matchers.EndsWith('/v3%s' % url))
 2883         role_inference = response['role_inference']
 2884         prior_role = role_inference['prior_role']
 2885         self.assertEqual(expected_prior_id, prior_role['id'])
 2886         self.assertIsNotNone(prior_role['name'])
 2887         self.assertThat(prior_role['links']['self'],
 2888                         matchers.EndsWith('/v3/roles/%s' % expected_prior_id))
 2889         implied_role = role_inference['implies']
 2890         self.assertEqual(expected_implied_id, implied_role['id'])
 2891         self.assertIsNotNone(implied_role['name'])
 2892         self.assertThat(implied_role['links']['self'], matchers.EndsWith(
 2893             '/v3/roles/%s' % expected_implied_id))
 2894 
 2895     def _assert_two_roles_implied(self):
 2896         self._assert_expected_implied_role_response(
 2897             self.prior['id'], [self.implied1['id'], self.implied2['id']])
 2898         self._assert_expected_role_inference_rule_response(
 2899             self.prior['id'], self.implied1['id'])
 2900         self._assert_expected_role_inference_rule_response(
 2901             self.prior['id'], self.implied2['id'])
 2902 
 2903     def _assert_one_role_implied(self):
 2904         self._assert_expected_implied_role_response(
 2905             self.prior['id'], [self.implied1['id']])
 2906 
 2907         self.get('/roles/%s/implies/%s' %
 2908                  (self.prior['id'], self.implied2['id']),
 2909                  expected_status=http.client.NOT_FOUND)
 2910 
 2911     def _assert_two_rules_defined(self):
 2912         r = self.get('/role_inferences/')
 2913 
 2914         rules = r.result['role_inferences']
 2915 
 2916         self.assertEqual(self.prior['id'], rules[0]['prior_role']['id'])
 2917         self.assertEqual(2, len(rules[0]['implies']))
 2918         implied_ids = [implied['id'] for implied in rules[0]['implies']]
 2919         implied_names = [implied['name'] for implied in rules[0]['implies']]
 2920 
 2921         self.assertIn(self.implied1['id'], implied_ids)
 2922         self.assertIn(self.implied2['id'], implied_ids)
 2923         self.assertIn(self.implied1['name'], implied_names)
 2924         self.assertIn(self.implied2['name'], implied_names)
 2925 
 2926     def _assert_one_rule_defined(self):
 2927         r = self.get('/role_inferences/')
 2928         rules = r.result['role_inferences']
 2929         self.assertEqual(self.prior['id'], rules[0]['prior_role']['id'])
 2930         self.assertEqual(self.implied1['id'], rules[0]['implies'][0]['id'])
 2931         self.assertEqual(self.implied1['name'], rules[0]['implies'][0]['name'])
 2932         self.assertEqual(1, len(rules[0]['implies']))
 2933 
 2934     def test_list_all_rules(self):
 2935         self._setup_prior_two_implied()
 2936         self._assert_two_rules_defined()
 2937 
 2938         self._delete_implied_role(self.prior, self.implied2)
 2939         self._assert_one_rule_defined()
 2940 
 2941     def test_CRD_implied_roles(self):
 2942 
 2943         self._setup_prior_two_implied()
 2944         self._assert_two_roles_implied()
 2945 
 2946         self._delete_implied_role(self.prior, self.implied2)
 2947         self._assert_one_role_implied()
 2948 
 2949     def _create_three_roles(self):
 2950         self.role_list = []
 2951         for _ in range(3):
 2952             role = unit.new_role_ref()
 2953             PROVIDERS.role_api.create_role(role['id'], role)
 2954             self.role_list.append(role)
 2955 
 2956     def _create_test_domain_user_project(self):
 2957         domain = unit.new_domain_ref()
 2958         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 2959         user = unit.create_user(PROVIDERS.identity_api, domain_id=domain['id'])
 2960         project = unit.new_project_ref(domain_id=domain['id'])
 2961         PROVIDERS.resource_api.create_project(project['id'], project)
 2962         return domain, user, project
 2963 
 2964     def _assign_top_role_to_user_on_project(self, user, project):
 2965         PROVIDERS.assignment_api.add_role_to_user_and_project(
 2966             user['id'], project['id'], self.role_list[0]['id'])
 2967 
 2968     def _build_effective_role_assignments_url(self, user):
 2969         return '/role_assignments?effective&user.id=%(user_id)s' % {
 2970             'user_id': user['id']}
 2971 
 2972     def _assert_all_roles_in_assignment(self, response, user):
 2973         # Now use the list role assignments api to check that all three roles
 2974         # appear in the collection
 2975         self.assertValidRoleAssignmentListResponse(
 2976             response,
 2977             expected_length=len(self.role_list),
 2978             resource_url=self._build_effective_role_assignments_url(user))
 2979 
 2980     def _assert_initial_assignment_in_effective(self, response, user, project):
 2981         # The initial assignment should be there (the link url will be
 2982         # generated and checked automatically since it matches the assignment)
 2983         entity = self.build_role_assignment_entity(
 2984             project_id=project['id'],
 2985             user_id=user['id'], role_id=self.role_list[0]['id'])
 2986         self.assertRoleAssignmentInListResponse(response, entity)
 2987 
 2988     def _assert_effective_role_for_implied_has_prior_in_links(
 2989             self, response, user, project, prior_index, implied_index):
 2990         # An effective role for an implied role will have the prior role
 2991         # assignment in the links
 2992         prior_link = '/prior_roles/%(prior)s/implies/%(implied)s' % {
 2993             'prior': self.role_list[prior_index]['id'],
 2994             'implied': self.role_list[implied_index]['id']}
 2995         link = self.build_role_assignment_link(
 2996             project_id=project['id'], user_id=user['id'],
 2997             role_id=self.role_list[prior_index]['id'])
 2998         entity = self.build_role_assignment_entity(
 2999             link=link, project_id=project['id'],
 3000             user_id=user['id'], role_id=self.role_list[implied_index]['id'],
 3001             prior_link=prior_link)
 3002         self.assertRoleAssignmentInListResponse(response, entity)
 3003 
 3004     def test_list_role_assignments_with_implied_roles(self):
 3005         """Call ``GET /role_assignments`` with implied role grant.
 3006 
 3007         Test Plan:
 3008 
 3009         - Create a domain with a user and a project
 3010         - Create 3 roles
 3011         - Role 0 implies role 1 and role 1 implies role 2
 3012         - Assign the top role to the project
 3013         - Issue the URL to check effective roles on project - this
 3014           should return all 3 roles.
 3015         - Check the links of the 3 roles indicate the prior role where
 3016           appropriate
 3017 
 3018         """
 3019         (domain, user, project) = self._create_test_domain_user_project()
 3020         self._create_three_roles()
 3021         self._create_implied_role(self.role_list[0], self.role_list[1])
 3022         self._create_implied_role(self.role_list[1], self.role_list[2])
 3023         self._assign_top_role_to_user_on_project(user, project)
 3024 
 3025         response = self.get(self._build_effective_role_assignments_url(user))
 3026         r = response
 3027 
 3028         self._assert_all_roles_in_assignment(r, user)
 3029         self._assert_initial_assignment_in_effective(response, user, project)
 3030         self._assert_effective_role_for_implied_has_prior_in_links(
 3031             response, user, project, 0, 1)
 3032         self._assert_effective_role_for_implied_has_prior_in_links(
 3033             response, user, project, 1, 2)
 3034 
 3035     def _create_named_role(self, name):
 3036         role = unit.new_role_ref()
 3037         role['name'] = name
 3038         PROVIDERS.role_api.create_role(role['id'], role)
 3039         return role
 3040 
 3041     def test_root_role_as_implied_role_forbidden(self):
 3042         """Test root role is forbidden to be set as an implied role.
 3043 
 3044         Create 2 roles that are prohibited from being an implied role.
 3045         Create 1 additional role which should be accepted as an implied
 3046         role. Assure the prohibited role names cannot be set as an implied
 3047         role. Assure the accepted role name which is not a member of the
 3048         prohibited implied role list can be successfully set an implied
 3049         role.
 3050         """
 3051         prohibited_name1 = 'root1'
 3052         prohibited_name2 = 'root2'
 3053         accepted_name1 = 'implied1'
 3054 
 3055         prohibited_names = [prohibited_name1, prohibited_name2]
 3056         self.config_fixture.config(group='assignment',
 3057                                    prohibited_implied_role=prohibited_names)
 3058 
 3059         prior_role = self._create_role()
 3060 
 3061         prohibited_role1 = self._create_named_role(prohibited_name1)
 3062         url = '/roles/{prior_role_id}/implies/{implied_role_id}'.format(
 3063             prior_role_id=prior_role['id'],
 3064             implied_role_id=prohibited_role1['id'])
 3065         self.put(url, expected_status=http.client.FORBIDDEN)
 3066 
 3067         prohibited_role2 = self._create_named_role(prohibited_name2)
 3068         url = '/roles/{prior_role_id}/implies/{implied_role_id}'.format(
 3069             prior_role_id=prior_role['id'],
 3070             implied_role_id=prohibited_role2['id'])
 3071         self.put(url, expected_status=http.client.FORBIDDEN)
 3072 
 3073         accepted_role1 = self._create_named_role(accepted_name1)
 3074         url = '/roles/{prior_role_id}/implies/{implied_role_id}'.format(
 3075             prior_role_id=prior_role['id'],
 3076             implied_role_id=accepted_role1['id'])
 3077         self.put(url, expected_status=http.client.CREATED)
 3078 
 3079     def test_trusts_from_implied_role(self):
 3080         self._create_three_roles()
 3081         self._create_implied_role(self.role_list[0], self.role_list[1])
 3082         self._create_implied_role(self.role_list[1], self.role_list[2])
 3083         self._assign_top_role_to_user_on_project(self.user, self.project)
 3084 
 3085         # Create a trustee and assign the prior role to her
 3086         trustee = unit.create_user(
 3087             PROVIDERS.identity_api, domain_id=self.domain_id
 3088         )
 3089         ref = unit.new_trust_ref(
 3090             trustor_user_id=self.user['id'],
 3091             trustee_user_id=trustee['id'],
 3092             project_id=self.project['id'],
 3093             role_ids=[self.role_list[0]['id']])
 3094         r = self.post('/OS-TRUST/trusts', body={'trust': ref})
 3095         trust = r.result['trust']
 3096 
 3097         # Only the role that was specified is in the trust, NOT implied roles
 3098         self.assertEqual(self.role_list[0]['id'], trust['roles'][0]['id'])
 3099         self.assertThat(trust['roles'], matchers.HasLength(1))
 3100 
 3101         # Authenticate as the trustee
 3102         auth_data = self.build_authentication_request(
 3103             user_id=trustee['id'],
 3104             password=trustee['password'],
 3105             trust_id=trust['id'])
 3106         r = self.v3_create_token(auth_data)
 3107         token = r.result['token']
 3108         self.assertThat(token['roles'],
 3109                         matchers.HasLength(len(self.role_list)))
 3110         for role in token['roles']:
 3111             self.assertIn(role, self.role_list)
 3112         for role in self.role_list:
 3113             self.assertIn(role, token['roles'])
 3114 
 3115     def test_trusts_from_domain_specific_implied_role(self):
 3116         self._create_three_roles()
 3117         # Overwrite the first role with a domain specific role
 3118         role = unit.new_role_ref(domain_id=self.domain_id)
 3119         self.role_list[0] = PROVIDERS.role_api.create_role(role['id'], role)
 3120         self._create_implied_role(self.role_list[0], self.role_list[1])
 3121         self._create_implied_role(self.role_list[1], self.role_list[2])
 3122         self._assign_top_role_to_user_on_project(self.user, self.project)
 3123 
 3124         # Create a trustee and assign the prior role to her
 3125         trustee = unit.create_user(
 3126             PROVIDERS.identity_api, domain_id=self.domain_id
 3127         )
 3128         ref = unit.new_trust_ref(
 3129             trustor_user_id=self.user['id'],
 3130             trustee_user_id=trustee['id'],
 3131             project_id=self.project['id'],
 3132             role_ids=[self.role_list[0]['id']])
 3133         r = self.post('/OS-TRUST/trusts', body={'trust': ref})
 3134         trust = r.result['trust']
 3135 
 3136         # Only the role that was specified is in the trust, NOT implied roles
 3137         self.assertEqual(self.role_list[0]['id'], trust['roles'][0]['id'])
 3138         self.assertThat(trust['roles'], matchers.HasLength(1))
 3139 
 3140         # Authenticate as the trustee
 3141         auth_data = self.build_authentication_request(
 3142             user_id=trustee['id'],
 3143             password=trustee['password'],
 3144             trust_id=trust['id'])
 3145         r = self.v3_create_token(auth_data)
 3146         token = r.result['token']
 3147 
 3148         # The token should have the roles implies by the domain specific role,
 3149         # but not the domain specific role itself.
 3150         self.assertThat(token['roles'],
 3151                         matchers.HasLength(len(self.role_list) - 1))
 3152         for role in token['roles']:
 3153             self.assertIn(role, self.role_list)
 3154         for role in [self.role_list[1], self.role_list[2]]:
 3155             self.assertIn(role, token['roles'])
 3156         self.assertNotIn(self.role_list[0], token['roles'])
 3157 
 3158     def test_global_role_cannot_imply_domain_specific_role(self):
 3159         domain = unit.new_domain_ref()
 3160         PROVIDERS.resource_api.create_domain(domain['id'], domain)
 3161 
 3162         domain_role_ref = unit.new_role_ref(domain_id=domain['id'])
 3163         domain_role = PROVIDERS.role_api.create_role(
 3164             domain_role_ref['id'], domain_role_ref
 3165         )
 3166         global_role_ref = unit.new_role_ref()
 3167         global_role = PROVIDERS.role_api.create_role(
 3168             global_role_ref['id'], global_role_ref
 3169         )
 3170 
 3171         self.put('/roles/%s/implies/%s' % (global_role['id'],
 3172                                            domain_role['id']),
 3173                  expected_status=http.client.FORBIDDEN)
 3174 
 3175 
 3176 class DomainSpecificRoleTests(test_v3.RestfulTestCase, unit.TestCase):
 3177     def setUp(self):
 3178         def create_role(domain_id=None):
 3179             """Call ``POST /roles``."""
 3180             ref = unit.new_role_ref(domain_id=domain_id)
 3181             r = self.post(
 3182                 '/roles',
 3183                 body={'role': ref})
 3184             return self.assertValidRoleResponse(r, ref)
 3185 
 3186         super(DomainSpecificRoleTests, self).setUp()
 3187         self.domainA = unit.new_domain_ref()
 3188         PROVIDERS.resource_api.create_domain(self.domainA['id'], self.domainA)
 3189         self.domainB = unit.new_domain_ref()
 3190         PROVIDERS.resource_api.create_domain(self.domainB['id'], self.domainB)
 3191 
 3192         self.global_role1 = create_role()
 3193         self.global_role2 = create_role()
 3194         # Since there maybe other global roles already created, let's count
 3195         # them, so we can ensure we can check subsequent list responses
 3196         # are correct
 3197         r = self.get('/roles')
 3198         self.existing_global_roles = len(r.result['roles'])
 3199 
 3200         # And now create some domain specific roles
 3201         self.domainA_role1 = create_role(domain_id=self.domainA['id'])
 3202         self.domainA_role2 = create_role(domain_id=self.domainA['id'])
 3203         self.domainB_role = create_role(domain_id=self.domainB['id'])
 3204 
 3205     def test_get_and_list_domain_specific_roles(self):
 3206         # Check we can get a domain specific role
 3207         r = self.get('/roles/%s' % self.domainA_role1['id'])
 3208         self.assertValidRoleResponse(r, self.domainA_role1)
 3209 
 3210         # If we list without specifying a domain, we should only get global
 3211         # roles back.
 3212         r = self.get('/roles')
 3213         self.assertValidRoleListResponse(
 3214             r, expected_length=self.existing_global_roles)
 3215         self.assertRoleInListResponse(r, self.global_role1)
 3216         self.assertRoleInListResponse(r, self.global_role2)
 3217         self.assertRoleNotInListResponse(r, self.domainA_role1)
 3218         self.assertRoleNotInListResponse(r, self.domainA_role2)
 3219         self.assertRoleNotInListResponse(r, self.domainB_role)
 3220 
 3221         # Now list those in domainA, making sure that's all we get back
 3222         r = self.get('/roles?domain_id=%s' % self.domainA['id'])
 3223         self.assertValidRoleListResponse(r, expected_length=2)
 3224         self.assertRoleInListResponse(r, self.domainA_role1)
 3225         self.assertRoleInListResponse(r, self.domainA_role2)
 3226 
 3227     def test_update_domain_specific_roles(self):
 3228         self.domainA_role1['name'] = uuid.uuid4().hex
 3229         self.patch('/roles/%(role_id)s' % {
 3230             'role_id': self.domainA_role1['id']},
 3231             body={'role': self.domainA_role1})
 3232         r = self.get('/roles/%s' % self.domainA_role1['id'])
 3233         self.assertValidRoleResponse(r, self.domainA_role1)
 3234 
 3235     def test_delete_domain_specific_roles(self):
 3236         # Check delete only removes that one domain role
 3237         self.delete('/roles/%(role_id)s' % {
 3238             'role_id': self.domainA_role1['id']})
 3239 
 3240         self.get('/roles/%s' % self.domainA_role1['id'],
 3241                  expected_status=http.client.NOT_FOUND)
 3242         # Now re-list those in domainA, making sure there's only one left
 3243         r = self.get('/roles?domain_id=%s' % self.domainA['id'])
 3244         self.assertValidRoleListResponse(r, expected_length=1)
 3245         self.assertRoleInListResponse(r, self.domainA_role2)
 3246 
 3247     def test_same_domain_assignment(self):
 3248         user = unit.create_user(PROVIDERS.identity_api,
 3249                                 domain_id=self.domainA['id'])
 3250 
 3251         projectA = unit.new_project_ref(domain_id=self.domainA['id'])
 3252         PROVIDERS.resource_api.create_project(projectA['id'], projectA)
 3253 
 3254         PROVIDERS.assignment_api.create_grant(
 3255             self.domainA_role1['id'], user_id=user['id'],
 3256             project_id=projectA['id']
 3257         )
 3258 
 3259     def test_cross_domain_assignment_valid(self):
 3260         user = unit.create_user(PROVIDERS.identity_api,
 3261                                 domain_id=self.domainB['id'])
 3262 
 3263         projectA = unit.new_project_ref(domain_id=self.domainA['id'])
 3264         PROVIDERS.resource_api.create_project(projectA['id'], projectA)
 3265 
 3266         # Positive: a role on domainA can be assigned to a user from domainB
 3267         # but only for use on a project from domainA
 3268         PROVIDERS.assignment_api.create_grant(
 3269             self.domainA_role1['id'], user_id=user['id'],
 3270             project_id=projectA['id']
 3271         )
 3272 
 3273     def test_cross_domain_assignment_invalid(self):
 3274         user = unit.create_user(PROVIDERS.identity_api,
 3275                                 domain_id=self.domainB['id'])
 3276 
 3277         projectB = unit.new_project_ref(domain_id=self.domainB['id'])
 3278         PROVIDERS.resource_api.create_project(projectB['id'], projectB)
 3279 
 3280         # Negative: a role on domainA can be assigned to a user from domainB
 3281         # only for a project from domainA
 3282         self.assertRaises(exception.DomainSpecificRoleMismatch,
 3283                           PROVIDERS.assignment_api.create_grant,
 3284                           self.domainA_role1['id'],
 3285                           user_id=user['id'],
 3286                           project_id=projectB['id'])
 3287 
 3288     def test_cross_domain_implied_roles_authentication(self):
 3289         # Create a user in domainB
 3290         user = unit.create_user(PROVIDERS.identity_api,
 3291                                 domain_id=self.domainB['id'])
 3292 
 3293         # Create project in domainA
 3294         projectA = unit.new_project_ref(domain_id=self.domainA['id'])
 3295         PROVIDERS.resource_api.create_project(projectA['id'], projectA)
 3296 
 3297         # Now we create an implied rule from a role in domainA to a
 3298         # role in domainB
 3299         self.put('/roles/%s/implies/%s' %
 3300                  (self.domainA_role1['id'], self.domainB_role['id']),
 3301                  expected_status=http.client.CREATED)
 3302 
 3303         # A role in domainA can be assigned to a user from domainB
 3304         # only for a project from domainA
 3305         PROVIDERS.assignment_api.create_grant(
 3306             self.domainA_role1['id'], user_id=user['id'],
 3307             project_id=projectA['id']
 3308         )
 3309 
 3310         # The role assignments should return an empty list since domain roles
 3311         # can only be used to imply another roles
 3312         assignments = PROVIDERS.assignment_api.list_role_assignments(
 3313             user_id=user['id'], effective=True)
 3314         self.assertEqual([], assignments)
 3315 
 3316         # This also means we can't authenticate using the existing assignment
 3317         auth_body = self.build_authentication_request(
 3318             user_id=user['id'],
 3319             password=user['password'],
 3320             project_id=projectA['id'])
 3321         self.post('/auth/tokens', body=auth_body,
 3322                   expected_status=http.client.UNAUTHORIZED)
 3323 
 3324 
 3325 class ListUserProjectsTestCase(test_v3.RestfulTestCase):
 3326     """Test for /users/<user>/projects."""
 3327 
 3328     def load_sample_data(self):
 3329         # do not load base class's data, keep it focused on the tests
 3330 
 3331         self.auths = []
 3332         self.domains = []
 3333         self.projects = []
 3334         self.roles = []
 3335         self.users = []
 3336 
 3337         root_domain = unit.new_domain_ref(
 3338             id=resource_base.NULL_DOMAIN_ID,
 3339             name=resource_base.NULL_DOMAIN_ID
 3340         )
 3341         self.resource_api.create_domain(resource_base.NULL_DOMAIN_ID,
 3342                                         root_domain)
 3343 
 3344         # Create 3 sets of domain, roles, projects, and users to demonstrate
 3345         # the right user's data is loaded and only projects they can access
 3346         # are returned.
 3347 
 3348         for _ in range(3):
 3349             domain = unit.new_domain_ref()
 3350             PROVIDERS.resource_api.create_domain(domain['id'], domain)
 3351 
 3352             user = unit.create_user(
 3353                 PROVIDERS.identity_api, domain_id=domain['id']
 3354             )
 3355 
 3356             role = unit.new_role_ref()
 3357             PROVIDERS.role_api.create_role(role['id'], role)
 3358 
 3359             PROVIDERS.assignment_api.create_grant(
 3360                 role['id'], user_id=user['id'], domain_id=domain['id']
 3361             )
 3362 
 3363             project = unit.new_project_ref(domain_id=domain['id'])
 3364             PROVIDERS.resource_api.create_project(project['id'], project)
 3365 
 3366             PROVIDERS.assignment_api.create_grant(
 3367                 role['id'], user_id=user['id'], project_id=project['id']
 3368             )
 3369 
 3370             auth = self.build_authentication_request(
 3371                 user_id=user['id'],
 3372                 password=user['password'],
 3373                 domain_id=domain['id'])
 3374 
 3375             self.auths.append(auth)
 3376             self.domains.append(domain)
 3377             self.projects.append(project)
 3378             self.roles.append(role)
 3379             self.users.append(user)
 3380 
 3381     def test_list_head_all(self):
 3382         for i in range(len(self.users)):
 3383             user = self.users[i]
 3384             auth = self.auths[i]
 3385 
 3386             url = '/users/%s/projects' % user['id']
 3387             result = self.get(url, auth=auth)
 3388             projects_result = result.json['projects']
 3389             self.assertEqual(1, len(projects_result))
 3390             self.assertEqual(self.projects[i]['id'], projects_result[0]['id'])
 3391             self.head(url, auth=auth, expected_status=http.client.OK)
 3392 
 3393     def test_list_enabled(self):
 3394         for i in range(len(self.users)):
 3395             user = self.users[i]
 3396             auth = self.auths[i]
 3397 
 3398             # There are no disabled projects
 3399             url = '/users/%s/projects?enabled=True' % user['id']
 3400             result = self.get(url, auth=auth)
 3401             projects_result = result.json['projects']
 3402             self.assertEqual(1, len(projects_result))
 3403             self.assertEqual(self.projects[i]['id'], projects_result[0]['id'])
 3404 
 3405     def test_list_disabled(self):
 3406         for i in range(len(self.users)):
 3407             user = self.users[i]
 3408             auth = self.auths[i]
 3409             project = self.projects[i]
 3410 
 3411             # There are no disabled projects
 3412             url = '/users/%s/projects?enabled=False' % user['id']
 3413             result = self.get(url, auth=auth)
 3414             self.assertEqual(0, len(result.json['projects']))
 3415 
 3416             # disable this one and check again
 3417             project['enabled'] = False
 3418             PROVIDERS.resource_api.update_project(project['id'], project)
 3419             result = self.get(url, auth=auth)
 3420             projects_result = result.json['projects']
 3421             self.assertEqual(1, len(projects_result))
 3422             self.assertEqual(self.projects[i]['id'], projects_result[0]['id'])
 3423 
 3424     def test_list_by_domain_id(self):
 3425         for i in range(len(self.users)):
 3426             user = self.users[i]
 3427             domain = self.domains[i]
 3428             auth = self.auths[i]
 3429 
 3430             # Try looking for projects with a non-existent domain_id
 3431             url = '/users/%s/projects?domain_id=%s' % (user['id'],
 3432                                                        uuid.uuid4().hex)
 3433             result = self.get(url, auth=auth)
 3434             self.assertEqual(0, len(result.json['projects']))
 3435 
 3436             # Now try a valid one
 3437             url = '/users/%s/projects?domain_id=%s' % (user['id'],
 3438                                                        domain['id'])
 3439             result = self.get(url, auth=auth)
 3440             projects_result = result.json['projects']
 3441             self.assertEqual(1, len(projects_result))
 3442             self.assertEqual(self.projects[i]['id'], projects_result[0]['id'])
 3443 
 3444 
 3445 # FIXME(lbragstad): These tests contain system-level API calls, which means
 3446 # they will log a warning message if they are called with a project-scoped
 3447 # token, regardless of the role assignment on the project.  We need to fix
 3448 # them by using a proper system-scoped admin token to make the call instead
 3449 # of a project scoped token.
 3450 class UserSystemRoleAssignmentTestCase(test_v3.RestfulTestCase,
 3451                                        SystemRoleAssignmentMixin):
 3452 
 3453     def test_assign_system_role_to_user(self):
 3454         system_role_id = self._create_new_role()
 3455 
 3456         # assign the user a role on the system
 3457         member_url = (
 3458             '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3459                 'user_id': self.user['id'],
 3460                 'role_id': system_role_id
 3461             }
 3462         )
 3463         self.put(member_url)
 3464 
 3465         # validate the role assignment
 3466         self.head(member_url)
 3467 
 3468         # list system roles
 3469         collection_url = (
 3470             '/system/users/%(user_id)s/roles' % {'user_id': self.user['id']}
 3471         )
 3472         roles = self.get(collection_url).json_body['roles']
 3473         self.assertEqual(len(roles), 1)
 3474         self.assertEqual(roles[0]['id'], system_role_id)
 3475         self.head(collection_url, expected_status=http.client.OK)
 3476 
 3477         response = self.get(
 3478             '/role_assignments?scope.system=all&user.id=%(user_id)s' % {
 3479                 'user_id': self.user['id']
 3480             }
 3481         )
 3482         self.assertValidRoleAssignmentListResponse(response)
 3483 
 3484     def test_list_role_assignments_for_user_returns_all_assignments(self):
 3485         system_role_id = self._create_new_role()
 3486 
 3487         # assign the user a role on the system
 3488         member_url = '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3489             'user_id': self.user['id'],
 3490             'role_id': system_role_id
 3491         }
 3492         self.put(member_url)
 3493 
 3494         # the response should contain one role assignment for the system role
 3495         # and one for a role that was setup during setUp().
 3496         response = self.get(
 3497             '/role_assignments?user.id=%(user_id)s' % {
 3498                 'user_id': self.user['id']
 3499             }
 3500         )
 3501         self.assertValidRoleAssignmentListResponse(response, expected_length=2)
 3502 
 3503     def test_list_system_roles_for_user_returns_none_without_assignment(self):
 3504         # list system roles for user
 3505         collection_url = '/system/users/%(user_id)s/roles' % {
 3506             'user_id': self.user['id']
 3507         }
 3508         response = self.get(collection_url)
 3509 
 3510         # assert that the user doesn't have any system role assignments, which
 3511         # is denoted by an empty list
 3512         self.assertEqual(response.json_body['roles'], [])
 3513 
 3514         response = self.get(
 3515             '/role_assignments?scope.system=all&user.id=%(user_id)s' % {
 3516                 'user_id': self.user['id']
 3517             }
 3518         )
 3519         self.assertEqual(len(response.json_body['role_assignments']), 0)
 3520         self.assertValidRoleAssignmentListResponse(response)
 3521 
 3522     def test_list_system_roles_for_user_does_not_return_project_roles(self):
 3523         system_role_id = self._create_new_role()
 3524 
 3525         # assign the user a role on the system
 3526         member_url = '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3527             'user_id': self.user['id'],
 3528             'role_id': system_role_id
 3529         }
 3530         self.put(member_url)
 3531 
 3532         # list project role assignments and save the role id of that
 3533         # assignment, this assignment was created during setUp
 3534         response = self.get(
 3535             '/projects/%(project_id)s/users/%(user_id)s/roles' % {
 3536                 'project_id': self.project['id'],
 3537                 'user_id': self.user['id']
 3538             }
 3539         )
 3540         self.assertEqual(len(response.json_body['roles']), 1)
 3541         project_role_id = response.json_body['roles'][0]['id']
 3542 
 3543         # list system role assignments
 3544         collection_url = '/system/users/%(user_id)s/roles' % {
 3545             'user_id': self.user['id']
 3546         }
 3547         response = self.get(collection_url)
 3548 
 3549         # assert the project role assignment is not in the system role
 3550         # assignments
 3551         for role in response.json_body['roles']:
 3552             self.assertNotEqual(role['id'], project_role_id)
 3553 
 3554         # make sure the role_assignment API filters correctly based on system
 3555         # scope
 3556         response = self.get(
 3557             '/role_assignments?scope.system=all&user.id=%(user_id)s' % {
 3558                 'user_id': self.user['id']
 3559             }
 3560         )
 3561         self.assertEqual(len(response.json_body['role_assignments']), 1)
 3562         system_assignment = response.json_body['role_assignments'][0]
 3563         self.assertEqual(system_assignment['role']['id'], system_role_id)
 3564         self.assertTrue(system_assignment['scope']['system']['all'])
 3565 
 3566         # make sure the role_assignment API doesn't include the system role
 3567         # assignment when we filter based on project
 3568         path = (
 3569             '/role_assignments?scope.project.id=%(project_id)s&'
 3570             'user.id=%(user_id)s'
 3571         ) % {'project_id': self.project['id'],
 3572              'user_id': self.user['id']}
 3573         response = self.get(path)
 3574         self.assertEqual(len(response.json_body['role_assignments']), 1)
 3575         project_assignment = response.json_body['role_assignments'][0]
 3576         self.assertEqual(project_assignment['role']['id'], project_role_id)
 3577 
 3578     def test_list_system_roles_for_user_does_not_return_domain_roles(self):
 3579         system_role_id = self._create_new_role()
 3580         domain_role_id = self._create_new_role()
 3581 
 3582         # assign a role to the user on a domain
 3583         domain_member_url = (
 3584             '/domains/%(domain_id)s/users/%(user_id)s/roles/%(role_id)s' % {
 3585                 'domain_id': self.user['domain_id'],
 3586                 'user_id': self.user['id'],
 3587                 'role_id': domain_role_id
 3588             }
 3589         )
 3590         self.put(domain_member_url)
 3591 
 3592         # assign the user a role on the system
 3593         member_url = '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3594             'user_id': self.user['id'],
 3595             'role_id': system_role_id
 3596         }
 3597         self.put(member_url)
 3598 
 3599         # list domain role assignments
 3600         response = self.get(
 3601             '/domains/%(domain_id)s/users/%(user_id)s/roles' % {
 3602                 'domain_id': self.user['domain_id'],
 3603                 'user_id': self.user['id']
 3604             }
 3605         )
 3606         self.assertEqual(len(response.json_body['roles']), 1)
 3607 
 3608         # list system role assignments
 3609         collection_url = '/system/users/%(user_id)s/roles' % {
 3610             'user_id': self.user['id']
 3611         }
 3612         response = self.get(collection_url)
 3613 
 3614         # assert the domain role assignment is not in the system role
 3615         # assignments
 3616         for role in response.json_body['roles']:
 3617             self.assertNotEqual(role['id'], domain_role_id)
 3618 
 3619         # make sure the role_assignment API filters correctly based on system
 3620         # scope
 3621         response = self.get(
 3622             '/role_assignments?scope.system=all&user.id=%(user_id)s' % {
 3623                 'user_id': self.user['id']
 3624             }
 3625         )
 3626         self.assertEqual(len(response.json_body['role_assignments']), 1)
 3627         system_assignment = response.json_body['role_assignments'][0]
 3628         self.assertEqual(system_assignment['role']['id'], system_role_id)
 3629         self.assertTrue(system_assignment['scope']['system']['all'])
 3630 
 3631         # make sure the role_assignment API doesn't include the system role
 3632         # assignment when we filter based on domain
 3633         path = (
 3634             '/role_assignments?scope.domain.id=%(domain_id)s&'
 3635             'user.id=%(user_id)s'
 3636         ) % {'domain_id': self.user['domain_id'],
 3637              'user_id': self.user['id']}
 3638         response = self.get(path)
 3639         self.assertEqual(len(response.json_body['role_assignments']), 1)
 3640         domain_assignment = response.json_body['role_assignments'][0]
 3641         self.assertEqual(domain_assignment['role']['id'], domain_role_id)
 3642 
 3643     def test_check_user_has_system_role_when_assignment_exists(self):
 3644         system_role_id = self._create_new_role()
 3645 
 3646         # assign the user a role on the system
 3647         member_url = '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3648             'user_id': self.user['id'],
 3649             'role_id': system_role_id
 3650         }
 3651         self.put(member_url)
 3652 
 3653         # check the user has the system role assignment
 3654         self.head(member_url)
 3655 
 3656     def test_check_user_does_not_have_system_role_without_assignment(self):
 3657         system_role_id = self._create_new_role()
 3658 
 3659         # check the user does't have the system role assignment
 3660         member_url = '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3661             'user_id': self.user['id'],
 3662             'role_id': system_role_id
 3663         }
 3664         self.head(member_url, expected_status=http.client.NOT_FOUND)
 3665 
 3666         response = self.get(
 3667             '/role_assignments?scope.system=all&user.id=%(user_id)s' % {
 3668                 'user_id': self.user['id']
 3669             }
 3670         )
 3671         self.assertEqual(len(response.json_body['role_assignments']), 0)
 3672         self.assertValidRoleAssignmentListResponse(response)
 3673 
 3674     def test_unassign_system_role_from_user(self):
 3675         system_role_id = self._create_new_role()
 3676 
 3677         # assign the user a role on the system
 3678         member_url = '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3679             'user_id': self.user['id'],
 3680             'role_id': system_role_id
 3681         }
 3682         self.put(member_url)
 3683 
 3684         # ensure the user has the role assignment
 3685         self.head(member_url)
 3686 
 3687         response = self.get(
 3688             '/role_assignments?scope.system=all&user.id=%(user_id)s' % {
 3689                 'user_id': self.user['id']
 3690             }
 3691         )
 3692         self.assertEqual(len(response.json_body['role_assignments']), 1)
 3693         self.assertValidRoleAssignmentListResponse(response)
 3694 
 3695         # remove the system role assignment from the user
 3696         self.delete(member_url)
 3697 
 3698         # ensure the user doesn't have any system role assignments
 3699         collection_url = '/system/users/%(user_id)s/roles' % {
 3700             'user_id': self.user['id']
 3701         }
 3702         response = self.get(collection_url)
 3703         self.assertEqual(len(response.json_body['roles']), 0)
 3704         response = self.get(
 3705             '/role_assignments?scope.system=all&user.id=%(user_id)s' % {
 3706                 'user_id': self.user['id']
 3707             }
 3708         )
 3709         self.assertValidRoleAssignmentListResponse(response, expected_length=0)
 3710 
 3711     def test_query_for_system_scope_and_domain_scope_fails(self):
 3712         # When asking for assignments and providing query parameters, we
 3713         # shouldn't be able to ask for two different types of scope. This is
 3714         # also true for project + domain scope.
 3715         path = (
 3716             '/role_assignments?scope.system=all'
 3717             '&scope.domain.id=%(domain_id)s'
 3718         ) % {'domain_id': self.domain_id}
 3719         self.get(path, expected_status=http.client.BAD_REQUEST)
 3720 
 3721     def test_query_for_system_scope_and_project_scope_fails(self):
 3722         # When asking for assignments and providing query parameters, we
 3723         # shouldn't be able to ask for two different types of scope. This is
 3724         # also true for project + domain scope.
 3725         path = (
 3726             '/role_assignments?scope.system=all'
 3727             '&scope.project.id=%(project_id)s'
 3728         ) % {'project_id': self.project_id}
 3729         self.get(path, expected_status=http.client.BAD_REQUEST)
 3730 
 3731     def test_query_for_role_id_does_not_return_system_user_roles(self):
 3732         system_role_id = self._create_new_role()
 3733 
 3734         # assign the user a role on the system
 3735         member_url = '/system/users/%(user_id)s/roles/%(role_id)s' % {
 3736             'user_id': self.user['id'],
 3737             'role_id': system_role_id
 3738         }
 3739         self.put(member_url)
 3740 
 3741         # Make sure we only get one role assignment back since the system role
 3742         # assignment shouldn't be returned.
 3743         path = (
 3744             '/role_assignments?role.id=%(role_id)s&user.id=%(user_id)s'
 3745         ) % {'role_id': self.role_id, 'user_id': self.user['id']}
 3746         response = self.get(path)
 3747         self.assertValidRoleAssignmentListResponse(response, expected_length=1)
 3748 
 3749 
 3750 # FIXME(lbragstad): These tests contain system-level API calls, which means
 3751 # they will log a warning message if they are called with a project-scoped
 3752 # token, regardless of the role assignment on the project.  We need to fix
 3753 # them by using a proper system-scoped admin token to make the call instead
 3754 # of a project scoped token.
 3755 class GroupSystemRoleAssignmentTestCase(test_v3.RestfulTestCase,
 3756                                         SystemRoleAssignmentMixin):
 3757 
 3758     def test_assign_system_role_to_group(self):
 3759         system_role_id = self._create_new_role()
 3760         group = self._create_group()
 3761 
 3762         # assign the role to the group globally
 3763         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3764             'group_id': group['id'],
 3765             'role_id': system_role_id
 3766         }
 3767         self.put(member_url)
 3768 
 3769         # validate the role assignment
 3770         self.head(member_url)
 3771 
 3772         # list global roles
 3773         collection_url = '/system/groups/%(group_id)s/roles' % {
 3774             'group_id': group['id']
 3775         }
 3776         roles = self.get(collection_url).json_body['roles']
 3777         self.assertEqual(len(roles), 1)
 3778         self.assertEqual(roles[0]['id'], system_role_id)
 3779         self.head(collection_url, expected_status=http.client.OK)
 3780 
 3781         response = self.get(
 3782             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 3783                 'group_id': group['id']
 3784             }
 3785         )
 3786         self.assertValidRoleAssignmentListResponse(response, expected_length=1)
 3787         self.assertEqual(
 3788             response.json_body['role_assignments'][0]['role']['id'],
 3789             system_role_id
 3790         )
 3791 
 3792     def test_assign_system_role_to_non_existant_group_fails(self):
 3793         system_role_id = self._create_new_role()
 3794         group_id = uuid.uuid4().hex
 3795 
 3796         # assign the role to the group globally
 3797         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3798             'group_id': group_id,
 3799             'role_id': system_role_id
 3800         }
 3801         self.put(member_url, expected_status=http.client.NOT_FOUND)
 3802 
 3803     def test_list_role_assignments_for_group_returns_all_assignments(self):
 3804         system_role_id = self._create_new_role()
 3805         group = self._create_group()
 3806 
 3807         # assign the role to the group globally and on a single project
 3808         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3809             'group_id': group['id'],
 3810             'role_id': system_role_id
 3811         }
 3812         self.put(member_url)
 3813         member_url = (
 3814             '/projects/%(project_id)s/groups/%(group_id)s/'
 3815             'roles/%(role_id)s'
 3816         ) % {
 3817             'project_id': self.project_id,
 3818             'group_id': group['id'],
 3819             'role_id': system_role_id
 3820         }
 3821         self.put(member_url)
 3822 
 3823         # make sure both assignments exist in the response, there should be two
 3824         response = self.get(
 3825             '/role_assignments?group.id=%(group_id)s' % {
 3826                 'group_id': group['id']
 3827             }
 3828         )
 3829         self.assertValidRoleAssignmentListResponse(response, expected_length=2)
 3830 
 3831     def test_list_system_roles_for_group_returns_none_without_assignment(self):
 3832         group = self._create_group()
 3833 
 3834         # list global roles for group
 3835         collection_url = '/system/groups/%(group_id)s/roles' % {
 3836             'group_id': group['id']
 3837         }
 3838         response = self.get(collection_url)
 3839 
 3840         # assert that the group doesn't have any system role assignments, which
 3841         # is denoted by an empty list
 3842         self.assertEqual(response.json_body['roles'], [])
 3843 
 3844         response = self.get(
 3845             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 3846                 'group_id': group['id']
 3847             }
 3848         )
 3849         self.assertValidRoleAssignmentListResponse(response, expected_length=0)
 3850 
 3851     def test_list_system_roles_for_group_does_not_return_project_roles(self):
 3852         system_role_id = self._create_new_role()
 3853         project_role_id = self._create_new_role()
 3854         group = self._create_group()
 3855 
 3856         # assign the group a role on the system and a role on a project
 3857         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3858             'group_id': group['id'], 'role_id': system_role_id
 3859         }
 3860         self.put(member_url)
 3861         member_url = (
 3862             '/projects/%(project_id)s/groups/%(group_id)s/'
 3863             'roles/%(role_id)s'
 3864         ) % {
 3865             'project_id': self.project_id,
 3866             'group_id': group['id'],
 3867             'role_id': project_role_id
 3868         }
 3869         self.put(member_url)
 3870 
 3871         # list system role assignments
 3872         collection_url = '/system/groups/%(group_id)s/roles' % {
 3873             'group_id': group['id']
 3874         }
 3875         response = self.get(collection_url)
 3876 
 3877         # assert the project role assignment is not in the system role
 3878         # assignments
 3879         for role in response.json_body['roles']:
 3880             self.assertNotEqual(role['id'], project_role_id)
 3881 
 3882         response = self.get(
 3883             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 3884                 'group_id': group['id']
 3885             }
 3886         )
 3887         self.assertValidRoleAssignmentListResponse(response, expected_length=1)
 3888 
 3889     def test_list_system_roles_for_group_does_not_return_domain_roles(self):
 3890         system_role_id = self._create_new_role()
 3891         domain_role_id = self._create_new_role()
 3892         group = self._create_group()
 3893 
 3894         # assign a role to the group on a domain
 3895         domain_member_url = (
 3896             '/domains/%(domain_id)s/groups/%(group_id)s/'
 3897             'roles/%(role_id)s' % {
 3898                 'domain_id': group['domain_id'],
 3899                 'group_id': group['id'],
 3900                 'role_id': domain_role_id
 3901             }
 3902         )
 3903         self.put(domain_member_url)
 3904 
 3905         # assign the group a role on the system
 3906         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3907             'group_id': group['id'],
 3908             'role_id': system_role_id
 3909         }
 3910         self.put(member_url)
 3911 
 3912         # list domain role assignments
 3913         response = self.get(
 3914             '/domains/%(domain_id)s/groups/%(group_id)s/roles' % {
 3915                 'domain_id': group['domain_id'], 'group_id': group['id']
 3916             }
 3917         )
 3918         self.assertEqual(len(response.json_body['roles']), 1)
 3919 
 3920         # list system role assignments
 3921         collection_url = '/system/groups/%(group_id)s/roles' % {
 3922             'group_id': group['id']
 3923         }
 3924         response = self.get(collection_url)
 3925 
 3926         # assert the domain role assignment is not in the system role
 3927         # assignments
 3928         for role in response.json_body['roles']:
 3929             self.assertNotEqual(role['id'], domain_role_id)
 3930 
 3931         response = self.get(
 3932             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 3933                 'group_id': group['id']
 3934             }
 3935         )
 3936         self.assertValidRoleAssignmentListResponse(response, expected_length=1)
 3937 
 3938     def test_check_group_has_system_role_when_assignment_exists(self):
 3939         system_role_id = self._create_new_role()
 3940         group = self._create_group()
 3941 
 3942         # assign the group a role on the system
 3943         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3944             'group_id': group['id'],
 3945             'role_id': system_role_id
 3946         }
 3947         self.put(member_url)
 3948 
 3949         # check the group has the system role assignment
 3950         self.head(member_url)
 3951 
 3952         response = self.get(
 3953             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 3954                 'group_id': group['id']
 3955             }
 3956         )
 3957         self.assertValidRoleAssignmentListResponse(response, expected_length=1)
 3958         self.assertEqual(
 3959             response.json_body['role_assignments'][0]['role']['id'],
 3960             system_role_id
 3961         )
 3962 
 3963     def test_check_group_does_not_have_system_role_without_assignment(self):
 3964         system_role_id = self._create_new_role()
 3965         group = self._create_group()
 3966 
 3967         # check the group does't have the system role assignment
 3968         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3969             'group_id': group['id'],
 3970             'role_id': system_role_id
 3971         }
 3972         self.head(member_url, expected_status=http.client.NOT_FOUND)
 3973 
 3974         response = self.get(
 3975             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 3976                 'group_id': group['id']
 3977             }
 3978         )
 3979         self.assertValidRoleAssignmentListResponse(response, expected_length=0)
 3980 
 3981     def test_unassign_system_role_from_group(self):
 3982         system_role_id = self._create_new_role()
 3983         group = self._create_group()
 3984 
 3985         # assign the group a role on the system
 3986         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 3987             'group_id': group['id'],
 3988             'role_id': system_role_id
 3989         }
 3990         self.put(member_url)
 3991 
 3992         # ensure the group has the role assignment
 3993         self.head(member_url)
 3994 
 3995         response = self.get(
 3996             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 3997                 'group_id': group['id']
 3998             }
 3999         )
 4000         self.assertEqual(len(response.json_body['role_assignments']), 1)
 4001         self.assertValidRoleAssignmentListResponse(response)
 4002 
 4003         # remove the system role assignment from the group
 4004         self.delete(member_url)
 4005 
 4006         # ensure the group doesn't have any system role assignments
 4007         collection_url = '/system/groups/%(group_id)s/roles' % {
 4008             'group_id': group['id']
 4009         }
 4010         response = self.get(collection_url)
 4011         self.assertEqual(len(response.json_body['roles']), 0)
 4012         response = self.get(
 4013             '/role_assignments?scope.system=all&group.id=%(group_id)s' % {
 4014                 'group_id': group['id']
 4015             }
 4016         )
 4017         self.assertValidRoleAssignmentListResponse(response, expected_length=0)
 4018 
 4019     def test_query_for_role_id_does_not_return_system_group_roles(self):
 4020         system_role_id = self._create_new_role()
 4021         group = self._create_group()
 4022 
 4023         # assign the group a role on the system
 4024         member_url = '/system/groups/%(group_id)s/roles/%(role_id)s' % {
 4025             'group_id': group['id'],
 4026             'role_id': system_role_id
 4027         }
 4028         self.put(member_url)
 4029 
 4030         # assign the group a role on the system
 4031         member_url = (
 4032             '/projects/%(project_id)s/groups/%(group_id)s/roles/%(role_id)s' %
 4033             {'project_id': self.project_id,
 4034              'group_id': group['id'],
 4035              'role_id': self.role_id}
 4036         )
 4037         self.put(member_url)
 4038 
 4039         # Make sure we only get one role assignment back since the system role
 4040         # assignment shouldn't be returned.
 4041         path = (
 4042             '/role_assignments?role.id=%(role_id)s&group.id=%(group_id)s'
 4043         ) % {'role_id': self.role_id, 'group_id': group['id']}
 4044         response = self.get(path)
 4045         self.assertValidRoleAssignmentListResponse(response, expected_length=1)