Handle COPY verb in container quota middleware
The patch fix the ability to bypass the account quota using the COPY verb. The quotas for destination container are now checked before the copy. Change-Id: I9f409ea6c0893f36972aa1fabe31fb143e151ab5 Fixes: bug #1259565
This commit is contained in:
parent
766ab4f0d0
commit
946984cb84
@ -79,9 +79,21 @@ class ContainerQuotaMiddleware(object):
|
||||
return HTTPBadRequest(body='Invalid count quota.')
|
||||
|
||||
# check user uploads against quotas
|
||||
elif obj and req.method == 'PUT':
|
||||
container_info = get_container_info(
|
||||
req.environ, self.app, swift_source='CQ')
|
||||
elif obj and req.method in ('PUT', 'COPY'):
|
||||
container_info = None
|
||||
if req.method == 'PUT':
|
||||
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('/')
|
||||
path_info = req.environ['PATH_INFO']
|
||||
req.environ['PATH_INFO'] = "/%s/%s/%s" % (
|
||||
version, account, dest)
|
||||
try:
|
||||
container_info = get_container_info(
|
||||
req.environ, self.app, swift_source='CQ')
|
||||
finally:
|
||||
req.environ['PATH_INFO'] = path_info
|
||||
if not container_info or not is_success(container_info['status']):
|
||||
# this will hopefully 404 later
|
||||
return self.app
|
||||
@ -90,10 +102,11 @@ class ContainerQuotaMiddleware(object):
|
||||
'bytes' in container_info and \
|
||||
container_info['meta']['quota-bytes'].isdigit():
|
||||
content_length = (req.content_length or 0)
|
||||
if 'x-copy-from' in req.headers:
|
||||
src_cont, src_obj = check_copy_from_header(req)
|
||||
if 'x-copy-from' in req.headers or req.method == 'COPY':
|
||||
if 'x-copy-from' in req.headers:
|
||||
container, obj = check_copy_from_header(req)
|
||||
path = '/%s/%s/%s/%s' % (version, account,
|
||||
src_cont, src_obj)
|
||||
container, obj)
|
||||
object_info = get_object_info(req.environ, self.app, path)
|
||||
if not object_info or not object_info['length']:
|
||||
content_length = 0
|
||||
|
@ -106,6 +106,18 @@ class TestContainerQuotas(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 413)
|
||||
|
||||
def test_exceed_bytes_quota_copy_verb(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '2'}})
|
||||
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
'swift.object/a/c2/o2': {'length': 10},
|
||||
'swift.cache': cache},
|
||||
headers={'Destination': '/c/o'})
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 413)
|
||||
|
||||
def test_not_exceed_bytes_quota(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}})
|
||||
@ -127,6 +139,17 @@ class TestContainerQuotas(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
|
||||
def test_not_exceed_bytes_quota_copy_verb(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}})
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
'swift.object/a/c2/o2': {'length': 10},
|
||||
'swift.cache': cache},
|
||||
headers={'Destination': '/c/o'})
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
|
||||
def test_bytes_quota_copy_from_no_src(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}})
|
||||
@ -148,6 +171,17 @@ class TestContainerQuotas(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 412)
|
||||
|
||||
def test_bytes_quota_copy_verb_no_src(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'bytes': 0, 'meta': {'quota-bytes': '100'}})
|
||||
req = Request.blank('/v1/a/c2/o3',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
'swift.object/a/c2/o2': {'length': 10},
|
||||
'swift.cache': cache},
|
||||
headers={'Destination': '/c/o'})
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
|
||||
def test_exceed_counts_quota(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'object_count': 1, 'meta': {'quota-count': '1'}})
|
||||
@ -169,6 +203,16 @@ class TestContainerQuotas(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 413)
|
||||
|
||||
def test_exceed_counts_quota_copy_verb(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'object_count': 1, 'meta': {'quota-count': '1'}})
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
'swift.cache': cache},
|
||||
headers={'Destination': '/c/o'})
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 413)
|
||||
|
||||
def test_not_exceed_counts_quota(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'object_count': 1, 'meta': {'quota-count': '2'}})
|
||||
@ -189,6 +233,16 @@ class TestContainerQuotas(unittest.TestCase):
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
|
||||
def test_not_exceed_counts_quota_copy_verb(self):
|
||||
app = container_quotas.ContainerQuotaMiddleware(FakeApp(), {})
|
||||
cache = FakeCache({'object_count': 1, 'meta': {'quota-count': '2'}})
|
||||
req = Request.blank('/v1/a/c2/o2',
|
||||
environ={'REQUEST_METHOD': 'COPY',
|
||||
'swift.cache': cache},
|
||||
headers={'Destination': '/c/o'})
|
||||
res = req.get_response(app)
|
||||
self.assertEquals(res.status_int, 200)
|
||||
|
||||
def test_invalid_quotas(self):
|
||||
req = Request.blank(
|
||||
'/v1/a/c',
|
||||
|
Loading…
Reference in New Issue
Block a user