"Fossies" - the Fresh Open Source Software Archive

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