Fix s3api cross policy copy

In s3api's request object we copy backend headers into the request
environ for logging after we call get_response.  The problem with s3api
copy is that we make a pre-flight HEAD request to the source object
using the same request object, so the first response backend headers
pollute the request and the proxy won't over-ride the backend header
with the correct storage policy.

As a possible fix we simply remove the problematic header from the
request object after the pre-flight HEAD request finishes.

Change-Id: I40b252446b3a1294a5ca8b531f224ce9c16f9aba
This commit is contained in:
Clay Gerrard 2022-06-15 15:27:44 -05:00
parent 961177e6f7
commit 7a996a5c38
3 changed files with 28 additions and 1 deletions

View File

@ -916,6 +916,8 @@ class S3Request(swob.Request):
src_resp = self.get_response(app, 'HEAD', src_bucket,
swob.str_to_wsgi(src_obj),
headers=headers, query=query)
# we can't let this HEAD req spoil our COPY
self.headers.pop('x-backend-storage-policy-index')
if src_resp.status_int == 304: # pylint: disable-msg=E1101
raise PreconditionFailed()

View File

@ -189,7 +189,8 @@ class FakeSwift(object):
# simulate object GET/HEAD
elif method in ('GET', 'HEAD') and obj:
req.headers['X-Backend-Storage-Policy-Index'] = '2'
req.headers['X-Backend-Storage-Policy-Index'] = headers.get(
'x-backend-storage-policy-index', '2')
# note: tests may assume this copy of req_headers is case insensitive
# so we deliberately use a HeaderKeyDict

View File

@ -835,6 +835,30 @@ class TestS3ApiObj(S3ApiTestCase):
return_value=timestamp):
return self.call_s3api(req)
def test_simple_object_copy(self):
self.swift.register('HEAD', '/v1/AUTH_test/some/source',
swob.HTTPOk, {
'x-backend-storage-policy-index': '1',
}, None)
req = Request.blank(
'/bucket/object', method='PUT',
headers={
'Authorization': 'AWS test:tester:hmac',
'X-Amz-Copy-Source': '/some/source',
'Date': self.get_date_header(),
},
)
timestamp = time.time()
with patch('swift.common.middleware.s3api.utils.time.time',
return_value=timestamp):
status, headers, body = self.call_s3api(req)
self.assertEqual(status.split()[0], '200')
head_call, put_call = self.swift.calls_with_headers
self.assertEqual(
head_call.headers['x-backend-storage-policy-index'], '1')
self.assertEqual(put_call.headers['x-copy-from'], '/some/source')
self.assertNotIn('x-backend-storage-policy-index', put_call.headers)
@s3acl
def test_object_PUT_copy(self):
def do_test(src_path):