xLO bug with auth tokens expiring during download.
Just put SLO and DLO after any auth middleware. This works because when the request goes through that middleware in the pipeline the authentication takes place: validation of the token, setting up who the user is, and setting the authorization call back. Each subrequest made for the segments will be subjected to that authorization call back which verifies the user has access to the individual segments. To get this to work with keystone, the keystone identity is set up during __call__ and applied to the authorize function using a functools.partial. When the authorize function is later called from the environ by the proxy server the idenity that was set up when the request passed through the auth middleware is used, not what can be pulled out of the possibly altered state of the request's environment. DocImpact fixes bug: 1315133 Change-Id: I7827dd2d9dfbb3c6424773fb2891355d47e372ba
This commit is contained in:
parent
b519424b91
commit
ab510952ef
@ -70,7 +70,7 @@
|
|||||||
# eventlet_debug = false
|
# eventlet_debug = false
|
||||||
|
|
||||||
[pipeline:main]
|
[pipeline:main]
|
||||||
pipeline = catch_errors gatekeeper healthcheck proxy-logging cache container_sync bulk tempurl slo dlo ratelimit tempauth container-quotas account-quotas proxy-logging proxy-server
|
pipeline = catch_errors gatekeeper healthcheck proxy-logging cache container_sync bulk tempurl ratelimit tempauth container-quotas account-quotas slo dlo proxy-logging proxy-server
|
||||||
|
|
||||||
[app:proxy-server]
|
[app:proxy-server]
|
||||||
use = egg:swift#proxy
|
use = egg:swift#proxy
|
||||||
@ -521,7 +521,7 @@ use = egg:swift#bulk
|
|||||||
[filter:container-quotas]
|
[filter:container-quotas]
|
||||||
use = egg:swift#container_quotas
|
use = egg:swift#container_quotas
|
||||||
|
|
||||||
# Note: Put before both ratelimit and auth in the pipeline.
|
# Note: Put after auth and staticweb in the pipeline.
|
||||||
[filter:slo]
|
[filter:slo]
|
||||||
use = egg:swift#slo
|
use = egg:swift#slo
|
||||||
# max_manifest_segments = 1000
|
# max_manifest_segments = 1000
|
||||||
@ -538,8 +538,7 @@ use = egg:swift#slo
|
|||||||
# Time limit on GET requests (seconds)
|
# Time limit on GET requests (seconds)
|
||||||
# max_get_time = 86400
|
# max_get_time = 86400
|
||||||
|
|
||||||
# Note: Put before both ratelimit and auth in the pipeline, but after
|
# Note: Put after auth and staticweb in the pipeline.
|
||||||
# gatekeeper, catch_errors, and proxy_logging (the first instance).
|
|
||||||
# If you don't put it in the pipeline, it will be inserted for you.
|
# If you don't put it in the pipeline, it will be inserted for you.
|
||||||
[filter:dlo]
|
[filter:dlo]
|
||||||
use = egg:swift#dlo
|
use = egg:swift#dlo
|
||||||
|
@ -16,6 +16,7 @@ from swift.common import utils as swift_utils
|
|||||||
from swift.common.middleware import acl as swift_acl
|
from swift.common.middleware import acl as swift_acl
|
||||||
from swift.common.swob import HTTPNotFound, HTTPForbidden, HTTPUnauthorized
|
from swift.common.swob import HTTPNotFound, HTTPForbidden, HTTPUnauthorized
|
||||||
from swift.common.utils import register_swift_info
|
from swift.common.utils import register_swift_info
|
||||||
|
import functools
|
||||||
|
|
||||||
|
|
||||||
class KeystoneAuth(object):
|
class KeystoneAuth(object):
|
||||||
@ -103,7 +104,9 @@ class KeystoneAuth(object):
|
|||||||
self.logger.debug('Using identity: %r', identity)
|
self.logger.debug('Using identity: %r', identity)
|
||||||
environ['keystone.identity'] = identity
|
environ['keystone.identity'] = identity
|
||||||
environ['REMOTE_USER'] = identity.get('tenant')
|
environ['REMOTE_USER'] = identity.get('tenant')
|
||||||
environ['swift.authorize'] = self.authorize
|
env_identity = self._integral_keystone_identity(environ)
|
||||||
|
environ['swift.authorize'] = functools.partial(
|
||||||
|
self.authorize, env_identity)
|
||||||
user_roles = (r.lower() for r in identity.get('roles', []))
|
user_roles = (r.lower() for r in identity.get('roles', []))
|
||||||
if self.reseller_admin_role in user_roles:
|
if self.reseller_admin_role in user_roles:
|
||||||
environ['reseller_request'] = True
|
environ['reseller_request'] = True
|
||||||
@ -177,9 +180,7 @@ class KeystoneAuth(object):
|
|||||||
return s
|
return s
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def authorize(self, req):
|
def authorize(self, env_identity, req):
|
||||||
env = req.environ
|
|
||||||
env_identity = self._integral_keystone_identity(env)
|
|
||||||
tenant_id, tenant_name = env_identity['tenant']
|
tenant_id, tenant_name = env_identity['tenant']
|
||||||
user_id, user_name = env_identity['user']
|
user_id, user_name = env_identity['user']
|
||||||
referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None))
|
referrers, roles = swift_acl.parse_acl(getattr(req, 'acl', None))
|
||||||
|
@ -56,10 +56,11 @@ required_filters = [
|
|||||||
{'name': 'catch_errors'},
|
{'name': 'catch_errors'},
|
||||||
{'name': 'gatekeeper',
|
{'name': 'gatekeeper',
|
||||||
'after_fn': lambda pipe: (['catch_errors']
|
'after_fn': lambda pipe: (['catch_errors']
|
||||||
if pipe.startswith("catch_errors")
|
if pipe.startswith('catch_errors')
|
||||||
else [])},
|
else [])},
|
||||||
{'name': 'dlo', 'after_fn': lambda _junk: ['catch_errors', 'gatekeeper',
|
{'name': 'dlo', 'after_fn': lambda _junk: [
|
||||||
'proxy_logging']}]
|
'staticweb', 'tempauth', 'keystoneauth',
|
||||||
|
'catch_errors', 'gatekeeper', 'proxy_logging']}]
|
||||||
|
|
||||||
|
|
||||||
class Application(object):
|
class Application(object):
|
||||||
|
@ -214,7 +214,9 @@ class TestAuthorize(unittest.TestCase):
|
|||||||
default_env.update(env)
|
default_env.update(env)
|
||||||
req = self._make_request(path, headers=headers, environ=default_env)
|
req = self._make_request(path, headers=headers, environ=default_env)
|
||||||
req.acl = acl
|
req.acl = acl
|
||||||
result = self.test_auth.authorize(req)
|
|
||||||
|
env_identity = self.test_auth._integral_keystone_identity(req.environ)
|
||||||
|
result = self.test_auth.authorize(env_identity, req)
|
||||||
|
|
||||||
# if we have requested an exception but nothing came back then
|
# if we have requested an exception but nothing came back then
|
||||||
if exception and not result:
|
if exception and not result:
|
||||||
@ -398,5 +400,20 @@ class TestAuthorize(unittest.TestCase):
|
|||||||
env={'REQUEST_METHOD': 'DELETE'})
|
env={'REQUEST_METHOD': 'DELETE'})
|
||||||
self.assertEqual(bool(req.environ.get('swift_owner')), True)
|
self.assertEqual(bool(req.environ.get('swift_owner')), True)
|
||||||
|
|
||||||
|
def test_identity_set_up_at_call(self):
|
||||||
|
def fake_start_response(*args, **kwargs):
|
||||||
|
pass
|
||||||
|
the_env = self._get_identity(
|
||||||
|
tenant_id='test', roles=['reselleradmin'])
|
||||||
|
self.test_auth(the_env, fake_start_response)
|
||||||
|
|
||||||
|
subreq = Request.blank(
|
||||||
|
'/v1/%s/c/o' % self.test_auth._get_account_for_tenant('test'))
|
||||||
|
subreq.environ.update(
|
||||||
|
self._get_identity(tenant_id='test', roles=['got_erased']))
|
||||||
|
|
||||||
|
authorize_resp = the_env['swift.authorize'](subreq)
|
||||||
|
self.assertEqual(authorize_resp, None)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user