Use from_environ when creating a context

The from_environ method is designed to pick up all the parameters set
from auth_token middleware and other oslo middlewares and create a
context with them.

By doing this there will be information available to libraries like
oslo.policy and oslo.logging without nova having to track each change to
the base library.

There is ongoing work here to move more values to the base class that
will be cleaned up in future.

Change-Id: I6b61028fcecb86cc6c25fb69977774e266a8ea5b
Related-Bug: #1602081
This commit is contained in:
Jamie Lennox 2016-07-14 11:25:09 +10:00
parent 2a610741b5
commit 13b5ab2686
3 changed files with 26 additions and 36 deletions

View File

@ -76,29 +76,10 @@ class NovaKeystoneContext(wsgi.Middleware):
@webob.dec.wsgify(RequestClass=wsgi.Request)
def __call__(self, req):
user_id = req.headers.get('X_USER')
user_id = req.headers.get('X_USER_ID', user_id)
if user_id is None:
LOG.debug("Neither X_USER_ID nor X_USER found in request")
return webob.exc.HTTPUnauthorized()
roles = self._get_roles(req)
if 'X_TENANT_ID' in req.headers:
# This is the new header since Keystone went to ID/Name
project_id = req.headers['X_TENANT_ID']
else:
# This is for legacy compatibility
project_id = req.headers['X_TENANT']
project_name = req.headers.get('X_TENANT_NAME')
user_name = req.headers.get('X_USER_NAME')
req_id = req.environ.get(request_id.ENV_REQUEST_ID)
# Get the auth token
auth_token = req.headers.get('X_AUTH_TOKEN',
req.headers.get('X_STORAGE_TOKEN'))
# Build a context, including the auth_token...
remote_address = req.remote_addr
if CONF.use_forwarded_for:
@ -117,22 +98,18 @@ class NovaKeystoneContext(wsgi.Middleware):
# middleware in newer versions.
user_auth_plugin = req.environ.get('keystone.token_auth')
ctx = context.RequestContext(user_id,
project_id,
user_name=user_name,
project_name=project_name,
roles=roles,
auth_token=auth_token,
remote_address=remote_address,
service_catalog=service_catalog,
request_id=req_id,
user_auth_plugin=user_auth_plugin)
ctx = context.RequestContext.from_environ(
req.environ,
user_name=user_name,
project_name=project_name,
user_auth_plugin=user_auth_plugin,
remote_address=remote_address,
service_catalog=service_catalog,
request_id=req_id)
if ctx.user_id is None:
LOG.debug("Neither X_USER_ID nor X_USER found in request")
return webob.exc.HTTPUnauthorized()
req.environ['nova.context'] = ctx
return self.application
def _get_roles(self, req):
"""Get the list of roles."""
roles = req.headers.get('X_ROLES', '')
return [r.strip() for r in roles.split(',')]

View File

@ -197,6 +197,19 @@ class RequestContext(context.RequestContext):
instance_lock_checked=values.get('instance_lock_checked', False),
)
@classmethod
def from_environ(cls, environ, **kwargs):
ctx = super(RequestContext, cls).from_environ(environ, **kwargs)
# the base oslo.context sets its user param and tenant param but not
# our user_id and project_id param so fix those up.
if ctx.user and not ctx.user_id:
ctx.user_id = ctx.user
if ctx.tenant and not ctx.project_id:
ctx.project_id = ctx.tenant
return ctx
def elevated(self, read_deleted=None):
"""Return a version of this context with admin flag set."""
context = copy.copy(self)

View File

@ -91,7 +91,7 @@ class TestKeystoneMiddlewareRoles(test.NoDBTestCase):
if "knight" in context.roles and "bad" not in context.roles:
return webob.Response(status="200 Role Match")
elif context.roles == ['']:
elif not context.roles:
return webob.Response(status="200 No Roles")
else:
raise webob.exc.HTTPBadRequest("unexpected role header")