From e1925637b4c0ec24575ef35b85deb8273053086b Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Wed, 4 May 2016 18:54:54 +1000 Subject: [PATCH 1/3] Allow deprecated headers in from_environ from_environ only supported the current environ variables from auth_token middleware as these have been in use for a long time. It turns out particularly in testing that services may still use the deprecated headers so we should still support those in oslo.context. Change-Id: Ia7faf7b657525c11f728ac753422efe87f6ac34f --- oslo_context/context.py | 33 +++++++++++++++----- oslo_context/tests/test_context.py | 48 ++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/oslo_context/context.py b/oslo_context/context.py index 038948d..bfbedcb 100644 --- a/oslo_context/context.py +++ b/oslo_context/context.py @@ -34,6 +34,18 @@ import uuid _request_store = threading.local() +# These arguments will be passed to a new context from the first available +# header to support backwards compatibility. +_ENVIRON_HEADERS = {'auth_token': ['HTTP_X_AUTH_TOKEN', + 'HTTP_X_STORAGE_TOKEN'], + 'user': ['HTTP_X_USER_ID', + 'HTTP_X_USER'], + 'tenant': ['HTTP_X_PROJECT_ID', + 'HTTP_X_TENANT_ID', + 'HTTP_X_TENANT'], + 'user_domain': ['HTTP_X_USER_DOMAIN_ID'], + 'project_domain': ['HTTP_X_PROJECT_DOMAIN_ID']} + def generate_request_id(): """Generate a unique request id.""" @@ -148,15 +160,20 @@ class RequestContext(object): # Load a new context object from the environment variables set by # auth_token middleware. See: # http://docs.openstack.org/developer/keystonemiddleware/api/keystonemiddleware.auth_token.html#what-auth-token-adds-to-the-request-for-use-by-the-openstack-service - kwargs.setdefault('auth_token', environ.get('HTTP_X_AUTH_TOKEN')) - kwargs.setdefault('user', environ.get('HTTP_X_USER_ID')) - kwargs.setdefault('tenant', environ.get('HTTP_X_PROJECT_ID')) - kwargs.setdefault('user_domain', environ.get('HTTP_X_USER_DOMAIN_ID')) - kwargs.setdefault('project_domain', - environ.get('HTTP_X_PROJECT_DOMAIN_ID')) - roles = environ.get('HTTP_X_ROLES') - kwargs.setdefault('roles', roles.split(',') if roles else []) + # add kwarg if not specified by user from a list of possible headers + for k, v_list in _ENVIRON_HEADERS.items(): + if k in kwargs: + continue + + for v in v_list: + if v in environ: + kwargs[k] = environ[v] + break + + if 'roles' not in kwargs: + roles = environ.get('HTTP_X_ROLES', environ.get('HTTP_X_ROLE')) + kwargs['roles'] = roles.split(',') if roles else [] return cls(**kwargs) diff --git a/oslo_context/tests/test_context.py b/oslo_context/tests/test_context.py index 7d13c06..f2a095a 100644 --- a/oslo_context/tests/test_context.py +++ b/oslo_context/tests/test_context.py @@ -161,6 +161,54 @@ class ContextTest(test_base.BaseTestCase): ctx = context.RequestContext.from_environ(environ={'HTTP_X_ROLES': ''}) self.assertEqual([], ctx.roles) + def test_from_environ_deprecated_variables(self): + value = uuid.uuid4().hex + + environ = {'HTTP_X_USER': value} + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual(value, ctx.user) + + environ = {'HTTP_X_TENANT_ID': value} + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual(value, ctx.tenant) + + environ = {'HTTP_X_STORAGE_TOKEN': value} + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual(value, ctx.auth_token) + + environ = {'HTTP_X_TENANT': value} + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual(value, ctx.tenant) + + environ = {'HTTP_X_ROLE': value} + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual([value], ctx.roles) + + def test_from_environ_deprecated_precendence(self): + old = uuid.uuid4().hex + new = uuid.uuid4().hex + override = uuid.uuid4().hex + + environ = {'HTTP_X_USER': old, + 'HTTP_X_USER_ID': new} + + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual(ctx.user, new) + + ctx = context.RequestContext.from_environ(environ=environ, + user=override) + self.assertEqual(ctx.user, override) + + environ = {'HTTP_X_TENANT': old, + 'HTTP_X_PROJECT_ID': new} + + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual(ctx.tenant, new) + + ctx = context.RequestContext.from_environ(environ=environ, + tenant=override) + self.assertEqual(ctx.tenant, override) + def test_from_function_and_args(self): ctx = context.RequestContext(user="user1") arg = [] From 0511e11287c6c554eac98fc725738baf6290c52e Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Wed, 4 May 2016 18:56:10 +1000 Subject: [PATCH 2/3] Strip roles in from_environ If somehow whitespace gets into the roles coming from headers we should remove it and only save the actual role name. This is not possible coming from auth_token middleware but is tested by some services and is simple to support here. Change-Id: I11ac3959d8f8b233c8785671d7a59263a4dc36df --- oslo_context/context.py | 3 ++- oslo_context/tests/test_context.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/oslo_context/context.py b/oslo_context/context.py index bfbedcb..d4902ad 100644 --- a/oslo_context/context.py +++ b/oslo_context/context.py @@ -173,7 +173,8 @@ class RequestContext(object): if 'roles' not in kwargs: roles = environ.get('HTTP_X_ROLES', environ.get('HTTP_X_ROLE')) - kwargs['roles'] = roles.split(',') if roles else [] + roles = [r.strip() for r in roles.split(',')] if roles else [] + kwargs['roles'] = roles return cls(**kwargs) diff --git a/oslo_context/tests/test_context.py b/oslo_context/tests/test_context.py index f2a095a..2165608 100644 --- a/oslo_context/tests/test_context.py +++ b/oslo_context/tests/test_context.py @@ -209,6 +209,11 @@ class ContextTest(test_base.BaseTestCase): tenant=override) self.assertEqual(ctx.tenant, override) + def test_from_environ_strip_roles(self): + environ = {'HTTP_X_ROLES': ' abc\t,\ndef\n,ghi\n\n'} + ctx = context.RequestContext.from_environ(environ=environ) + self.assertEqual(['abc', 'def', 'ghi'], ctx.roles) + def test_from_function_and_args(self): ctx = context.RequestContext(user="user1") arg = [] From cf33c028e9795ba26c1216e19d2ed50f8f6de914 Mon Sep 17 00:00:00 2001 From: "ChangBo Guo(gcb)" Date: Wed, 11 May 2016 19:26:50 +0800 Subject: [PATCH 3/3] Trivial: ignore openstack/common in flake8 exclude list The directory openstack/common doesn't exist any more. So remove it from flake8 exclude list. Change-Id: I3de6bac0c10f194108e0e77db1bb21a7421c6cf6 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index d43baa6..c44a34c 100644 --- a/tox.ini +++ b/tox.ini @@ -24,7 +24,7 @@ commands = python setup.py test --coverage --coverage-package-name=oslo_context show-source = True ignore = E123,E125,H803 -exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build +exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build [hacking] import_exceptions =