We don't have to keep the retrieved token anymore
Since the change in s3_token_middleware to retrieve the auth info from keystone directly, now, we don't need to have any tokens provided by keystone in the request header as X-Auth-Token. Note that this makes the pipeline ordering change documented in the related changes mandatory, even when working with a v2 Keystone server. Change-Id: I7c251a758dfc1fedb3fb61e351de305b431afa79 Related-Change: I21e38884a2aefbb94b76c76deccd815f01db7362 Related-Change: Ic9af387b9192f285f0f486e7171eefb23968007e
This commit is contained in:
parent
032cf3b3b4
commit
4aa71aa25c
@ -534,7 +534,6 @@ class S3Request(swob.Request):
|
|||||||
'string_to_sign': self.string_to_sign,
|
'string_to_sign': self.string_to_sign,
|
||||||
'check_signature': self.check_signature,
|
'check_signature': self.check_signature,
|
||||||
}
|
}
|
||||||
self.token = None
|
|
||||||
self.account = None
|
self.account = None
|
||||||
self.user_id = None
|
self.user_id = None
|
||||||
self.slo_enabled = slo_enabled
|
self.slo_enabled = slo_enabled
|
||||||
@ -1134,8 +1133,6 @@ class S3Request(swob.Request):
|
|||||||
if method is not None:
|
if method is not None:
|
||||||
env['REQUEST_METHOD'] = method
|
env['REQUEST_METHOD'] = method
|
||||||
|
|
||||||
env['HTTP_X_AUTH_TOKEN'] = self.token
|
|
||||||
|
|
||||||
if obj:
|
if obj:
|
||||||
path = '/v1/%s/%s/%s' % (account, container, obj)
|
path = '/v1/%s/%s/%s' % (account, container, obj)
|
||||||
elif container:
|
elif container:
|
||||||
@ -1327,7 +1324,7 @@ class S3Request(swob.Request):
|
|||||||
except swob.HTTPException as err:
|
except swob.HTTPException as err:
|
||||||
sw_resp = err
|
sw_resp = err
|
||||||
else:
|
else:
|
||||||
# reuse account and tokens
|
# reuse account
|
||||||
_, self.account, _ = split_path(sw_resp.environ['PATH_INFO'],
|
_, self.account, _ = split_path(sw_resp.environ['PATH_INFO'],
|
||||||
2, 3, True)
|
2, 3, True)
|
||||||
|
|
||||||
@ -1337,10 +1334,11 @@ class S3Request(swob.Request):
|
|||||||
if not self.user_id:
|
if not self.user_id:
|
||||||
if 'HTTP_X_USER_NAME' in sw_resp.environ:
|
if 'HTTP_X_USER_NAME' in sw_resp.environ:
|
||||||
# keystone
|
# keystone
|
||||||
self.user_id = \
|
self.user_id = "%s:%s" % (
|
||||||
utf8encode("%s:%s" %
|
sw_resp.environ['HTTP_X_TENANT_NAME'],
|
||||||
(sw_resp.environ['HTTP_X_TENANT_NAME'],
|
sw_resp.environ['HTTP_X_USER_NAME'])
|
||||||
sw_resp.environ['HTTP_X_USER_NAME']))
|
if six.PY2 and not isinstance(self.user_id, bytes):
|
||||||
|
self.user_id = self.user_id.encode('utf8')
|
||||||
else:
|
else:
|
||||||
# tempauth
|
# tempauth
|
||||||
self.user_id = self.access_key
|
self.user_id = self.access_key
|
||||||
@ -1501,8 +1499,8 @@ class S3AclRequest(S3Request):
|
|||||||
# keystone
|
# keystone
|
||||||
self.user_id = "%s:%s" % (sw_resp.environ['HTTP_X_TENANT_NAME'],
|
self.user_id = "%s:%s" % (sw_resp.environ['HTTP_X_TENANT_NAME'],
|
||||||
sw_resp.environ['HTTP_X_USER_NAME'])
|
sw_resp.environ['HTTP_X_USER_NAME'])
|
||||||
self.user_id = utf8encode(self.user_id)
|
if six.PY2 and not isinstance(self.user_id, bytes):
|
||||||
self.token = sw_resp.environ.get('HTTP_X_AUTH_TOKEN')
|
self.user_id = self.user_id.encode('utf8')
|
||||||
else:
|
else:
|
||||||
# tempauth
|
# tempauth
|
||||||
self.user_id = self.access_key
|
self.user_id = self.access_key
|
||||||
|
@ -111,10 +111,7 @@ def parse_v2_response(token):
|
|||||||
'X-Project-Id': access_info['token']['tenant']['id'],
|
'X-Project-Id': access_info['token']['tenant']['id'],
|
||||||
'X-Project-Name': access_info['token']['tenant']['name'],
|
'X-Project-Name': access_info['token']['tenant']['name'],
|
||||||
}
|
}
|
||||||
return (
|
return headers, access_info['token']['tenant']
|
||||||
headers,
|
|
||||||
access_info['token'].get('id'),
|
|
||||||
access_info['token']['tenant'])
|
|
||||||
|
|
||||||
|
|
||||||
def parse_v3_response(token):
|
def parse_v3_response(token):
|
||||||
@ -134,7 +131,7 @@ def parse_v3_response(token):
|
|||||||
'X-Project-Domain-Id': token['project']['domain']['id'],
|
'X-Project-Domain-Id': token['project']['domain']['id'],
|
||||||
'X-Project-Domain-Name': token['project']['domain']['name'],
|
'X-Project-Domain-Name': token['project']['domain']['name'],
|
||||||
}
|
}
|
||||||
return headers, None, token['project']
|
return headers, token['project']
|
||||||
|
|
||||||
|
|
||||||
class S3Token(object):
|
class S3Token(object):
|
||||||
@ -308,7 +305,13 @@ class S3Token(object):
|
|||||||
if memcache_client:
|
if memcache_client:
|
||||||
cached_auth_data = memcache_client.get(memcache_token_key)
|
cached_auth_data = memcache_client.get(memcache_token_key)
|
||||||
if cached_auth_data:
|
if cached_auth_data:
|
||||||
headers, token_id, tenant, secret = cached_auth_data
|
if len(cached_auth_data) == 4:
|
||||||
|
# Old versions of swift may have cached token, too,
|
||||||
|
# but we don't need it
|
||||||
|
headers, _token, tenant, secret = cached_auth_data
|
||||||
|
else:
|
||||||
|
headers, tenant, secret = cached_auth_data
|
||||||
|
|
||||||
if s3_auth_details['check_signature'](secret):
|
if s3_auth_details['check_signature'](secret):
|
||||||
self._logger.debug("Cached creds valid")
|
self._logger.debug("Cached creds valid")
|
||||||
else:
|
else:
|
||||||
@ -348,9 +351,9 @@ class S3Token(object):
|
|||||||
try:
|
try:
|
||||||
token = resp.json()
|
token = resp.json()
|
||||||
if 'access' in token:
|
if 'access' in token:
|
||||||
headers, token_id, tenant = parse_v2_response(token)
|
headers, tenant = parse_v2_response(token)
|
||||||
elif 'token' in token:
|
elif 'token' in token:
|
||||||
headers, token_id, tenant = parse_v3_response(token)
|
headers, tenant = parse_v3_response(token)
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
if memcache_client:
|
if memcache_client:
|
||||||
@ -363,7 +366,7 @@ class S3Token(object):
|
|||||||
access=access)
|
access=access)
|
||||||
memcache_client.set(
|
memcache_client.set(
|
||||||
memcache_token_key,
|
memcache_token_key,
|
||||||
(headers, token_id, tenant, cred_ref.secret),
|
(headers, tenant, cred_ref.secret),
|
||||||
time=self._secret_cache_duration)
|
time=self._secret_cache_duration)
|
||||||
self._logger.debug("Cached keystone credentials")
|
self._logger.debug("Cached keystone credentials")
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -391,7 +394,6 @@ class S3Token(object):
|
|||||||
environ, start_response)
|
environ, start_response)
|
||||||
|
|
||||||
req.headers.update(headers)
|
req.headers.update(headers)
|
||||||
req.headers['X-Auth-Token'] = token_id
|
|
||||||
tenant_to_connect = force_tenant or tenant['id']
|
tenant_to_connect = force_tenant or tenant['id']
|
||||||
if six.PY2 and isinstance(tenant_to_connect, six.text_type):
|
if six.PY2 and isinstance(tenant_to_connect, six.text_type):
|
||||||
tenant_to_connect = tenant_to_connect.encode('utf-8')
|
tenant_to_connect = tenant_to_connect.encode('utf-8')
|
||||||
|
@ -232,6 +232,8 @@ class Owner(object):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, id, name):
|
def __init__(self, id, name):
|
||||||
self.id = id
|
self.id = id
|
||||||
|
if not (name is None or isinstance(name, six.string_types)):
|
||||||
|
raise TypeError('name must be a string or None')
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
|
|
||||||
|
@ -538,8 +538,8 @@ class SwiftHttpProxiedProtocol(SwiftHttpProtocol):
|
|||||||
|
|
||||||
return SwiftHttpProtocol.handle(self)
|
return SwiftHttpProtocol.handle(self)
|
||||||
|
|
||||||
def get_environ(self):
|
def get_environ(self, *args, **kwargs):
|
||||||
environ = SwiftHttpProtocol.get_environ(self)
|
environ = SwiftHttpProtocol.get_environ(self, *args, **kwargs)
|
||||||
if self.proxy_address:
|
if self.proxy_address:
|
||||||
environ['SERVER_ADDR'] = self.proxy_address[0]
|
environ['SERVER_ADDR'] = self.proxy_address[0]
|
||||||
environ['SERVER_PORT'] = self.proxy_address[1]
|
environ['SERVER_PORT'] = self.proxy_address[1]
|
||||||
|
@ -22,7 +22,6 @@ import hashlib
|
|||||||
import mock
|
import mock
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
import copy
|
|
||||||
import six
|
import six
|
||||||
from six.moves.urllib.parse import unquote, quote
|
from six.moves.urllib.parse import unquote, quote
|
||||||
|
|
||||||
@ -34,6 +33,7 @@ from swift.common.swob import Request
|
|||||||
from keystonemiddleware.auth_token import AuthProtocol
|
from keystonemiddleware.auth_token import AuthProtocol
|
||||||
from keystoneauth1.access import AccessInfoV2
|
from keystoneauth1.access import AccessInfoV2
|
||||||
|
|
||||||
|
from test.unit import debug_logger
|
||||||
from test.unit.common.middleware.s3api import S3ApiTestCase
|
from test.unit.common.middleware.s3api import S3ApiTestCase
|
||||||
from test.unit.common.middleware.s3api.helpers import FakeSwift
|
from test.unit.common.middleware.s3api.helpers import FakeSwift
|
||||||
from test.unit.common.middleware.s3api.test_s3token import \
|
from test.unit.common.middleware.s3api.test_s3token import \
|
||||||
@ -335,7 +335,7 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
self.assertEqual(status.split()[0], '200', body)
|
self.assertEqual(status.split()[0], '200', body)
|
||||||
for _, _, headers in self.swift.calls_with_headers:
|
for _, _, headers in self.swift.calls_with_headers:
|
||||||
self.assertNotIn('Authorization', headers)
|
self.assertNotIn('Authorization', headers)
|
||||||
self.assertIsNone(headers['X-Auth-Token'])
|
self.assertNotIn('X-Auth-Token', headers)
|
||||||
|
|
||||||
def test_signed_urls_v4_bad_credential(self):
|
def test_signed_urls_v4_bad_credential(self):
|
||||||
def test(credential, message, extra=b''):
|
def test(credential, message, extra=b''):
|
||||||
@ -767,7 +767,7 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
self.assertEqual(status.split()[0], '200', body)
|
self.assertEqual(status.split()[0], '200', body)
|
||||||
for _, _, headers in self.swift.calls_with_headers:
|
for _, _, headers in self.swift.calls_with_headers:
|
||||||
self.assertEqual(authz_header, headers['Authorization'])
|
self.assertEqual(authz_header, headers['Authorization'])
|
||||||
self.assertIsNone(headers['X-Auth-Token'])
|
self.assertNotIn('X-Auth-Token', headers)
|
||||||
|
|
||||||
def test_signature_v4_no_date(self):
|
def test_signature_v4_no_date(self):
|
||||||
environ = {
|
environ = {
|
||||||
@ -1096,6 +1096,7 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
self.s3_token = S3Token(
|
self.s3_token = S3Token(
|
||||||
self.keystone_auth, {'auth_uri': 'https://fakehost/identity'})
|
self.keystone_auth, {'auth_uri': 'https://fakehost/identity'})
|
||||||
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
||||||
|
self.s3api.logger = debug_logger()
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/bucket',
|
'/bucket',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
@ -1122,6 +1123,7 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
self.s3_token = S3Token(
|
self.s3_token = S3Token(
|
||||||
self.keystone_auth, {'auth_uri': 'https://fakehost/identity'})
|
self.keystone_auth, {'auth_uri': 'https://fakehost/identity'})
|
||||||
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
||||||
|
self.s3api.logger = debug_logger()
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/bucket',
|
'/bucket',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
@ -1150,6 +1152,7 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
self.s3_token = S3Token(
|
self.s3_token = S3Token(
|
||||||
self.auth_token, {'auth_uri': 'https://fakehost/identity'})
|
self.auth_token, {'auth_uri': 'https://fakehost/identity'})
|
||||||
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
||||||
|
self.s3api.logger = debug_logger()
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/bucket',
|
'/bucket',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
@ -1162,6 +1165,8 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
with patch.object(self.s3_token, '_json_request') as mock_req:
|
with patch.object(self.s3_token, '_json_request') as mock_req:
|
||||||
with patch.object(self.auth_token,
|
with patch.object(self.auth_token,
|
||||||
'_do_fetch_token') as mock_fetch:
|
'_do_fetch_token') as mock_fetch:
|
||||||
|
# sanity check
|
||||||
|
self.assertIn('id', GOOD_RESPONSE_V2['access']['token'])
|
||||||
mock_resp = requests.Response()
|
mock_resp = requests.Response()
|
||||||
mock_resp._content = json.dumps(
|
mock_resp._content = json.dumps(
|
||||||
GOOD_RESPONSE_V2).encode('ascii')
|
GOOD_RESPONSE_V2).encode('ascii')
|
||||||
@ -1174,21 +1179,28 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
mock_fetch.return_value = (MagicMock(), mock_access_info)
|
mock_fetch.return_value = (MagicMock(), mock_access_info)
|
||||||
|
|
||||||
status, headers, body = self.call_s3api(req)
|
status, headers, body = self.call_s3api(req)
|
||||||
self.assertEqual(body, b'')
|
# Even though s3token got a token back from keystone, we drop
|
||||||
|
# it on the floor, resulting in a 401 Unauthorized at
|
||||||
|
# `swift.common.middleware.keystoneauth` because
|
||||||
|
# keystonemiddleware's auth_token strips out all auth headers,
|
||||||
|
# significantly 'X-Identity-Status'. Without a token, it then
|
||||||
|
# sets 'X-Identity-Status: Invalid' and never contacts
|
||||||
|
# Keystone.
|
||||||
|
self.assertEqual('403 Forbidden', status)
|
||||||
self.assertEqual(1, mock_req.call_count)
|
self.assertEqual(1, mock_req.call_count)
|
||||||
# With X-Auth-Token, auth_token will call _do_fetch_token to
|
# it never even tries to contact keystone
|
||||||
# connect to keystone in auth_token, again
|
self.assertEqual(0, mock_fetch.call_count)
|
||||||
self.assertEqual(1, mock_fetch.call_count)
|
|
||||||
|
|
||||||
def test_s3api_with_s3_token_no_pass_token_to_auth_token(self):
|
def test_s3api_with_only_s3_token_in_s3acl(self):
|
||||||
self.swift = FakeSwift()
|
self.swift = FakeSwift()
|
||||||
self.keystone_auth = KeystoneAuth(
|
self.keystone_auth = KeystoneAuth(
|
||||||
self.swift, {'operator_roles': 'swift-user'})
|
self.swift, {'operator_roles': 'swift-user'})
|
||||||
self.auth_token = AuthProtocol(
|
|
||||||
self.keystone_auth, {'delay_auth_decision': 'True'})
|
|
||||||
self.s3_token = S3Token(
|
self.s3_token = S3Token(
|
||||||
self.auth_token, {'auth_uri': 'https://fakehost/identity'})
|
self.keystone_auth, {'auth_uri': 'https://fakehost/identity'})
|
||||||
|
|
||||||
|
self.conf['s3_acl'] = True
|
||||||
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
self.s3api = S3ApiMiddleware(self.s3_token, self.conf)
|
||||||
|
self.s3api.logger = debug_logger()
|
||||||
req = Request.blank(
|
req = Request.blank(
|
||||||
'/bucket',
|
'/bucket',
|
||||||
environ={'REQUEST_METHOD': 'PUT'},
|
environ={'REQUEST_METHOD': 'PUT'},
|
||||||
@ -1196,41 +1208,21 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||||||
'Date': self.get_date_header()})
|
'Date': self.get_date_header()})
|
||||||
self.swift.register('PUT', '/v1/AUTH_TENANT_ID/bucket',
|
self.swift.register('PUT', '/v1/AUTH_TENANT_ID/bucket',
|
||||||
swob.HTTPCreated, {}, None)
|
swob.HTTPCreated, {}, None)
|
||||||
self.swift.register('HEAD', '/v1/AUTH_TENANT_ID',
|
# For now, s3 acl commits the bucket owner acl via POST
|
||||||
swob.HTTPOk, {}, None)
|
# after PUT container so we need to register the resposne here
|
||||||
|
self.swift.register('POST', '/v1/AUTH_TENANT_ID/bucket',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
self.swift.register('TEST', '/v1/AUTH_TENANT_ID',
|
||||||
|
swob.HTTPMethodNotAllowed, {}, None)
|
||||||
with patch.object(self.s3_token, '_json_request') as mock_req:
|
with patch.object(self.s3_token, '_json_request') as mock_req:
|
||||||
with patch.object(self.auth_token,
|
mock_resp = requests.Response()
|
||||||
'_do_fetch_token') as mock_fetch:
|
mock_resp._content = json.dumps(GOOD_RESPONSE_V2).encode('ascii')
|
||||||
mock_resp = requests.Response()
|
mock_resp.status_code = 201
|
||||||
no_token_id_good_resp = copy.deepcopy(GOOD_RESPONSE_V2)
|
mock_req.return_value = mock_resp
|
||||||
# delete token id
|
|
||||||
del no_token_id_good_resp['access']['token']['id']
|
|
||||||
mock_resp._content = json.dumps(
|
|
||||||
no_token_id_good_resp).encode('ascii')
|
|
||||||
mock_resp.status_code = 201
|
|
||||||
mock_req.return_value = mock_resp
|
|
||||||
|
|
||||||
mock_access_info = AccessInfoV2(GOOD_RESPONSE_V2)
|
status, headers, body = self.call_s3api(req)
|
||||||
mock_access_info.will_expire_soon = \
|
self.assertEqual(body, b'')
|
||||||
lambda stale_duration: False
|
self.assertEqual(1, mock_req.call_count)
|
||||||
mock_fetch.return_value = (MagicMock(), mock_access_info)
|
|
||||||
|
|
||||||
status, headers, body = self.call_s3api(req)
|
|
||||||
# No token provided from keystone result in 401 Unauthorized
|
|
||||||
# at `swift.common.middleware.keystoneauth` because auth_token
|
|
||||||
# will remove all auth headers including 'X-Identity-Status'[1]
|
|
||||||
# and then, set X-Identity-Status: Invalid at [2]
|
|
||||||
#
|
|
||||||
# 1: https://github.com/openstack/keystonemiddleware/blob/
|
|
||||||
# master/keystonemiddleware/auth_token/__init__.py#L620
|
|
||||||
# 2: https://github.com/openstack/keystonemiddleware/blob/
|
|
||||||
# master/keystonemiddleware/auth_token/__init__.py#L627-L629
|
|
||||||
|
|
||||||
self.assertEqual('403 Forbidden', status)
|
|
||||||
self.assertEqual(1, mock_req.call_count)
|
|
||||||
# if no token provided from keystone, we can skip the call to
|
|
||||||
# fetch the token
|
|
||||||
self.assertEqual(0, mock_fetch.call_count)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -249,9 +249,11 @@ class TestRequest(S3ApiTestCase):
|
|||||||
m_swift_resp.return_value = FakeSwiftResponse()
|
m_swift_resp.return_value = FakeSwiftResponse()
|
||||||
s3_req = S3AclRequest(req.environ, MagicMock())
|
s3_req = S3AclRequest(req.environ, MagicMock())
|
||||||
self.assertNotIn('s3api.auth_details', s3_req.environ)
|
self.assertNotIn('s3api.auth_details', s3_req.environ)
|
||||||
self.assertEqual(s3_req.token, 'token')
|
|
||||||
|
|
||||||
def test_to_swift_req_Authorization_not_exist_in_swreq(self):
|
def test_to_swift_req_Authorization_not_exist_in_swreq(self):
|
||||||
|
# the difference from
|
||||||
|
# test_authenticate_delete_Authorization_from_s3req_headers above is
|
||||||
|
# this method asserts *to_swift_req* method.
|
||||||
container = 'bucket'
|
container = 'bucket'
|
||||||
obj = 'obj'
|
obj = 'obj'
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
@ -264,9 +266,12 @@ class TestRequest(S3ApiTestCase):
|
|||||||
|
|
||||||
m_swift_resp.return_value = FakeSwiftResponse()
|
m_swift_resp.return_value = FakeSwiftResponse()
|
||||||
s3_req = S3AclRequest(req.environ, MagicMock())
|
s3_req = S3AclRequest(req.environ, MagicMock())
|
||||||
|
# Yes, we *want* to assert this
|
||||||
sw_req = s3_req.to_swift_req(method, container, obj)
|
sw_req = s3_req.to_swift_req(method, container, obj)
|
||||||
|
# So since the result of S3AclRequest init tests and with this
|
||||||
|
# result to_swift_req doesn't add Authorization header and token
|
||||||
self.assertNotIn('s3api.auth_details', sw_req.environ)
|
self.assertNotIn('s3api.auth_details', sw_req.environ)
|
||||||
self.assertEqual(sw_req.headers['X-Auth-Token'], 'token')
|
self.assertNotIn('X-Auth-Token', sw_req.headers)
|
||||||
|
|
||||||
def test_to_swift_req_subrequest_proxy_access_log(self):
|
def test_to_swift_req_subrequest_proxy_access_log(self):
|
||||||
container = 'bucket'
|
container = 'bucket'
|
||||||
|
@ -196,11 +196,11 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
|
|||||||
self.middleware(req.environ, self.start_fake_response)
|
self.middleware(req.environ, self.start_fake_response)
|
||||||
self.assertEqual(self.response_status, 200)
|
self.assertEqual(self.response_status, 200)
|
||||||
|
|
||||||
def _assert_authorized(self, req, expect_token=True,
|
def _assert_authorized(self, req, account_path='/v1/AUTH_TENANT_ID/'):
|
||||||
account_path='/v1/AUTH_TENANT_ID/'):
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
req.path.startswith(account_path),
|
req.path.startswith(account_path),
|
||||||
'%r does not start with %r' % (req.path, account_path))
|
'%r does not start with %r' % (req.path, account_path))
|
||||||
|
self.assertNotIn('X-Auth-Token', req.headers)
|
||||||
expected_headers = {
|
expected_headers = {
|
||||||
'X-Identity-Status': 'Confirmed',
|
'X-Identity-Status': 'Confirmed',
|
||||||
'X-Roles': 'swift-user,_member_',
|
'X-Roles': 'swift-user,_member_',
|
||||||
@ -210,12 +210,8 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
|
|||||||
'X-Tenant-Name': 'TENANT_NAME',
|
'X-Tenant-Name': 'TENANT_NAME',
|
||||||
'X-Project-Id': 'TENANT_ID',
|
'X-Project-Id': 'TENANT_ID',
|
||||||
'X-Project-Name': 'TENANT_NAME',
|
'X-Project-Name': 'TENANT_NAME',
|
||||||
'X-Auth-Token': 'TOKEN_ID',
|
|
||||||
}
|
}
|
||||||
for header, value in expected_headers.items():
|
for header, value in expected_headers.items():
|
||||||
if header == 'X-Auth-Token' and not expect_token:
|
|
||||||
self.assertNotIn(header, req.headers)
|
|
||||||
continue
|
|
||||||
self.assertIn(header, req.headers)
|
self.assertIn(header, req.headers)
|
||||||
self.assertEqual(value, req.headers[header])
|
self.assertEqual(value, req.headers[header])
|
||||||
# WSGI wants native strings for headers
|
# WSGI wants native strings for headers
|
||||||
@ -253,7 +249,7 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
|
|||||||
'string_to_sign': u'token',
|
'string_to_sign': u'token',
|
||||||
}
|
}
|
||||||
req.get_response(self.middleware)
|
req.get_response(self.middleware)
|
||||||
self._assert_authorized(req, expect_token=False)
|
self._assert_authorized(req)
|
||||||
|
|
||||||
def test_authorized_bytes(self):
|
def test_authorized_bytes(self):
|
||||||
req = Request.blank('/v1/AUTH_cfa/c/o')
|
req = Request.blank('/v1/AUTH_cfa/c/o')
|
||||||
@ -533,7 +529,7 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
|
|||||||
|
|
||||||
cache = MOCK_CACHE_FROM_ENV.return_value
|
cache = MOCK_CACHE_FROM_ENV.return_value
|
||||||
|
|
||||||
fake_cache_response = ({}, 'token_id', {'id': 'tenant_id'}, 'secret')
|
fake_cache_response = ({}, {'id': 'tenant_id'}, 'secret')
|
||||||
cache.get.return_value = fake_cache_response
|
cache.get.return_value = fake_cache_response
|
||||||
|
|
||||||
MOCK_REQUEST.return_value = TestResponse({
|
MOCK_REQUEST.return_value = TestResponse({
|
||||||
@ -600,8 +596,7 @@ class S3TokenMiddlewareTestGood(S3TokenMiddlewareTestBase):
|
|||||||
|
|
||||||
self.assertTrue(MOCK_REQUEST.called)
|
self.assertTrue(MOCK_REQUEST.called)
|
||||||
tenant = GOOD_RESPONSE_V2['access']['token']['tenant']
|
tenant = GOOD_RESPONSE_V2['access']['token']['tenant']
|
||||||
token = GOOD_RESPONSE_V2['access']['token']['id']
|
expected_cache = (expected_headers, tenant, 'secret')
|
||||||
expected_cache = (expected_headers, token, tenant, 'secret')
|
|
||||||
cache.set.assert_called_once_with('s3secret/access', expected_cache,
|
cache.set.assert_called_once_with('s3secret/access', expected_cache,
|
||||||
time=20)
|
time=20)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user