Reuse token_ref fetched in AuthContextMiddleware.
All keystone middleware components should reuse the auth context prepared by AuthContextMiddleware. Note that AuthContextMiddleware is listed in etc/keystone-paste.ini as one of the earliest middleware components in the keystone pipeline. This means that almost all other middleware components can depend on the auth context being available for use. Also added a test to check that a trust cannot be retrived in case of a missing auth context. Such a request should throw Forbidden exception. Change-Id: I1c08976cf4d175fa2cfe2e39fe55811f04f13243 Closes-Bug: #1433211
This commit is contained in:
parent
c387a9353e
commit
288a05a4de
|
@ -26,10 +26,10 @@ from six.moves import urllib
|
|||
from keystone.assignment import schema
|
||||
from keystone.common import controller
|
||||
from keystone.common import dependency
|
||||
from keystone.common import utils
|
||||
from keystone.common import validation
|
||||
from keystone import exception
|
||||
from keystone.i18n import _, _LW
|
||||
from keystone.models import token_model
|
||||
from keystone import notifications
|
||||
|
||||
|
||||
|
@ -51,14 +51,7 @@ class TenantAssignment(controller.V2Controller):
|
|||
Doesn't care about token scopedness.
|
||||
|
||||
"""
|
||||
try:
|
||||
token_data = self.token_provider_api.validate_token(
|
||||
context['token_id'])
|
||||
token_ref = token_model.KeystoneToken(token_id=context['token_id'],
|
||||
token_data=token_data)
|
||||
except exception.NotFound as e:
|
||||
LOG.warning(_LW('Authentication failed: %s'), e)
|
||||
raise exception.Unauthorized(e)
|
||||
token_ref = utils.get_token_ref(context)
|
||||
|
||||
tenant_refs = (
|
||||
self.assignment_api.list_projects_for_user(token_ref.user_id))
|
||||
|
|
|
@ -690,19 +690,7 @@ class V3Controller(wsgi.Application):
|
|||
if context['query_string'].get('domain_id') is not None:
|
||||
return context['query_string'].get('domain_id')
|
||||
|
||||
try:
|
||||
token_ref = token_model.KeystoneToken(
|
||||
token_id=context['token_id'],
|
||||
token_data=self.token_provider_api.validate_token(
|
||||
context['token_id']))
|
||||
except KeyError:
|
||||
raise exception.ValidationError(
|
||||
_('domain_id is required as part of entity'))
|
||||
except (exception.TokenNotFound,
|
||||
exception.UnsupportedTokenVersionException):
|
||||
LOG.warning(_LW('Invalid token found while getting domain ID '
|
||||
'for list request'))
|
||||
raise exception.Unauthorized()
|
||||
token_ref = utils.get_token_ref(context)
|
||||
|
||||
if token_ref.domain_scoped:
|
||||
return token_ref.domain_id
|
||||
|
@ -719,25 +707,7 @@ class V3Controller(wsgi.Application):
|
|||
being used.
|
||||
|
||||
"""
|
||||
# We could make this more efficient by loading the domain_id
|
||||
# into the context in the wrapper function above (since
|
||||
# this version of normalize_domain will only be called inside
|
||||
# a v3 protected call). However, this optimization is probably not
|
||||
# worth the duplication of state
|
||||
try:
|
||||
token_ref = token_model.KeystoneToken(
|
||||
token_id=context['token_id'],
|
||||
token_data=self.token_provider_api.validate_token(
|
||||
context['token_id']))
|
||||
except KeyError:
|
||||
# This might happen if we use the Admin token, for instance
|
||||
raise exception.ValidationError(
|
||||
_('A domain-scoped token must be used'))
|
||||
except (exception.TokenNotFound,
|
||||
exception.UnsupportedTokenVersionException):
|
||||
LOG.warning(_LW('Invalid token found while getting domain ID '
|
||||
'for create request'))
|
||||
raise exception.Unauthorized()
|
||||
token_ref = utils.get_token_ref(context)
|
||||
|
||||
if token_ref.domain_scoped:
|
||||
return token_ref.domain_id
|
||||
|
|
|
@ -32,6 +32,7 @@ import passlib.hash
|
|||
import six
|
||||
from six import moves
|
||||
|
||||
from keystone.common import authorization
|
||||
from keystone import exception
|
||||
from keystone.i18n import _, _LE, _LW
|
||||
|
||||
|
@ -504,3 +505,20 @@ def isotime(at=None, subsecond=False):
|
|||
def strtime():
|
||||
at = timeutils.utcnow()
|
||||
return at.strftime(timeutils.PERFECT_TIME_FORMAT)
|
||||
|
||||
|
||||
def get_token_ref(context):
|
||||
"""Retrieves KeystoneToken object from the auth context and returns it.
|
||||
|
||||
:param dict context: The request context.
|
||||
:raises: exception.Unauthorized if auth context cannot be found.
|
||||
:returns: The KeystoneToken object.
|
||||
"""
|
||||
try:
|
||||
# Retrieve the auth context that was prepared by AuthContextMiddleware.
|
||||
auth_context = (context['environment']
|
||||
[authorization.AUTH_CONTEXT_ENV])
|
||||
return auth_context['token']
|
||||
except KeyError:
|
||||
LOG.warning(_LW("Couldn't find the auth context."))
|
||||
raise exception.Unauthorized()
|
||||
|
|
|
@ -299,13 +299,7 @@ class Application(BaseApplication):
|
|||
"""
|
||||
|
||||
if not context['is_admin']:
|
||||
try:
|
||||
user_token_ref = token_model.KeystoneToken(
|
||||
token_id=context['token_id'],
|
||||
token_data=self.token_provider_api.validate_token(
|
||||
context['token_id']))
|
||||
except exception.TokenNotFound as e:
|
||||
raise exception.Unauthorized(e)
|
||||
user_token_ref = utils.get_token_ref(context)
|
||||
|
||||
validate_token_bind(context, user_token_ref)
|
||||
creds = copy.deepcopy(user_token_ref.metadata)
|
||||
|
@ -364,16 +358,7 @@ class Application(BaseApplication):
|
|||
LOG.debug(('will not lookup trust as the request auth token is '
|
||||
'either absent or it is the system admin token'))
|
||||
return None
|
||||
|
||||
try:
|
||||
token_data = self.token_provider_api.validate_token(
|
||||
context['token_id'])
|
||||
except exception.TokenNotFound:
|
||||
LOG.warning(_LW('Invalid token in _get_trust_id_for_request'))
|
||||
raise exception.Unauthorized()
|
||||
|
||||
token_ref = token_model.KeystoneToken(token_id=context['token_id'],
|
||||
token_data=token_data)
|
||||
token_ref = utils.get_token_ref(context)
|
||||
return token_ref.trust_id
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -46,7 +46,6 @@ from keystone.common import utils
|
|||
from keystone.common import wsgi
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone.models import token_model
|
||||
|
||||
|
||||
@dependency.requires('assignment_api', 'catalog_api', 'credential_api',
|
||||
|
@ -319,14 +318,7 @@ class Ec2Controller(Ec2ControllerCommon, controller.V2Controller):
|
|||
:raises exception.Forbidden: when token is invalid
|
||||
|
||||
"""
|
||||
try:
|
||||
token_data = self.token_provider_api.validate_token(
|
||||
context['token_id'])
|
||||
except exception.TokenNotFound as e:
|
||||
raise exception.Unauthorized(e)
|
||||
|
||||
token_ref = token_model.KeystoneToken(token_id=context['token_id'],
|
||||
token_data=token_data)
|
||||
token_ref = utils.get_token_ref(context)
|
||||
|
||||
if token_ref.user_id != user_id:
|
||||
raise exception.Forbidden(_('Token belongs to another user'))
|
||||
|
|
|
@ -20,12 +20,12 @@ from oslo_utils import timeutils
|
|||
|
||||
from keystone.common import controller
|
||||
from keystone.common import dependency
|
||||
from keystone.common import utils
|
||||
from keystone.common import wsgi
|
||||
from keystone.contrib.oauth1 import core as oauth1
|
||||
from keystone.contrib.oauth1 import validator
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone.models import token_model
|
||||
from keystone import notifications
|
||||
|
||||
|
||||
|
@ -84,10 +84,7 @@ class ConsumerCrudV3(controller.V3Controller):
|
|||
|
||||
@controller.protected()
|
||||
def delete_consumer(self, context, consumer_id):
|
||||
user_token_ref = token_model.KeystoneToken(
|
||||
token_id=context['token_id'],
|
||||
token_data=self.token_provider_api.validate_token(
|
||||
context['token_id']))
|
||||
user_token_ref = utils.get_token_ref(context)
|
||||
payload = {'user_id': user_token_ref.user_id,
|
||||
'consumer_id': consumer_id}
|
||||
_emit_user_oauth_consumer_token_invalidate(payload)
|
||||
|
@ -382,10 +379,7 @@ class OAuthControllerV3(controller.V3Controller):
|
|||
authed_roles.add(role['id'])
|
||||
|
||||
# verify the authorizing user has the roles
|
||||
user_token = token_model.KeystoneToken(
|
||||
token_id=context['token_id'],
|
||||
token_data=self.token_provider_api.validate_token(
|
||||
context['token_id']))
|
||||
user_token = utils.get_token_ref(context)
|
||||
user_id = user_token.user_id
|
||||
project_id = req_token['requested_project_id']
|
||||
user_roles = self.assignment_api.get_roles_for_user_and_project(
|
||||
|
|
|
@ -933,8 +933,8 @@ class AuthWithTrust(AuthTest):
|
|||
|
||||
def test_get_trust(self):
|
||||
unscoped_token = self.get_unscoped_token(self.trustor['name'])
|
||||
context = {'token_id': unscoped_token['access']['token']['id'],
|
||||
'host_url': HOST_URL}
|
||||
context = self._create_auth_context(
|
||||
unscoped_token['access']['token']['id'])
|
||||
new_trust = self.trust_controller.create_trust(
|
||||
context, trust=self.sample_data)['trust']
|
||||
trust = self.trust_controller.get_trust(context,
|
||||
|
@ -945,6 +945,21 @@ class AuthWithTrust(AuthTest):
|
|||
for role in new_trust['roles']:
|
||||
self.assertIn(role['id'], role_ids)
|
||||
|
||||
def test_get_trust_without_auth_context(self):
|
||||
"""Verify that a trust cannot be retrieved when the auth context is
|
||||
missing.
|
||||
"""
|
||||
unscoped_token = self.get_unscoped_token(self.trustor['name'])
|
||||
context = self._create_auth_context(
|
||||
unscoped_token['access']['token']['id'])
|
||||
new_trust = self.trust_controller.create_trust(
|
||||
context, trust=self.sample_data)['trust']
|
||||
# Delete the auth context before calling get_trust().
|
||||
del context['environment'][authorization.AUTH_CONTEXT_ENV]
|
||||
self.assertRaises(exception.Forbidden,
|
||||
self.trust_controller.get_trust, context,
|
||||
new_trust['id'])
|
||||
|
||||
def test_create_trust_no_impersonation(self):
|
||||
new_trust = self.create_trust(self.sample_data, self.trustor['name'],
|
||||
expires_at=None, impersonation=False)
|
||||
|
|
|
@ -27,7 +27,6 @@ from keystone.common import utils
|
|||
from keystone.common import validation
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone.models import token_model
|
||||
from keystone import notifications
|
||||
from keystone.trust import schema
|
||||
|
||||
|
@ -64,13 +63,11 @@ class TrustV3(controller.V3Controller):
|
|||
return super(TrustV3, cls).base_url(context, path=path)
|
||||
|
||||
def _get_user_id(self, context):
|
||||
if 'token_id' in context:
|
||||
token_id = context['token_id']
|
||||
token_data = self.token_provider_api.validate_token(token_id)
|
||||
token_ref = token_model.KeystoneToken(token_id=token_id,
|
||||
token_data=token_data)
|
||||
return token_ref.user_id
|
||||
return None
|
||||
try:
|
||||
token_ref = utils.get_token_ref(context)
|
||||
except exception.Unauthorized:
|
||||
return None
|
||||
return token_ref.user_id
|
||||
|
||||
def get_trust(self, context, trust_id):
|
||||
user_id = self._get_user_id(context)
|
||||
|
|
Loading…
Reference in New Issue