summaryrefslogtreecommitdiffstats
path: root/keystone-moon/keystone/token/providers/fernet/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon/keystone/token/providers/fernet/core.py')
-rw-r--r--keystone-moon/keystone/token/providers/fernet/core.py239
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