diff options
Diffstat (limited to 'keystone-moon/keystone/token/providers/fernet/core.py')
-rw-r--r-- | keystone-moon/keystone/token/providers/fernet/core.py | 239 |
1 files changed, 77 insertions, 162 deletions
diff --git a/keystone-moon/keystone/token/providers/fernet/core.py b/keystone-moon/keystone/token/providers/fernet/core.py index a71c375b..ff6fe9cc 100644 --- a/keystone-moon/keystone/token/providers/fernet/core.py +++ b/keystone-moon/keystone/token/providers/fernet/core.py @@ -11,23 +11,18 @@ # under the License. from oslo_config import cfg -from oslo_log import log from keystone.common import dependency from keystone.common import utils as ks_utils -from keystone.contrib.federation import constants as federation_constants -from keystone import exception -from keystone.i18n import _ -from keystone.token import provider +from keystone.federation import constants as federation_constants from keystone.token.providers import common from keystone.token.providers.fernet import token_formatters as tf CONF = cfg.CONF -LOG = log.getLogger(__name__) -@dependency.requires('trust_api') +@dependency.requires('trust_api', 'oauth_api') class Provider(common.BaseProvider): def __init__(self, *args, **kwargs): super(Provider, self).__init__(*args, **kwargs) @@ -38,65 +33,10 @@ class Provider(common.BaseProvider): """Should the token be written to a backend.""" return False - def issue_v2_token(self, token_ref, roles_ref=None, catalog_ref=None): - """Issue a V2 formatted token. - - :param token_ref: reference describing the token - :param roles_ref: reference describing the roles for the token - :param catalog_ref: reference describing the token's catalog - :returns: tuple containing the ID of the token and the token data - - """ - # TODO(lbragstad): Currently, Fernet tokens don't support bind in the - # token format. Raise a 501 if we're dealing with bind. - if token_ref.get('bind'): - raise exception.NotImplemented() - - user_id = token_ref['user']['id'] - # Default to password since methods not provided by token_ref - method_names = ['password'] - project_id = None - # Verify that tenant is not None in token_ref - if token_ref.get('tenant'): - project_id = token_ref['tenant']['id'] - - # maintain expiration time across rescopes - expires = token_ref.get('expires') - - parent_audit_id = token_ref.get('parent_audit_id') - # If parent_audit_id is defined then a token authentication was made - if parent_audit_id: - method_names.append('token') - - audit_ids = provider.audit_info(parent_audit_id) - - # Get v3 token data and exclude building v3 specific catalog. This is - # due to the fact that the V2TokenDataHelper.format_token() method - # doesn't build any of the token_reference from other Keystone APIs. - # Instead, it builds it from what is persisted in the token reference. - # Here we are going to leverage the V3TokenDataHelper.get_token_data() - # method written for V3 because it goes through and populates the token - # reference dynamically. Once we have a V3 token reference, we can - # attempt to convert it to a V2 token response. - v3_token_data = self.v3_token_data_helper.get_token_data( - user_id, - method_names, - project_id=project_id, - token=token_ref, - include_catalog=False, - audit_info=audit_ids, - expires=expires) - - expires_at = v3_token_data['token']['expires_at'] - token_id = self.token_formatter.create_token(user_id, expires_at, - audit_ids, - methods=method_names, - project_id=project_id) - self._build_issued_at_info(token_id, v3_token_data) - # Convert v3 to v2 token data and build v2 catalog - token_data = self.v2_token_data_helper.v3_to_v2_token(v3_token_data) - token_data['access']['token']['id'] = token_id - + def issue_v2_token(self, *args, **kwargs): + token_id, token_data = super(Provider, self).issue_v2_token( + *args, **kwargs) + self._build_issued_at_info(token_id, token_data) return token_id, token_data def issue_v3_token(self, *args, **kwargs): @@ -117,8 +57,12 @@ class Provider(common.BaseProvider): # that we have to rely on when we validate the token. fernet_creation_datetime_obj = self.token_formatter.creation_time( token_id) - token_data['token']['issued_at'] = ks_utils.isotime( - at=fernet_creation_datetime_obj, subsecond=True) + if token_data.get('access'): + token_data['access']['token']['issued_at'] = ks_utils.isotime( + at=fernet_creation_datetime_obj, subsecond=True) + else: + token_data['token']['issued_at'] = ks_utils.isotime( + at=fernet_creation_datetime_obj, subsecond=True) def _build_federated_info(self, token_data): """Extract everything needed for federated tokens. @@ -127,18 +71,18 @@ class Provider(common.BaseProvider): the values and build federated Fernet tokens. """ - idp_id = token_data['token'].get('user', {}).get( - federation_constants.FEDERATION, {}).get( - 'identity_provider', {}).get('id') - protocol_id = token_data['token'].get('user', {}).get( - federation_constants.FEDERATION, {}).get('protocol', {}).get('id') - # If we don't have an identity provider ID and a protocol ID, it's safe - # to assume we aren't dealing with a federated token. - if not (idp_id and protocol_id): - return None - - group_ids = token_data['token'].get('user', {}).get( - federation_constants.FEDERATION, {}).get('groups') + token_data = token_data['token'] + try: + user = token_data['user'] + federation = user[federation_constants.FEDERATION] + idp_id = federation['identity_provider']['id'] + protocol_id = federation['protocol']['id'] + except KeyError: + # The token data doesn't have federated info, so we aren't dealing + # with a federated token and no federated info to build. + return + + group_ids = federation.get('groups') return {'group_ids': group_ids, 'idp_id': idp_id, @@ -195,96 +139,66 @@ class Provider(common.BaseProvider): self.v3_token_data_helper.populate_roles_for_groups( token_dict, group_ids, project_id, domain_id, user_id) - def validate_v2_token(self, token_ref): - """Validate a V2 formatted token. - - :param token_ref: reference describing the token to validate - :returns: the token data - :raises keystone.exception.TokenNotFound: if token format is invalid - :raises keystone.exception.Unauthorized: if v3 token is used - - """ - try: - (user_id, methods, - audit_ids, domain_id, - project_id, trust_id, - federated_info, created_at, - expires_at) = self.token_formatter.validate_token(token_ref) - except exception.ValidationError as e: - raise exception.TokenNotFound(e) - - if trust_id or domain_id or federated_info: - msg = _('This is not a v2.0 Fernet token. Use v3 for trust, ' - 'domain, or federated tokens.') - raise exception.Unauthorized(msg) - - v3_token_data = self.v3_token_data_helper.get_token_data( - user_id, - methods, - project_id=project_id, - expires=expires_at, - issued_at=created_at, - token=token_ref, - include_catalog=False, - audit_info=audit_ids) - token_data = self.v2_token_data_helper.v3_to_v2_token(v3_token_data) - token_data['access']['token']['id'] = token_ref - return token_data - - def validate_v3_token(self, token): - """Validate a V3 formatted token. - - :param token: a string describing the token to validate - :returns: the token data - :raises keystone.exception.TokenNotFound: if token format version isn't - supported - - """ - try: - (user_id, methods, audit_ids, domain_id, project_id, trust_id, - federated_info, created_at, expires_at) = ( - self.token_formatter.validate_token(token)) - except exception.ValidationError as e: - raise exception.TokenNotFound(e) - - token_dict = None - trust_ref = None - if federated_info: - token_dict = self._rebuild_federated_info(federated_info, user_id) - if project_id or domain_id: - self._rebuild_federated_token_roles(token_dict, federated_info, - user_id, project_id, - domain_id) - if trust_id: - trust_ref = self.trust_api.get_trust(trust_id) - - return self.v3_token_data_helper.get_token_data( - user_id, - method_names=methods, - domain_id=domain_id, - project_id=project_id, - issued_at=created_at, - expires=expires_at, - trust=trust_ref, - token=token_dict, - audit_info=audit_ids) + def _extract_v2_token_data(self, token_data): + user_id = token_data['access']['user']['id'] + expires_at = token_data['access']['token']['expires'] + audit_ids = token_data['access']['token'].get('audit_ids') + methods = ['password'] + if len(audit_ids) > 1: + methods.append('token') + project_id = token_data['access']['token'].get('tenant', {}).get('id') + domain_id = None + trust_id = None + access_token_id = None + federated_info = None + return (user_id, expires_at, audit_ids, methods, domain_id, project_id, + trust_id, access_token_id, federated_info) + + def _extract_v3_token_data(self, token_data): + """Extract information from a v3 token reference.""" + user_id = token_data['token']['user']['id'] + expires_at = token_data['token']['expires_at'] + audit_ids = token_data['token']['audit_ids'] + methods = token_data['token'].get('methods') + domain_id = token_data['token'].get('domain', {}).get('id') + project_id = token_data['token'].get('project', {}).get('id') + trust_id = token_data['token'].get('OS-TRUST:trust', {}).get('id') + access_token_id = token_data['token'].get('OS-OAUTH1', {}).get( + 'access_token_id') + federated_info = self._build_federated_info(token_data) + + return (user_id, expires_at, audit_ids, methods, domain_id, project_id, + trust_id, access_token_id, federated_info) def _get_token_id(self, token_data): """Generate the token_id based upon the data in token_data. :param token_data: token information :type token_data: dict - :raises keystone.exception.NotImplemented: when called + :rtype: six.text_type + """ + # NOTE(lbragstad): Only v2.0 token responses include an 'access' + # attribute. + if token_data.get('access'): + (user_id, expires_at, audit_ids, methods, domain_id, project_id, + trust_id, access_token_id, federated_info) = ( + self._extract_v2_token_data(token_data)) + else: + (user_id, expires_at, audit_ids, methods, domain_id, project_id, + trust_id, access_token_id, federated_info) = ( + self._extract_v3_token_data(token_data)) + return self.token_formatter.create_token( - token_data['token']['user']['id'], - token_data['token']['expires_at'], - token_data['token']['audit_ids'], - methods=token_data['token'].get('methods'), - domain_id=token_data['token'].get('domain', {}).get('id'), - project_id=token_data['token'].get('project', {}).get('id'), - trust_id=token_data['token'].get('OS-TRUST:trust', {}).get('id'), - federated_info=self._build_federated_info(token_data) + user_id, + expires_at, + audit_ids, + methods=methods, + domain_id=domain_id, + project_id=project_id, + trust_id=trust_id, + federated_info=federated_info, + access_token_id=access_token_id ) @property @@ -292,5 +206,6 @@ class Provider(common.BaseProvider): """Return if the token provider supports bind authentication methods. :returns: False + """ return False |