From c52795e263ab40d29baf1177812a5c93d15fbb26 Mon Sep 17 00:00:00 2001 From: Thiago da Silva Date: Mon, 24 Nov 2014 16:44:42 -0500 Subject: [PATCH] Fix container quota check during cross-account COPY Container quota is not currently checking Destination-Account header which could cause quota to not be enforced in case of copies Change-Id: I43adb0d7d2fc14ba6c0ca419a52a5c3f138f799a Signed-off-by: Thiago da Silva --- swift/common/middleware/container_quotas.py | 13 ++++++--- test/unit/common/middleware/test_quotas.py | 32 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/swift/common/middleware/container_quotas.py b/swift/common/middleware/container_quotas.py index 4aef895d2f..4feca69a7b 100644 --- a/swift/common/middleware/container_quotas.py +++ b/swift/common/middleware/container_quotas.py @@ -51,7 +51,8 @@ For example:: [filter:container_quotas] use = egg:swift#container_quotas """ -from swift.common.constraints import check_copy_from_header +from swift.common.constraints import check_copy_from_header, \ + check_account_format, check_destination_header from swift.common.http import is_success from swift.common.swob import HTTPRequestEntityTooLarge, HTTPBadRequest, \ wsgify @@ -96,10 +97,14 @@ class ContainerQuotaMiddleware(object): container_info = get_container_info( req.environ, self.app, swift_source='CQ') if req.method == 'COPY' and 'Destination' in req.headers: - dest = req.headers.get('Destination').lstrip('/') + dest_account = account + if 'Destination-Account' in req.headers: + dest_account = req.headers.get('Destination-Account') + dest_account = check_account_format(req, dest_account) + dest_container, dest_object = check_destination_header(req) path_info = req.environ['PATH_INFO'] - req.environ['PATH_INFO'] = "/%s/%s/%s" % ( - version, account, dest) + req.environ['PATH_INFO'] = "/%s/%s/%s/%s" % ( + version, dest_account, dest_container, dest_object) try: container_info = get_container_info( req.environ, self.app, swift_source='CQ') diff --git a/test/unit/common/middleware/test_quotas.py b/test/unit/common/middleware/test_quotas.py index b0548cc56c..56a7780e2e 100644 --- a/test/unit/common/middleware/test_quotas.py +++ b/test/unit/common/middleware/test_quotas.py @@ -219,6 +219,38 @@ class TestContainerQuotas(unittest.TestCase): self.assertEquals(res.status_int, 413) self.assertEquals(res.body, 'Upload exceeds quota.') + def test_exceed_counts_quota_copy_cross_account_verb(self): + app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) + a_c_cache = {'storage_policy': '0', 'meta': {'quota-count': '2'}, + 'status': 200, 'object_count': 1} + a2_c_cache = {'storage_policy': '0', 'meta': {'quota-count': '1'}, + 'status': 200, 'object_count': 1} + req = Request.blank('/v1/a/c2/o2', + environ={'REQUEST_METHOD': 'COPY', + 'swift.container/a/c': a_c_cache, + 'swift.container/a2/c': a2_c_cache}, + headers={'Destination': '/c/o', + 'Destination-Account': 'a2'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 413) + self.assertEquals(res.body, 'Upload exceeds quota.') + + def test_exceed_counts_quota_copy_cross_account_PUT_verb(self): + app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) + a_c_cache = {'storage_policy': '0', 'meta': {'quota-count': '2'}, + 'status': 200, 'object_count': 1} + a2_c_cache = {'storage_policy': '0', 'meta': {'quota-count': '1'}, + 'status': 200, 'object_count': 1} + req = Request.blank('/v1/a2/c/o', + environ={'REQUEST_METHOD': 'PUT', + 'swift.container/a/c': a_c_cache, + 'swift.container/a2/c': a2_c_cache}, + headers={'X-Copy-From': '/c2/o2', + 'X-Copy-From-Account': 'a'}) + res = req.get_response(app) + self.assertEquals(res.status_int, 413) + self.assertEquals(res.body, 'Upload exceeds quota.') + def test_not_exceed_counts_quota(self): app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {}) cache = FakeCache({'object_count': 1, 'meta': {'quota-count': '2'}})