diff --git a/swift/common/middleware/versioned_writes.py b/swift/common/middleware/versioned_writes.py index 3cb0989..ec95b9c 100644 --- a/swift/common/middleware/versioned_writes.py +++ b/swift/common/middleware/versioned_writes.py @@ -279,6 +279,7 @@ class VersionedWritesContext(WSGIContext): def _put_versioned_obj(self, req, put_path_info, source_resp): # Create a new Request object to PUT to the versions container, copying # all headers from the source object apart from x-timestamp. + # put_req = make_subrequest( put_req = make_pre_authed_request( req.environ, path=put_path_info, method='PUT', swift_source='VW') @@ -331,6 +332,16 @@ class VersionedWritesContext(WSGIContext): # check for any other errors self._check_response_error(req, get_resp) + # validate the write access to the versioned container before + # making any backend requests + if 'swift.authorize' in req.environ: + container_info = get_container_info( + req.environ, self.app) + req.acl = container_info.get('write_acl') + aresp = req.environ['swift.authorize'](req) + if aresp: + raise aresp + # if there's an existing object, then copy it to # X-Versions-Location prefix_len = '%03x' % len(object_name) diff --git a/test/functional/tests.py b/test/functional/tests.py index fa5b018..e443079 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -3777,11 +3777,16 @@ class TestObjectVersioning(Base): cfg={'use_token': self.env.storage_token3}) # user3 cannot write or delete from source container either + number_of_versions = versions_container.info()['object_count'] self.assertRaises(ResponseError, versioned_obj.write, "some random user trying to write data", cfg={'use_token': self.env.storage_token3}) + self.assertEqual(number_of_versions, + versions_container.info()['object_count']) self.assertRaises(ResponseError, versioned_obj.delete, cfg={'use_token': self.env.storage_token3}) + self.assertEqual(number_of_versions, + versions_container.info()['object_count']) # user2 can't read or delete from versions-location self.assertRaises(ResponseError, backup_file.read, diff --git a/test/unit/common/middleware/test_versioned_writes.py b/test/unit/common/middleware/test_versioned_writes.py index c6da47f..610d66d 100644 --- a/test/unit/common/middleware/test_versioned_writes.py +++ b/test/unit/common/middleware/test_versioned_writes.py @@ -387,7 +387,9 @@ class VersionedWritesTestCase(VersionedWritesBaseTestCase): 'swift.trans_id': 'fake_trans_id'}) status, headers, body = self.call_vw(req) self.assertEqual(status, '201 Created') - self.assertEqual(len(self.authorized), 1) + # authorized twice now becuase versioned_writes now makes a check on + # PUT. + self.assertEqual(len(self.authorized), 2) self.assertRequestEqual(req, self.authorized[0]) self.assertEqual(['VW', 'VW', None], self.app.swift_sources) self.assertEqual({'fake_trans_id'}, set(self.app.txn_ids)) @@ -467,7 +469,9 @@ class VersionedWritesTestCase(VersionedWritesBaseTestCase): 'CONTENT_LENGTH': '100'}) status, headers, body = self.call_vw(req) self.assertEqual(status, '200 OK') - self.assertEqual(len(self.authorized), 1) + # authorized twice now becuase versioned_writes now makes a check on + # PUT. + self.assertEqual(len(self.authorized), 2) self.assertRequestEqual(req, self.authorized[0]) # check that sysmeta header was used @@ -510,8 +514,10 @@ class VersionedWritesTestCase(VersionedWritesBaseTestCase): headers={'Destination': 'tgt_cont/tgt_obj'}) status, headers, body = self.call_vw(req) self.assertEqual(status, '200 OK') - self.assertEqual(len(self.authorized), 1) - self.assertRequestEqual(req, self.authorized[0]) + # authorized twice now becuase versioned_writes now makes a check on + # PUT. + self.assertEqual(len(self.authorized), 2) + self.assertRequestEqual(req, self.authorized[-1]) self.assertEqual(3, self.app.call_count) def test_copy_new_version_different_account(self): @@ -532,8 +538,10 @@ class VersionedWritesTestCase(VersionedWritesBaseTestCase): 'Destination-Account': 'tgt_a'}) status, headers, body = self.call_vw(req) self.assertEqual(status, '200 OK') - self.assertEqual(len(self.authorized), 1) - self.assertRequestEqual(req, self.authorized[0]) + # authorized twice now becuase versioned_writes now makes a check on + # PUT. + self.assertEqual(len(self.authorized), 2) + self.assertRequestEqual(req, self.authorized[-1]) self.assertEqual(3, self.app.call_count) def test_copy_new_version_bogus_account(self):