diff options
author | Guang Yee <guang.yee@hp.com> | 2013-02-25 12:46:16 -0800 |
---|---|---|
committer | Guang Yee <guang.yee@hp.com> | 2013-02-26 09:22:09 -0800 |
commit | 250e6716bd91f9cc3412c92e5341557e59837e1e (patch) | |
tree | 45aaadc5f93c9852b8de78a782e074d02c4e9da1 | |
parent | f3d2a462209a9f2dd3faa1c5ca271f304eaa16d5 (diff) | |
download | keystone-250e6716bd91f9cc3412c92e5341557e59837e1e.tar.gz keystone-250e6716bd91f9cc3412c92e5341557e59837e1e.tar.xz keystone-250e6716bd91f9cc3412c92e5341557e59837e1e.zip |
bug 1131840: fix auth and token data for XML translation
Change-Id: I4408b3e6e0752ca75bc36399f5148890820e9a89
-rw-r--r-- | keystone/auth/controllers.py | 26 | ||||
-rw-r--r-- | keystone/auth/core.py | 28 | ||||
-rw-r--r-- | keystone/auth/methods/token.py | 14 | ||||
-rw-r--r-- | keystone/auth/token_factory.py | 14 | ||||
-rw-r--r-- | keystone/common/controller.py | 2 | ||||
-rw-r--r-- | keystone/common/serializer.py | 34 | ||||
-rw-r--r-- | keystone/common/wsgi.py | 2 | ||||
-rw-r--r-- | keystone/middleware/core.py | 3 | ||||
-rw-r--r-- | tests/test_auth_plugin.py | 8 | ||||
-rw-r--r-- | tests/test_content_types.py | 23 | ||||
-rw-r--r-- | tests/test_serializer.py | 11 | ||||
-rw-r--r-- | tests/test_v3.py | 45 | ||||
-rw-r--r-- | tests/test_v3_auth.py | 85 | ||||
-rw-r--r-- | tests/test_v3_protection.py | 13 |
14 files changed, 189 insertions, 119 deletions
diff --git a/keystone/auth/controllers.py b/keystone/auth/controllers.py index d2eaa234..3760aa3a 100644 --- a/keystone/auth/controllers.py +++ b/keystone/auth/controllers.py @@ -187,15 +187,15 @@ class AuthInfo(object): def _validate_auth_methods(self): # make sure auth methods are provided - if 'methods' not in self.auth['authentication']: + if 'methods' not in self.auth['identity']: raise exception.ValidationError(attribute='methods', - target='authentication') + target='identity') # make sure all the method data/payload are provided for method_name in self.get_method_names(): - if method_name not in self.auth['authentication']: + if method_name not in self.auth['identity']: raise exception.ValidationError(attribute=method_name, - target='authentication') + target='identity') # make sure auth method is supported for method_name in self.get_method_names(): @@ -213,12 +213,12 @@ class AuthInfo(object): self._validate_and_normalize_scope_data() def get_method_names(self): - """ Returns the authentication method names. + """ Returns the identity method names. :returns: list of auth method names """ - return self.auth['authentication']['methods'] + return self.auth['identity']['methods'] def get_method_data(self, method): """ Get the auth method payload. @@ -226,10 +226,10 @@ class AuthInfo(object): :returns: auth method payload """ - if method not in self.auth['authentication']['methods']: + if method not in self.auth['identity']['methods']: raise exception.ValidationError(attribute=method_name, - target='authentication') - return self.auth['authentication'][method] + target='identity') + return self.auth['identity'][method] def get_scope(self): """ Get scope information. @@ -257,13 +257,9 @@ class Auth(controller.V3Controller): super(Auth, self).__init__(*args, **kw) self.token_controllers_ref = token.controllers.Auth() - def authenticate_for_token(self, context, authentication, scope=None): + def authenticate_for_token(self, context, auth=None): """ Authenticate user and issue a token. """ try: - auth = None - auth = {'authentication': authentication} - if scope: - auth['scope'] = scope auth_info = AuthInfo(context, auth=auth) auth_context = {'extras': {}, 'method_names': []} self.authenticate(context, auth_info, auth_context) @@ -306,7 +302,7 @@ class Auth(controller.V3Controller): # requiring domain_id to do user lookup now. Try to get # the user_id from auth_info for now, assuming external auth # has check to make sure user is the same as the one specify - # in "authentication". + # in "identity". if 'password' in auth_info.get_method_names(): user_info = auth_info.get_method_data('password') user_ref = auth_info.lookup_user(user_info['user']) diff --git a/keystone/auth/core.py b/keystone/auth/core.py index 40f7d040..da70c43c 100644 --- a/keystone/auth/core.py +++ b/keystone/auth/core.py @@ -49,21 +49,23 @@ class AuthMethodHandler(object): "extras": {}} Plugins are invoked in the order in which they are specified in the - "methods" attribute of the "authentication" request body. + "methods" attribute of the "identity" object. For example, with the following authentication request, - {"authentication": { - "methods": ["custom-plugin", "password", "token"], - "token": { - "id": "sdfafasdfsfasfasdfds" - }, - "custom-plugin": { - "custom-data": "sdfdfsfsfsdfsf" - }, - "password": { - "user": { - "id": "s23sfad1", - "password": "secrete" + {"auth": { + "identity": { + "methods": ["custom-plugin", "password", "token"], + "token": { + "id": "sdfafasdfsfasfasdfds" + }, + "custom-plugin": { + "custom-data": "sdfdfsfsfsdfsf" + }, + "password": { + "user": { + "id": "s23sfad1", + "password": "secrete" + } } } }} diff --git a/keystone/auth/methods/token.py b/keystone/auth/methods/token.py index 72006130..05c5385d 100644 --- a/keystone/auth/methods/token.py +++ b/keystone/auth/methods/token.py @@ -38,12 +38,14 @@ class Token(auth.AuthMethodHandler): target=METHOD_NAME) token_id = auth_payload['id'] token_ref = self.token_api.get_token(context, token_id) - user_context.setdefault('user_id', - token_ref['token_data']['user']['id']) - user_context.setdefault('expires', - token_ref['expires']) - user_context['extras'].update(token_ref['token_data']['extras']) - user_context['method_names'] += token_ref['token_data']['methods'] + user_context.setdefault( + 'user_id', token_ref['token_data']['token']['user']['id']) + user_context.setdefault( + 'expires', token_ref['token_data']['token']['expires']) + user_context['extras'].update( + token_ref['token_data']['token']['extras']) + user_context['method_names'].extend( + token_ref['token_data']['token']['methods']) except AssertionError as e: LOG.error(e) raise exception.Unauthorized(e) diff --git a/keystone/auth/token_factory.py b/keystone/auth/token_factory.py index 03d4ed74..4b1bf637 100644 --- a/keystone/auth/token_factory.py +++ b/keystone/auth/token_factory.py @@ -144,7 +144,7 @@ class TokenDataHelper(object): self._populate_service_catalog(token_data, user_id, domain_id, project_id) self._populate_token(token_data, expires) - return token_data + return {'token': token_data} def recreate_token_data(context, token_data=None, expires=None, @@ -161,6 +161,8 @@ def recreate_token_data(context, token_data=None, expires=None, methods = ['password', 'token'] extras = {} if token_data: + # peel the outer layer so its easier to operate + token_data = token_data['token'] domain_id = (token_data['domain']['id'] if 'domain' in token_data else None) project_id = (token_data['project']['id'] if 'project' in token_data @@ -207,20 +209,20 @@ def create_token(context, auth_context, auth_info): CONF.signing.token_format) token_api = token_module.Manager() try: - expiry = token_data['expires'] + expiry = token_data['token']['expires'] if isinstance(expiry, basestring): expiry = timeutils.parse_isotime(expiry) role_ids = [] - if 'project' in token_data: + if 'project' in token_data['token']: # project-scoped token, fill in the v2 token data # all we care are the role IDs - role_ids = [role['id'] for role in token_data['roles']] + role_ids = [role['id'] for role in token_data['token']['roles']] metadata_ref = {'roles': role_ids} data = dict(key=token_id, id=token_id, expires=expiry, - user=token_data['user'], - tenant=token_data.get('project'), + user=token_data['token']['user'], + tenant=token_data['token'].get('project'), metadata=metadata_ref, token_data=token_data) token_api.create_token(context, token_id, data) diff --git a/keystone/common/controller.py b/keystone/common/controller.py index 4d8c5ddc..c9300002 100644 --- a/keystone/common/controller.py +++ b/keystone/common/controller.py @@ -30,7 +30,7 @@ def _build_policy_check_credentials(self, action, context, kwargs): creds = {} if 'token_data' in token_ref: #V3 Tokens - token_data = token_ref['token_data'] + token_data = token_ref['token_data']['token'] try: creds['user_id'] = token_data['user']['id'] except AttributeError: diff --git a/keystone/common/serializer.py b/keystone/common/serializer.py index 2a33ee70..91a16be4 100644 --- a/keystone/common/serializer.py +++ b/keystone/common/serializer.py @@ -120,10 +120,28 @@ class XmlDeserializer(object): # current spec does not have attributes on an element with text values = values or text or {} + decoded_tag = XmlDeserializer._tag_name(element.tag, namespace) + list_item_tag = None + if decoded_tag[-1] == 's' and len(values) == 0: + # FIXME(gyee): special-case lists for now unti we + # figure out how to properly handle them. + # If any key ends with an 's', we are assuming it is a list. + # List element have no attributes. + values = list(values) + if decoded_tag == 'policies': + list_item_tag = 'policy' + else: + list_item_tag = decoded_tag[:-1] for child in [self.walk_element(x) for x in element if not isinstance(x, ENTITY_TYPE)]: - values = dict(values.items() + child.items()) + if list_item_tag: + # FIXME(gyee): special-case lists for now unti we + # figure out how to properly handle them. + # If any key ends with an 's', we are assuming it is a list. + values.append(child[list_item_tag]) + else: + values = dict(values.items() + child.items()) return {XmlDeserializer._tag_name(element.tag, namespace): values} @@ -173,7 +191,7 @@ class XmlSerializer(object): container = etree.Element(k) element.append(container) name = k[:-1] - elif k == 'serviceCatalog': + elif k == 'serviceCatalog' or k == 'catalog': # xsd compliance: <serviceCatalog> contains <service>s container = etree.Element(k) element.append(container) @@ -184,7 +202,13 @@ class XmlSerializer(object): # unnecessary in XML name = element.tag[:-1] elif k[-1] == 's': - name = k[:-1] + container = etree.Element(k) + element.append(container) + if k == 'policies': + # need to special-case policies since policie is not a word + name = 'policy' + else: + name = k[:-1] else: name = k @@ -226,6 +250,8 @@ class XmlSerializer(object): self._populate_sequence(element, value) elif isinstance(value, dict): self._populate_tree(element, value) + elif isinstance(value, basestring): + element.text = unicode(value) def _populate_sequence(self, element, l): """Populates an etree with a sequence of elements, given a list.""" @@ -233,6 +259,8 @@ class XmlSerializer(object): name = element.tag if element.tag[-1] == 's': name = element.tag[:-1] + if name == 'policie': + name = 'policy' for item in l: child = etree.Element(name) diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py index a515eefe..108cc0ca 100644 --- a/keystone/common/wsgi.py +++ b/keystone/common/wsgi.py @@ -553,5 +553,5 @@ def render_exception(error): 'message': str(error) }} if isinstance(error, exception.AuthPluginException): - body['authentication'] = error.authentication + body['error']['identity'] = error.authentication return render_response(status=(error.code, error.title), body=body) diff --git a/keystone/middleware/core.py b/keystone/middleware/core.py index d904e3c0..29a6832b 100644 --- a/keystone/middleware/core.py +++ b/keystone/middleware/core.py @@ -16,6 +16,7 @@ import webob.dec +from keystone.common import logging from keystone.common import serializer from keystone.common import utils from keystone.common import wsgi @@ -25,6 +26,7 @@ from keystone.openstack.common import jsonutils CONF = config.CONF +LOG = logging.getLogger(__name__) # Header used to transmit the auth token @@ -158,6 +160,7 @@ class XmlBodyMiddleware(wsgi.Middleware): body_obj = jsonutils.loads(response.body) response.body = serializer.to_xml(body_obj) except Exception: + LOG.exception('Serializer failed') raise exception.Error(message=response.body) return response diff --git a/tests/test_auth_plugin.py b/tests/test_auth_plugin.py index d35d5f23..fc44c53d 100644 --- a/tests/test_auth_plugin.py +++ b/tests/test_auth_plugin.py @@ -56,7 +56,7 @@ class TestAuthPlugin(test.TestCase): method_name = uuid.uuid4().hex auth_data = {'methods': [method_name]} auth_data[method_name] = {'test': 'test'} - auth_data = {'authentication': auth_data} + auth_data = {'identity': auth_data} self.assertRaises(exception.AuthMethodNotSupported, auth.controllers.AuthInfo, None, @@ -66,7 +66,7 @@ class TestAuthPlugin(test.TestCase): auth_data = {'methods': ['simple-challenge-response']} auth_data['simple-challenge-response'] = { 'test': 'test'} - auth_data = {'authentication': auth_data} + auth_data = {'identity': auth_data} auth_info = auth.controllers.AuthInfo(None, auth_data) auth_context = {'extras': {}, 'method_names': []} try: @@ -81,7 +81,7 @@ class TestAuthPlugin(test.TestCase): auth_data = {'methods': ['simple-challenge-response']} auth_data['simple-challenge-response'] = { 'response': EXPECTED_RESPONSE} - auth_data = {'authentication': auth_data} + auth_data = {'identity': auth_data} auth_info = auth.controllers.AuthInfo(None, auth_data) auth_context = {'extras': {}, 'method_names': []} self.api.authenticate({}, auth_info, auth_context) @@ -91,7 +91,7 @@ class TestAuthPlugin(test.TestCase): auth_data = {'methods': ['simple-challenge-response']} auth_data['simple-challenge-response'] = { 'response': uuid.uuid4().hex} - auth_data = {'authentication': auth_data} + auth_data = {'identity': auth_data} auth_info = auth.controllers.AuthInfo(None, auth_data) auth_context = {'extras': {}, 'method_names': []} self.assertRaises(exception.Unauthorized, diff --git a/tests/test_content_types.py b/tests/test_content_types.py index 183974fd..91b61661 100644 --- a/tests/test_content_types.py +++ b/tests/test_content_types.py @@ -173,15 +173,15 @@ class RestfulTestCase(test.TestCase): if response.body is not None and response.body.strip(): # if a body is provided, a Content-Type is also expected header = response.getheader('Content-Type', None) - self.assertIn(self.content_type, header) + self.assertIn(content_type, header) - if self.content_type == 'json': + if content_type == 'json': response.body = jsonutils.loads(response.body) - elif self.content_type == 'xml': + elif content_type == 'xml': response.body = etree.fromstring(response.body) def restful_request(self, method='GET', headers=None, body=None, - token=None, **kwargs): + token=None, content_type=None, **kwargs): """Serializes/deserializes json/xml as request/response body. .. WARNING:: @@ -196,13 +196,13 @@ class RestfulTestCase(test.TestCase): if token is not None: headers['X-Auth-Token'] = token - body = self._to_content_type(body, headers) + body = self._to_content_type(body, headers, content_type) # Perform the HTTP request/response response = self.request(method=method, headers=headers, body=body, **kwargs) - self._from_content_type(response) + self._from_content_type(response, content_type) # we can save some code & improve coverage by always doing this if method != 'HEAD' and response.status >= 400: @@ -742,8 +742,9 @@ class XmlTestCase(RestfulTestCase, CoreApiTests): self.assertIsNotNone(extension.find(self._tag('description'))) self.assertTrue(extension.find(self._tag('description')).text) - self.assertTrue(len(extension.findall(self._tag('link')))) - for link in extension.findall(self._tag('link')): + links = extension.find(self._tag('links')) + self.assertTrue(len(links.findall(self._tag('link')))) + for link in links.findall(self._tag('link')): self.assertValidExtensionLink(link) def assertValidExtensionListResponse(self, r): @@ -763,8 +764,10 @@ class XmlTestCase(RestfulTestCase, CoreApiTests): def assertValidVersion(self, version): super(XmlTestCase, self).assertValidVersion(version) - self.assertTrue(len(version.findall(self._tag('link')))) - for link in version.findall(self._tag('link')): + links = version.find(self._tag('links')) + self.assertIsNotNone(links) + self.assertTrue(len(links.findall(self._tag('link')))) + for link in links.findall(self._tag('link')): self.assertIsNotNone(link.get('rel')) self.assertIsNotNone(link.get('href')) diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 288e5516..816bad45 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -145,6 +145,17 @@ class XmlSerializerTestCase(test.TestCase): self.assertSerializeDeserialize(d, xml) + def test_policy_list(self): + d = {"policies": [{"id": "ab12cd"}]} + + xml = """ + <?xml version="1.0" encoding="UTF-8"?> + <policies xmlns="http://docs.openstack.org/identity/api/v2.0"> + <policy id="ab12cd"/> + </policies> + """ + self.assertEqualIgnoreWhitespace(serializer.to_xml(d), xml) + def test_values_list(self): d = { "objects": { diff --git a/tests/test_v3.py b/tests/test_v3.py index ef1a1a6c..a0252af0 100644 --- a/tests/test_v3.py +++ b/tests/test_v3.py @@ -1,5 +1,8 @@ import uuid +from lxml import etree + +from keystone.common import serializer from keystone.common.sql import util as sql_util from keystone import auth from keystone import test @@ -128,21 +131,23 @@ class RestfulTestCase(test_content_types.RestfulTestCase): method='POST', path='/v3/auth/tokens', body={ - 'authentication': { - 'methods': ['password'], - 'password': { - 'user': { - 'name': self.user['name'], - 'password': self.user['password'], - 'domain': { - 'id': self.user['domain_id'] + 'auth': { + 'identity': { + 'methods': ['password'], + 'password': { + 'user': { + 'name': self.user['name'], + 'password': self.user['password'], + 'domain': { + 'id': self.user['domain_id'] + } } } - } - }, - 'scope': { - 'project': { - 'id': self.project['id'], + }, + 'scope': { + 'project': { + 'id': self.project['id'], + } } } }) @@ -191,11 +196,15 @@ class RestfulTestCase(test_content_types.RestfulTestCase): return self.v3_request(method='DELETE', path=path, **kwargs) def assertValidErrorResponse(self, r): - self.assertIsNotNone(r.body.get('error')) - self.assertIsNotNone(r.body['error'].get('code')) - self.assertIsNotNone(r.body['error'].get('title')) - self.assertIsNotNone(r.body['error'].get('message')) - self.assertEqual(r.body['error']['code'], r.status) + if r.getheader('Content-Type') == 'application/xml': + resp = serializer.from_xml(etree.tostring(r.body)) + else: + resp = r.body + self.assertIsNotNone(resp.get('error')) + self.assertIsNotNone(resp['error'].get('code')) + self.assertIsNotNone(resp['error'].get('title')) + self.assertIsNotNone(resp['error'].get('message')) + self.assertEqual(int(resp['error']['code']), r.status) def assertValidListResponse(self, resp, key, entity_validator, ref=None, expected_length=None): diff --git a/tests/test_v3_auth.py b/tests/test_v3_auth.py index c7f78adf..0497ff9a 100644 --- a/tests/test_v3_auth.py +++ b/tests/test_v3_auth.py @@ -14,9 +14,13 @@ import uuid +from lxml import etree + from keystone import auth from keystone import config from keystone import exception +from keystone.common import serializer +from keystone.openstack.common import jsonutils from keystone.openstack.common import timeutils from keystone import test @@ -86,13 +90,13 @@ def _build_authentication_request(token=None, user_id=None, username=None, that it receives. """ auth_data = {} - auth_data['authentication'] = {'methods': []} + auth_data['identity'] = {'methods': []} if token: - auth_data['authentication']['methods'].append('token') - auth_data['authentication']['token'] = _build_token_auth(token) + auth_data['identity']['methods'].append('token') + auth_data['identity']['token'] = _build_token_auth(token) if user_id or username: - auth_data['authentication']['methods'].append('password') - auth_data['authentication']['password'] = _build_password_auth( + auth_data['identity']['methods'].append('password') + auth_data['identity']['password'] = _build_password_auth( user_id, username, user_domain_id, user_domain_name, password) if project_id or project_name or domain_id or domain_name: auth_data['scope'] = _build_auth_scope(project_id, @@ -101,14 +105,17 @@ def _build_authentication_request(token=None, user_id=None, username=None, project_domain_name, domain_id, domain_name) - return auth_data + return {'auth': auth_data} class AuthTest(test_v3.RestfulTestCase): def assertValidTokenResponse(self, r): 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'] self.assertIn('expires', token) self.assertIn('user', token) self.assertEqual(self.user['id'], token['user']['id']) @@ -169,23 +176,23 @@ class AuthTest(test_v3.RestfulTestCase): the time in the comparison. """ def normalize(token): - del token['expires'] - del token['issued_at'] + del token['token']['expires'] + del token['token']['issued_at'] return token self.assertCloseEnoughForGovernmentWork( - timeutils.parse_isotime(a['expires']), - timeutils.parse_isotime(b['expires'])) + timeutils.parse_isotime(a['token']['expires']), + timeutils.parse_isotime(b['token']['expires'])) self.assertCloseEnoughForGovernmentWork( - timeutils.parse_isotime(a['issued_at']), - timeutils.parse_isotime(b['issued_at'])) + timeutils.parse_isotime(a['token']['issued_at']), + timeutils.parse_isotime(b['token']['issued_at'])) return self.assertDictEqual(normalize(a), normalize(b)) class TestAuthInfo(test.TestCase): def test_missing_auth_methods(self): - auth_data = {'authentication': {}} - auth_data['authentication']['token'] = {'id': uuid.uuid4().hex} + auth_data = {'identity': {}} + auth_data['identity']['token'] = {'id': uuid.uuid4().hex} self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo, None, @@ -194,7 +201,7 @@ class TestAuthInfo(test.TestCase): def test_unsupported_auth_method(self): auth_data = {'methods': ['abc']} auth_data['abc'] = {'test': 'test'} - auth_data = {'authentication': auth_data} + auth_data = {'identity': auth_data} self.assertRaises(exception.AuthMethodNotSupported, auth.controllers.AuthInfo, None, @@ -202,7 +209,7 @@ class TestAuthInfo(test.TestCase): def test_missing_auth_method_data(self): auth_data = {'methods': ['password']} - auth_data = {'authentication': auth_data} + auth_data = {'identity': auth_data} self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo, None, @@ -211,7 +218,7 @@ class TestAuthInfo(test.TestCase): def test_project_name_no_domain(self): auth_data = _build_authentication_request(username='test', password='test', - project_name='abc') + project_name='abc')['auth'] self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo, None, @@ -221,7 +228,7 @@ class TestAuthInfo(test.TestCase): auth_data = _build_authentication_request(user_id='test', password='test', project_name='test', - domain_name='test') + domain_name='test')['auth'] self.assertRaises(exception.ValidationError, auth.controllers.AuthInfo, None, @@ -262,11 +269,11 @@ class TestTokenAPIs(AuthTest): method='GET') v2_token = resp.body self.assertEqual(v2_token['access']['user']['id'], - token_data['user']['id']) + token_data['token']['user']['id']) self.assertEqual(v2_token['access']['token']['expires'], - token_data['expires']) + token_data['token']['expires']) self.assertEqual(v2_token['access']['user']['roles'][0]['id'], - token_data['roles'][0]['id']) + token_data['token']['roles'][0]['id']) def test_v3_v2_pki_token_intermix(self): # FIXME(gyee): PKI tokens are not interchangeable because token @@ -287,11 +294,11 @@ class TestTokenAPIs(AuthTest): method='GET') v2_token = resp.body self.assertEqual(v2_token['access']['user']['id'], - token_data['user']['id']) + token_data['token']['user']['id']) self.assertEqual(v2_token['access']['token']['expires'], - token_data['expires']) + token_data['token']['expires']) self.assertEqual(v2_token['access']['user']['roles'][0]['id'], - token_data['roles'][0]['id']) + token_data['token']['roles'][0]['id']) def test_v2_v3_uuid_token_intermix(self): self.opt_in_group('signing', token_format='UUID') @@ -312,11 +319,11 @@ class TestTokenAPIs(AuthTest): resp = self.get('/auth/tokens', headers=headers) token_data = resp.body self.assertEqual(v2_token_data['access']['user']['id'], - token_data['user']['id']) + token_data['token']['user']['id']) self.assertEqual(v2_token_data['access']['token']['expires'], - token_data['expires']) + token_data['token']['expires']) self.assertEqual(v2_token_data['access']['user']['roles'][0]['name'], - token_data['roles'][0]['name']) + token_data['token']['roles'][0]['name']) def test_v2_v3_pki_token_intermix(self): self.opt_in_group('signing', token_format='PKI') @@ -337,21 +344,21 @@ class TestTokenAPIs(AuthTest): resp = self.get('/auth/tokens', headers=headers) token_data = resp.body self.assertEqual(v2_token_data['access']['user']['id'], - token_data['user']['id']) + token_data['token']['user']['id']) self.assertEqual(v2_token_data['access']['token']['expires'], - token_data['expires']) + token_data['token']['expires']) self.assertEqual(v2_token_data['access']['user']['roles'][0]['name'], - token_data['roles'][0]['name']) + token_data['token']['roles'][0]['name']) def test_rescoping_token(self): - expires = self.token_data['expires'] + expires = self.token_data['token']['expires'] auth_data = _build_authentication_request( token=self.token, project_id=self.project_id) r = self.post('/auth/tokens', body=auth_data) self.assertValidProjectScopedTokenResponse(r) # make sure expires stayed the same - self.assertEqual(expires, r.body['expires']) + self.assertEqual(expires, r.body['token']['expires']) def test_check_token(self): self.head('/auth/tokens', headers=self.headers, expected_status=204) @@ -370,7 +377,9 @@ class TestTokenAPIs(AuthTest): self.assertIn('signed', r.body) -class TestAuth(AuthTest): +class TestAuthJSON(AuthTest): + content_type = 'json' + def test_unscoped_token_with_user_id(self): auth_data = _build_authentication_request( user_id=self.user['id'], @@ -601,7 +610,7 @@ class TestAuth(AuthTest): def test_remote_user(self): auth_data = _build_authentication_request( user_id=self.user['id'], - password=self.user['password']) + password=self.user['password'])['auth'] api = auth.controllers.Auth() context = {'REMOTE_USER': self.user['name']} auth_info = auth.controllers.AuthInfo(None, auth_data) @@ -612,7 +621,7 @@ class TestAuth(AuthTest): def test_remote_user_no_domain(self): auth_data = _build_authentication_request( username=self.user['name'], - password=self.user['password']) + password=self.user['password'])['auth'] api = auth.controllers.Auth() context = {'REMOTE_USER': self.user['name']} auth_info = auth.controllers.AuthInfo(None, auth_data) @@ -622,3 +631,7 @@ class TestAuth(AuthTest): context, auth_info, auth_context) + + +class TestAuthXML(TestAuthJSON): + content_type = 'xml' diff --git a/tests/test_v3_protection.py b/tests/test_v3_protection.py index 999dfa86..5b461693 100644 --- a/tests/test_v3_protection.py +++ b/tests/test_v3_protection.py @@ -83,13 +83,14 @@ class IdentityTestProtectedCase(test_v3.RestfulTestCase): # A default auth request we can use - un-scoped user token self.auth = {} - self.auth['authentication'] = {'methods': []} - self.auth['authentication']['methods'].append('password') - self.auth['authentication']['password'] = {'user': {}} - self.auth['authentication']['password']['user']['id'] = ( + self.auth['identity'] = {'methods': []} + self.auth['identity']['methods'].append('password') + self.auth['identity']['password'] = {'user': {}} + self.auth['identity']['password']['user']['id'] = ( self.user1['id']) - self.auth['authentication']['password']['user']['password'] = ( + self.auth['identity']['password']['user']['password'] = ( self.user1['password']) + self.auth = {'auth': self.auth} def tearDown(self): super(IdentityTestProtectedCase, self).tearDown() @@ -136,7 +137,7 @@ class IdentityTestProtectedCase(test_v3.RestfulTestCase): new_policy = """{"identity:list_users": ["domain_id:%(domain_id)s"]}""" with open(self.tmpfilename, "w") as policyfile: policyfile.write(new_policy) - self.auth['scope'] = {'domain': {'id': self.domainA['id']}} + self.auth['auth']['scope'] = {'domain': {'id': self.domainA['id']}} url_by_name = '/users?domain_id=%s' % self.user1['domain_id'] r = self.get(url_by_name, auth=self.auth) # We should only get back one user, the one in DomainA |