Add is_admin_project to context
is_admin_project is provided by keystonemiddleware and used by oslo.policy to enforce that a project scoped token exists in the admin project. To make this usable we add the ability to read the X-Is-Admin-Project header from the environment, and add it to the outputted policy values. Note the value is added to keystonemiddleware in the depend review however it must work even with older auth_token middlewares so is fine to merge prior to a middleware release. Closes-Bug: #1577996 Depends-On: Ic680e6eaa683926914cf4b2152ec3bb67c6601ff Change-Id: Ie48fedb8092e33e9645a37ea3fe44b88d34ad3b8
This commit is contained in:
parent
ae6f152447
commit
d3af1d06b4
|
@ -71,11 +71,16 @@ class RequestContext(object):
|
|||
read_only=False, show_deleted=False, request_id=None,
|
||||
resource_uuid=None, overwrite=True, roles=None,
|
||||
user_name=None, project_name=None, domain_name=None,
|
||||
user_domain_name=None, project_domain_name=None):
|
||||
user_domain_name=None, project_domain_name=None,
|
||||
is_admin_project=True):
|
||||
"""Initialize the RequestContext
|
||||
|
||||
:param overwrite: Set to False to ensure that the greenthread local
|
||||
copy of the index is not overwritten.
|
||||
:param is_admin_project: Whether the specified project is specified in
|
||||
the token as the admin project. Defaults to
|
||||
True for backwards compatibility.
|
||||
:type is_admin_project: bool
|
||||
"""
|
||||
self.auth_token = auth_token
|
||||
self.user = user
|
||||
|
@ -91,6 +96,7 @@ class RequestContext(object):
|
|||
self.project_domain = project_domain
|
||||
self.project_domain_name = project_domain_name
|
||||
self.is_admin = is_admin
|
||||
self.is_admin_project = is_admin_project
|
||||
self.read_only = read_only
|
||||
self.show_deleted = show_deleted
|
||||
self.resource_uuid = resource_uuid
|
||||
|
@ -121,7 +127,8 @@ class RequestContext(object):
|
|||
'user_domain_id': self.user_domain,
|
||||
'project_id': self.tenant,
|
||||
'project_domain_id': self.project_domain,
|
||||
'roles': self.roles}
|
||||
'roles': self.roles,
|
||||
'is_admin_project': self.is_admin_project}
|
||||
|
||||
def to_dict(self):
|
||||
"""Return a dictionary of context attributes."""
|
||||
|
@ -144,7 +151,8 @@ class RequestContext(object):
|
|||
'request_id': self.request_id,
|
||||
'resource_uuid': self.resource_uuid,
|
||||
'roles': self.roles,
|
||||
'user_identity': user_idt}
|
||||
'user_identity': user_idt,
|
||||
'is_admin_project': self.is_admin_project}
|
||||
|
||||
def get_logging_values(self):
|
||||
"""Return a dictionary of logging specific context attributes."""
|
||||
|
@ -194,6 +202,13 @@ class RequestContext(object):
|
|||
roles = [r.strip() for r in roles.split(',')] if roles else []
|
||||
kwargs['roles'] = roles
|
||||
|
||||
if 'is_admin_project' not in kwargs:
|
||||
# NOTE(jamielennox): we default is_admin_project to true because if
|
||||
# nothing is provided we have to assume it is the admin project to
|
||||
# make old policy continue to work.
|
||||
is_admin_proj_str = environ.get('HTTP_X_IS_ADMIN_PROJECT', 'true')
|
||||
kwargs['is_admin_project'] = is_admin_proj_str.lower() == 'true'
|
||||
|
||||
return cls(**kwargs)
|
||||
|
||||
|
||||
|
|
|
@ -241,6 +241,22 @@ class ContextTest(test_base.BaseTestCase):
|
|||
ctx = context.RequestContext.from_environ(environ=environ)
|
||||
self.assertEqual(['abc', 'def', 'ghi'], ctx.roles)
|
||||
|
||||
def test_environ_admin_project(self):
|
||||
environ = {}
|
||||
ctx = context.RequestContext.from_environ(environ=environ)
|
||||
self.assertIs(True, ctx.is_admin_project)
|
||||
self.assertIs(True, ctx.to_policy_values()['is_admin_project'])
|
||||
|
||||
environ = {'HTTP_X_IS_ADMIN_PROJECT': 'True'}
|
||||
ctx = context.RequestContext.from_environ(environ=environ)
|
||||
self.assertIs(True, ctx.is_admin_project)
|
||||
self.assertIs(True, ctx.to_policy_values()['is_admin_project'])
|
||||
|
||||
environ = {'HTTP_X_IS_ADMIN_PROJECT': 'False'}
|
||||
ctx = context.RequestContext.from_environ(environ=environ)
|
||||
self.assertIs(False, ctx.is_admin_project)
|
||||
self.assertIs(False, ctx.to_policy_values()['is_admin_project'])
|
||||
|
||||
def test_from_function_and_args(self):
|
||||
ctx = context.RequestContext(user="user1")
|
||||
arg = []
|
||||
|
@ -390,6 +406,7 @@ class ContextTest(test_base.BaseTestCase):
|
|||
project_domain = uuid.uuid4().hex
|
||||
roles = [uuid.uuid4().hex, uuid.uuid4().hex, uuid.uuid4().hex]
|
||||
|
||||
# default is_admin_project is True
|
||||
ctx = context.RequestContext(user=user,
|
||||
user_domain=user_domain,
|
||||
tenant=tenant,
|
||||
|
@ -400,4 +417,22 @@ class ContextTest(test_base.BaseTestCase):
|
|||
'user_domain_id': user_domain,
|
||||
'project_id': tenant,
|
||||
'project_domain_id': project_domain,
|
||||
'roles': roles}, ctx.to_policy_values())
|
||||
'roles': roles,
|
||||
'is_admin_project': True},
|
||||
ctx.to_policy_values())
|
||||
|
||||
# is_admin_project False gets passed through
|
||||
ctx = context.RequestContext(user=user,
|
||||
user_domain=user_domain,
|
||||
tenant=tenant,
|
||||
project_domain=project_domain,
|
||||
roles=roles,
|
||||
is_admin_project=False)
|
||||
|
||||
self.assertEqual({'user_id': user,
|
||||
'user_domain_id': user_domain,
|
||||
'project_id': tenant,
|
||||
'project_domain_id': project_domain,
|
||||
'roles': roles,
|
||||
'is_admin_project': False},
|
||||
ctx.to_policy_values())
|
||||
|
|
Loading…
Reference in New Issue