summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDolph Mathews <dolph.mathews@gmail.com>2013-03-18 08:22:01 -0500
committerDolph Mathews <dolph.mathews@gmail.com>2013-03-18 08:22:01 -0500
commit7c07de189335571bacced5a1d9a0de2f4c8dcecf (patch)
tree759a574bf3b28b07f744aacbd215d9274ece9675
parent167a8b7a3ed8f60018826a2d73d4af3b2ae7b66f (diff)
downloadkeystone-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.py30
-rw-r--r--tests/test_v3_auth.py53
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)