diff options
author | Marek Denis <marek.denis@cern.ch> | 2014-10-23 18:28:51 +0200 |
---|---|---|
committer | Steve Martinelli <stevemar@ca.ibm.com> | 2015-01-14 01:03:43 -0500 |
commit | 2e4878ac5c619887900d5c996a66aabf8e31f7d9 (patch) | |
tree | a364f46891f6908e51fd6ce141d904b5b19137e4 /keystone/auth/plugins/token.py | |
parent | 9e5aa70c365070a7c5484488b2ddb3319937e260 (diff) | |
download | keystone-2e4878ac5c619887900d5c996a66aabf8e31f7d9.tar.gz |
Scope federated token with 'token' identity method
Instead of using separate identity method mapped/saml2 a 'token' method
should be used.
Change-Id: Ife1906c9aa63c41bfe19d20b9f08d158d1f8662f
Implements: blueprint federation-token-scoping
Diffstat (limited to 'keystone/auth/plugins/token.py')
-rw-r--r-- | keystone/auth/plugins/token.py | 100 |
1 files changed, 58 insertions, 42 deletions
diff --git a/keystone/auth/plugins/token.py b/keystone/auth/plugins/token.py index 2e8f5040b..d6ae62b00 100644 --- a/keystone/auth/plugins/token.py +++ b/keystone/auth/plugins/token.py @@ -13,6 +13,7 @@ # under the License. from keystone import auth +from keystone.auth.plugins import mapped from keystone.common import dependency from keystone.common import wsgi from keystone import exception @@ -23,51 +24,66 @@ from keystone.openstack.common import log LOG = log.getLogger(__name__) -@dependency.requires('token_provider_api') +@dependency.optional('federation_api') +@dependency.requires('identity_api', 'token_provider_api') class Token(auth.AuthMethodHandler): method = 'token' + def _get_token_ref(self, auth_payload): + token_id = auth_payload['id'] + response = self.token_provider_api.validate_token(token_id) + return token_model.KeystoneToken(token_id=token_id, + token_data=response) + def authenticate(self, context, auth_payload, user_context): + if 'id' not in auth_payload: + raise exception.ValidationError(attribute='id', + target=self.method) + token_ref = self._get_token_ref(auth_payload) + if token_ref.is_federated_user and self.federation_api: + mapped.handle_scoped_token( + context, auth_payload, user_context, token_ref, + self.federation_api, self.identity_api, + self.token_provider_api) + else: + token_authenticate(context, auth_payload, user_context, token_ref) + + +def token_authenticate(context, auth_payload, user_context, token_ref): + try: + + # Do not allow tokens used for delegation to + # create another token, or perform any changes of + # state in Keystone. To do so is to invite elevation of + # privilege attacks + + if token_ref.oauth_scoped or token_ref.trust_scoped: + raise exception.Forbidden() + + wsgi.validate_token_bind(context, token_ref) + + # New tokens maintain the audit_id of the original token in the + # chain (if possible) as the second element in the audit data + # structure. Look for the last element in the audit data structure + # which will be either the audit_id of the token (in the case of + # a token that has not been rescoped) or the audit_chain id (in + # the case of a token that has been rescoped). try: - if 'id' not in auth_payload: - raise exception.ValidationError(attribute='id', - target=self.method) - token_id = auth_payload['id'] - response = self.token_provider_api.validate_token(token_id) - token_ref = token_model.KeystoneToken(token_id=token_id, - token_data=response) - - # Do not allow tokens used for delegation to - # create another token, or perform any changes of - # state in Keystone. To do so is to invite elevation of - # privilege attacks - if token_ref.oauth_scoped or token_ref.trust_scoped: - raise exception.Forbidden() - - wsgi.validate_token_bind(context, token_ref) - - # New tokens maintain the audit_id of the original token in the - # chain (if possible) as the second element in the audit data - # structure. Look for the last element in the audit data structure - # which will be either the audit_id of the token (in the case of - # a token that has not been rescoped) or the audit_chain id (in - # the case of a token that has been rescoped). - try: - token_audit_id = token_ref.get('audit_ids', [])[-1] - except IndexError: - # NOTE(morganfainberg): In the case this is a token that was - # issued prior to audit id existing, the chain is not tracked. - token_audit_id = None - - user_context.setdefault('expires_at', token_ref.expires) - user_context['audit_id'] = token_audit_id - user_context.setdefault('user_id', token_ref.user_id) - # TODO(morganfainberg: determine if token 'extras' can be removed - # from the user_context - user_context['extras'].update(token_ref.get('extras', {})) - user_context['method_names'].extend(token_ref.methods) - - except AssertionError as e: - LOG.error(e) - raise exception.Unauthorized(e) + token_audit_id = token_ref.get('audit_ids', [])[-1] + except IndexError: + # NOTE(morganfainberg): In the case this is a token that was + # issued prior to audit id existing, the chain is not tracked. + token_audit_id = None + + user_context.setdefault('expires_at', token_ref.expires) + user_context['audit_id'] = token_audit_id + user_context.setdefault('user_id', token_ref.user_id) + # TODO(morganfainberg: determine if token 'extras' can be removed + # from the user_context + user_context['extras'].update(token_ref.get('extras', {})) + user_context['method_names'].extend(token_ref.methods) + + except AssertionError as e: + LOG.error(e) + raise exception.Unauthorized(e) |