Merge "Consolidate the fernet provider validate_v3_token()"

This commit is contained in:
Jenkins 2016-02-04 18:48:54 +00:00 committed by Gerrit Code Review
commit c4640b8708
5 changed files with 62 additions and 47 deletions

View File

@ -49,10 +49,14 @@ class TestFernetTokenProvider(unit.TestCase):
self.assertFalse(self.provider.needs_persistence())
def test_invalid_v3_token_raises_token_not_found(self):
# NOTE(lbragstad): Here we use the validate_non_persistent_token()
# methods because the validate_v3_token() method is strictly for
# validating UUID formatted tokens. It is written to assume cached
# tokens from a backend, where validate_non_persistent_token() is not.
token_id = uuid.uuid4().hex
e = self.assertRaises(
exception.TokenNotFound,
self.provider.validate_v3_token,
self.provider.validate_non_persistent_token,
token_id)
self.assertIn(token_id, u'%s' % e)

View File

@ -253,19 +253,19 @@ class Manager(manager.Manager):
if not token_id:
raise exception.TokenNotFound(_('No token in the request'))
unique_id = utils.generate_unique_id(token_id)
# NOTE(lbragstad): Only go to persistent storage if we have a token to
# fetch from the backend (the driver persists the token). Otherwise
# the information about the token must be in the token id.
if not self._needs_persistence:
token_ref = token_id
token_ref = self.validate_non_persistent_token(token_id)
else:
unique_id = utils.generate_unique_id(token_id)
# NOTE(morganfainberg): Ensure we never use the long-form token_id
# (PKI) as part of the cache_key.
token_ref = self._persistence.get_token(unique_id)
token = self._validate_v3_token(token_ref)
self._is_valid_token(token)
return token
token_ref = self._validate_v3_token(token_ref)
self._is_valid_token(token_ref)
return token_ref
@MEMOIZE
def _validate_token(self, token_id):
@ -273,7 +273,9 @@ class Manager(manager.Manager):
raise exception.TokenNotFound(_('No token in the request'))
if not self._needs_persistence:
return self.driver.validate_v3_token(token_id)
# NOTE(lbragstad): This will validate v2 and v3 non-persistent
# tokens.
return self.driver.validate_non_persistent_token(token_id)
token_ref = self._persistence.get_token(token_id)
version = self.get_token_version(token_ref)
if version == self.V3:
@ -577,6 +579,17 @@ class Provider(object):
"""
raise exception.NotImplemented() # pragma: no cover
@abc.abstractmethod
def validate_non_persistent_token(self, token_id):
"""Validate a given non-persistent token id and return the token_data.
:param token_id: the token id
:type token_id: string
:returns: token data
:raises keystone.exception.TokenNotFound: When the token is invalid
"""
raise exception.NotImplemented() # pragma: no cover
@abc.abstractmethod
def validate_v3_token(self, token_ref):
"""Validate the given V3 token and return the token_data.

View File

@ -678,6 +678,43 @@ class BaseProvider(provider.Provider):
token_id = token_ref['token_data']['access']['token']['id']
raise exception.TokenNotFound(token_id=token_id)
def validate_non_persistent_token(self, token_id):
try:
(user_id, methods, audit_ids, domain_id, project_id, trust_id,
federated_info, created_at, expires_at) = (
self.token_formatter.validate_token(token_id))
except exception.ValidationError as e:
raise exception.TokenNotFound(e)
token_dict = None
trust_ref = None
if federated_info:
# NOTE(lbragstad): We need to rebuild information about the
# federated token as well as the federated token roles. This is
# because when we validate a non-persistent token, we don't have a
# token reference to pull the federated token information out of.
# As a result, we have to extract it from the token itself and
# rebuild the federated context. These private methods currently
# live in the keystone.token.providers.fernet.Provider() class.
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 validate_v3_token(self, token_ref):
# FIXME(gyee): performance or correctness? Should we return the
# cached token or reconstruct it? Obviously if we are going with

View File

@ -230,45 +230,6 @@ class Provider(common.BaseProvider):
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:
raise exception.TokenNotFound(token_id=token)
token_dict = 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)
trust_ref = None
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 _get_token_id(self, token_data):
"""Generate the token_id based upon the data in token_data.

View File

@ -99,7 +99,7 @@ class TokenFormatter(object):
return self.crypto.decrypt(token.encode('utf-8'))
except fernet.InvalidToken:
raise exception.ValidationError(
_('This is not a recognized Fernet token'))
_('This is not a recognized Fernet token %s') % token)
@classmethod
def restore_padding(cls, token):