diff options
| author | Dolph Mathews <dolph.mathews@gmail.com> | 2013-03-18 08:22:01 -0500 |
|---|---|---|
| committer | Dolph Mathews <dolph.mathews@gmail.com> | 2013-03-18 08:22:01 -0500 |
| commit | 7c07de189335571bacced5a1d9a0de2f4c8dcecf (patch) | |
| tree | 759a574bf3b28b07f744aacbd215d9274ece9675 | |
| parent | 167a8b7a3ed8f60018826a2d73d4af3b2ae7b66f (diff) | |
| download | keystone-7c07de189335571bacced5a1d9a0de2f4c8dcecf.tar.gz keystone-7c07de189335571bacced5a1d9a0de2f4c8dcecf.tar.xz keystone-7c07de189335571bacced5a1d9a0de2f4c8dcecf.zip | |
Test default_project_id scoping (bug 1023502)
Change-Id: I14361812980e27b6d3365055586c264e48a25a3b
| -rw-r--r-- | tests/test_v3.py | 30 | ||||
| -rw-r--r-- | tests/test_v3_auth.py | 53 |
2 files changed, 67 insertions, 16 deletions
diff --git a/tests/test_v3.py b/tests/test_v3.py index b14036e1..1d9855e8 100644 --- a/tests/test_v3.py +++ b/tests/test_v3.py @@ -175,6 +175,17 @@ class RestfulTestCase(test_content_types.RestfulTestCase): return ref + def admin_request(self, *args, **kwargs): + """Translates XML responses to dicts. + + This implies that we only have to write assertions for JSON. + + """ + r = super(RestfulTestCase, self).admin_request(*args, **kwargs) + if r.getheader('Content-Type') == 'application/xml': + r.body = serializer.from_xml(etree.tostring(r.body)) + return r + def get_scoped_token(self): """Convenience method so that we can test authenticated requests.""" r = self.admin_request( @@ -223,10 +234,8 @@ class RestfulTestCase(test_content_types.RestfulTestCase): if not token: token = self.get_scoped_token() path = '/v3' + path - return self.admin_request( - path=path, - token=token, - **kwargs) + + return self.admin_request(path=path, token=token, **kwargs) def get(self, path, **kwargs): r = self.v3_request(method='GET', path=path, **kwargs) @@ -300,10 +309,7 @@ class RestfulTestCase(test_content_types.RestfulTestCase): response, and asserted to be equal. """ - resp_body = resp.body - if resp.getheader('Content-Type') == 'application/xml': - resp_body = serializer.from_xml(etree.tostring(resp_body)) - entities = resp_body.get(key) + entities = resp.body.get(key) self.assertIsNotNone(entities) if expected_length is not None: @@ -313,7 +319,7 @@ class RestfulTestCase(test_content_types.RestfulTestCase): self.assertTrue(len(entities)) # collections should have relational links - self.assertValidListLinks(resp_body.get('links')) + self.assertValidListLinks(resp.body.get('links')) for entity in entities: self.assertIsNotNone(entity) @@ -370,11 +376,7 @@ class RestfulTestCase(test_content_types.RestfulTestCase): def assertValidTokenResponse(self, r, user=None): self.assertTrue(r.getheader('X-Subject-Token')) - token = r.body - if r.getheader('Content-Type') == 'application/xml': - token = serializer.from_xml(etree.tostring(r.body))['token'] - else: - token = r.body['token'] + token = r.body['token'] self.assertIsNotNone(token.get('expires_at')) expires_at = self.assertValidISO8601ExtendedFormatDatetime( diff --git a/tests/test_v3_auth.py b/tests/test_v3_auth.py index dea677c2..e3954615 100644 --- a/tests/test_v3_auth.py +++ b/tests/test_v3_auth.py @@ -13,15 +13,14 @@ # under the License. import json -import nose.exc import uuid +import nose.exc from keystone.common import cms from keystone import auth from keystone import config from keystone import exception -from keystone import test import test_v3 @@ -589,6 +588,56 @@ class TestAuthJSON(test_v3.RestfulTestCase): r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse(r) + def test_default_project_id_scoped_token_with_user_id(self): + # create a second project to work with + ref = self.new_project_ref(domain_id=self.domain_id) + r = self.post('/projects', body={'project': ref}) + project = self.assertValidProjectResponse(r, ref) + + # grant the user a role on the project + self.put( + '/projects/%(project_id)s/users/%(user_id)s/roles/%(role_id)s' % { + 'user_id': self.user['id'], + 'project_id': project['id'], + 'role_id': self.role['id']}) + + # set the user's preferred project + body = {'user': {'default_project_id': project['id']}} + r = self.patch('/users/%(user_id)s' % { + 'user_id': self.user['id']}, + body=body) + self.assertValidUserResponse(r) + + # attempt to authenticate without requesting a project + auth_data = self.build_authentication_request( + user_id=self.user['id'], + password=self.user['password']) + r = self.post('/auth/tokens', body=auth_data) + self.assertValidProjectScopedTokenResponse(r) + self.assertEqual(r.body['token']['project']['id'], project['id']) + + def test_default_project_id_scoped_token_with_user_id_401(self): + # create a second project to work with + ref = self.new_project_ref(domain_id=self.domain['id']) + del ref['id'] + r = self.post('/projects', body={'project': ref}) + project = self.assertValidProjectResponse(r, ref) + + # set the user's preferred project without having authz on that project + body = {'user': {'default_project_id': project['id']}} + r = self.patch('/users/%(user_id)s' % { + 'user_id': self.user['id']}, + body=body) + self.assertValidUserResponse(r) + + # attempt to authenticate without requesting a project + # the default_project_id should be the assumed scope of the request, + # and fail because the user doesn't have explicit authz on that scope + auth_data = self.build_authentication_request( + user_id=self.user['id'], + password=self.user['password']) + self.post('/auth/tokens', body=auth_data, expected_status=401) + def test_project_id_scoped_token_with_user_id_401(self): project_id = uuid.uuid4().hex project = self.new_project_ref(domain_id=self.domain_id) |
