diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-02-27 01:30:09 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-02-27 01:30:09 +0000 |
| commit | e865b978fbaf24f29c0797bf6589dc3f7df3f1d5 (patch) | |
| tree | 8d3dad5fd57688d18aabb95ff7caa99a711a9b9e /keystone | |
| parent | 5cfecddec07145d0b6594ecd982b713522536f00 (diff) | |
| parent | 250e6716bd91f9cc3412c92e5341557e59837e1e (diff) | |
Merge "bug 1131840: fix auth and token data for XML translation"
Diffstat (limited to 'keystone')
| -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 |
8 files changed, 78 insertions, 45 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 |
