Merge "s3api: Stop mangling Authorization header for v4 signatures"
This commit is contained in:
commit
7b1679b9b2
|
@ -491,15 +491,6 @@ class S3Request(swob.Request):
|
|||
self.user_id = None
|
||||
self.slo_enabled = slo_enabled
|
||||
|
||||
# NOTE(andrey-mp): substitute authorization header for next modules
|
||||
# in pipeline (s3token). it uses this and X-Auth-Token in specific
|
||||
# format.
|
||||
# (kota_): yeah, the reason we need this is s3token only supports
|
||||
# v2 like header consists of AWS access:signature. Since the commit
|
||||
# b626a3ca86e467fc7564eac236b9ee2efd49bdcc, the s3token is in swift3
|
||||
# repo so probably we need to change s3token to support v4 format.
|
||||
self.headers['Authorization'] = 'AWS %s:%s' % (
|
||||
self.access_key, self.signature)
|
||||
# Avoids that swift.swob.Response replaces Location header value
|
||||
# by full URL when absolute path given. See swift.swob for more detail.
|
||||
self.environ['swift.leave_relative_location'] = True
|
||||
|
@ -1460,7 +1451,6 @@ class S3AclRequest(S3Request):
|
|||
|
||||
# Need to skip S3 authorization on subsequent requests to prevent
|
||||
# overwriting the account in PATH_INFO
|
||||
del self.headers['Authorization']
|
||||
del self.environ['s3api.auth_details']
|
||||
|
||||
def to_swift_req(self, method, container, obj, query=None,
|
||||
|
|
|
@ -38,15 +38,14 @@ class FakeApp(object):
|
|||
E.g. '/v1/test:tester/bucket/object' will become
|
||||
'/v1/AUTH_test/bucket/object'. This method emulates the behavior.
|
||||
"""
|
||||
_, authorization = env['HTTP_AUTHORIZATION'].split(' ')
|
||||
tenant_user, sign = authorization.rsplit(':', 1)
|
||||
tenant_user = env['s3api.auth_details']['access_key']
|
||||
tenant, user = tenant_user.rsplit(':', 1)
|
||||
|
||||
path = env['PATH_INFO']
|
||||
env['PATH_INFO'] = path.replace(tenant_user, 'AUTH_' + tenant)
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
if 'HTTP_AUTHORIZATION' in env:
|
||||
if 's3api.auth_details' in env:
|
||||
self._update_s3_path_info(env)
|
||||
|
||||
return self.swift(env, start_response)
|
||||
|
|
|
@ -41,11 +41,10 @@ class FakeSwift(object):
|
|||
if 'swift.authorize_override' in env:
|
||||
return
|
||||
|
||||
if 'HTTP_AUTHORIZATION' not in env:
|
||||
if 's3api.auth_details' not in env:
|
||||
return
|
||||
|
||||
_, authorization = env['HTTP_AUTHORIZATION'].split(' ')
|
||||
tenant_user, sign = authorization.rsplit(':', 1)
|
||||
tenant_user = env['s3api.auth_details']['access_key']
|
||||
tenant, user = tenant_user.rsplit(':', 1)
|
||||
|
||||
path = env['PATH_INFO']
|
||||
|
|
|
@ -30,27 +30,6 @@ from swift.common.middleware.s3api.subresource import ACL, User, encode_acl, \
|
|||
Owner, Grant
|
||||
from swift.common.middleware.s3api.etree import fromstring
|
||||
from swift.common.middleware.s3api.utils import mktime, S3Timestamp
|
||||
from test.unit.common.middleware.s3api.helpers import FakeSwift
|
||||
|
||||
|
||||
def _wrap_fake_auth_middleware(org_func):
|
||||
def fake_fake_auth_middleware(self, env):
|
||||
org_func(env)
|
||||
|
||||
if 'swift.authorize_override' in env:
|
||||
return
|
||||
|
||||
if 'HTTP_AUTHORIZATION' not in env:
|
||||
return
|
||||
|
||||
_, authorization = env['HTTP_AUTHORIZATION'].split(' ')
|
||||
tenant_user, sign = authorization.rsplit(':', 1)
|
||||
tenant, user = tenant_user.rsplit(':', 1)
|
||||
|
||||
env['HTTP_X_TENANT_NAME'] = tenant
|
||||
env['HTTP_X_USER_NAME'] = user
|
||||
|
||||
return fake_fake_auth_middleware
|
||||
|
||||
|
||||
class TestS3ApiObj(S3ApiTestCase):
|
||||
|
@ -320,15 +299,20 @@ class TestS3ApiObj(S3ApiTestCase):
|
|||
@s3acl(s3acl_only=True)
|
||||
def test_object_GET_with_s3acl_and_keystone(self):
|
||||
# for passing keystone authentication root
|
||||
fake_auth = self.swift._fake_auth_middleware
|
||||
with patch.object(FakeSwift, '_fake_auth_middleware',
|
||||
_wrap_fake_auth_middleware(fake_auth)):
|
||||
orig_auth = self.swift._fake_auth_middleware
|
||||
calls = []
|
||||
|
||||
def wrapped_auth(env):
|
||||
calls.append((env['REQUEST_METHOD'], 's3api.auth_details' in env))
|
||||
orig_auth(env)
|
||||
|
||||
with patch.object(self.swift, '_fake_auth_middleware', wrapped_auth):
|
||||
self._test_object_GETorHEAD('GET')
|
||||
_, _, headers = self.swift.calls_with_headers[-1]
|
||||
self.assertNotIn('Authorization', headers)
|
||||
_, _, headers = self.swift.calls_with_headers[0]
|
||||
self.assertNotIn('Authorization', headers)
|
||||
self.assertEqual(calls, [
|
||||
('TEST', True),
|
||||
('HEAD', False),
|
||||
('GET', False),
|
||||
])
|
||||
|
||||
@s3acl
|
||||
def test_object_GET_Range(self):
|
||||
|
|
|
@ -267,8 +267,8 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||
req.content_type = 'text/plain'
|
||||
status, headers, body = self.call_s3api(req)
|
||||
self.assertEqual(status.split()[0], '200')
|
||||
for _, _, headers in self.swift.calls_with_headers:
|
||||
self.assertEqual(headers['Authorization'], 'AWS test:tester:X')
|
||||
for _, path, headers in self.swift.calls_with_headers:
|
||||
self.assertNotIn('Authorization', headers)
|
||||
|
||||
def test_signed_urls_no_timestamp(self):
|
||||
expire = '2147483647' # 19 Jan 2038 03:14:07
|
||||
|
@ -281,7 +281,7 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||
# for signed_url access and it also doesn't check timestamp
|
||||
self.assertEqual(status.split()[0], '200')
|
||||
for _, _, headers in self.swift.calls_with_headers:
|
||||
self.assertEqual(headers['Authorization'], 'AWS test:tester:X')
|
||||
self.assertNotIn('Authorization', headers)
|
||||
|
||||
def test_signed_urls_invalid_expire(self):
|
||||
expire = 'invalid'
|
||||
|
@ -332,8 +332,8 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||
status, headers, body = self.call_s3api(req)
|
||||
self.assertEqual(status.split()[0], '200', body)
|
||||
for _, _, headers in self.swift.calls_with_headers:
|
||||
self.assertEqual('AWS test:tester:X', headers['Authorization'])
|
||||
self.assertIn('X-Auth-Token', headers)
|
||||
self.assertNotIn('Authorization', headers)
|
||||
self.assertIsNone(headers['X-Auth-Token'])
|
||||
|
||||
def test_signed_urls_v4_bad_credential(self):
|
||||
def test(credential, message, extra=''):
|
||||
|
@ -740,12 +740,14 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||
def test_signature_v4(self):
|
||||
environ = {
|
||||
'REQUEST_METHOD': 'GET'}
|
||||
authz_header = 'AWS4-HMAC-SHA256 ' + ', '.join([
|
||||
'Credential=test:tester/%s/us-east-1/s3/aws4_request' %
|
||||
self.get_v4_amz_date_header().split('T', 1)[0],
|
||||
'SignedHeaders=host;x-amz-date',
|
||||
'Signature=X',
|
||||
])
|
||||
headers = {
|
||||
'Authorization':
|
||||
'AWS4-HMAC-SHA256 '
|
||||
'Credential=test:tester/%s/us-east-1/s3/aws4_request, '
|
||||
'SignedHeaders=host;x-amz-date,'
|
||||
'Signature=X' % self.get_v4_amz_date_header().split('T', 1)[0],
|
||||
'Authorization': authz_header,
|
||||
'X-Amz-Date': self.get_v4_amz_date_header(),
|
||||
'X-Amz-Content-SHA256': '0123456789'}
|
||||
req = Request.blank('/bucket/object', environ=environ, headers=headers)
|
||||
|
@ -753,8 +755,8 @@ class TestS3ApiMiddleware(S3ApiTestCase):
|
|||
status, headers, body = self.call_s3api(req)
|
||||
self.assertEqual(status.split()[0], '200', body)
|
||||
for _, _, headers in self.swift.calls_with_headers:
|
||||
self.assertEqual('AWS test:tester:X', headers['Authorization'])
|
||||
self.assertIn('X-Auth-Token', headers)
|
||||
self.assertEqual(authz_header, headers['Authorization'])
|
||||
self.assertIsNone(headers['X-Auth-Token'])
|
||||
|
||||
def test_signature_v4_no_date(self):
|
||||
environ = {
|
||||
|
|
|
@ -246,8 +246,6 @@ class TestRequest(S3ApiTestCase):
|
|||
m_swift_resp.return_value = FakeSwiftResponse()
|
||||
s3_req = S3AclRequest(req.environ, MagicMock())
|
||||
self.assertNotIn('s3api.auth_details', s3_req.environ)
|
||||
self.assertNotIn('HTTP_AUTHORIZATION', s3_req.environ)
|
||||
self.assertNotIn('Authorization', s3_req.headers)
|
||||
self.assertEqual(s3_req.token, 'token')
|
||||
|
||||
def test_to_swift_req_Authorization_not_exist_in_swreq(self):
|
||||
|
@ -265,8 +263,6 @@ class TestRequest(S3ApiTestCase):
|
|||
s3_req = S3AclRequest(req.environ, MagicMock())
|
||||
sw_req = s3_req.to_swift_req(method, container, obj)
|
||||
self.assertNotIn('s3api.auth_details', sw_req.environ)
|
||||
self.assertNotIn('HTTP_AUTHORIZATION', sw_req.environ)
|
||||
self.assertNotIn('Authorization', sw_req.headers)
|
||||
self.assertEqual(sw_req.headers['X-Auth-Token'], 'token')
|
||||
|
||||
def test_to_swift_req_subrequest_proxy_access_log(self):
|
||||
|
|
Loading…
Reference in New Issue