From a82bfb25ba180dbde700d2f9108acf1c85f5d61f Mon Sep 17 00:00:00 2001 From: Alistair Coles Date: Thu, 29 Jan 2015 14:26:01 +0000 Subject: [PATCH] Make container GET call authorize when account not found When an account was not found, ContainerController would return 404 unconditionally for a container GET or HEAD request, without checking that the request was authorized. This patch modifies the GETorHEAD method to first call any callback method registered under 'swift.authorize' in the request environ and prefer any response from that over the 404. Closes-Bug: 1415957 Change-Id: I4f41fd9e445238e14af74b6208885d83698cc08d --- swift/proxy/controllers/container.py | 4 ++ test/unit/proxy/test_server.py | 72 ++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/swift/proxy/controllers/container.py b/swift/proxy/controllers/container.py index 1482dcc116..355bd8a7ba 100644 --- a/swift/proxy/controllers/container.py +++ b/swift/proxy/controllers/container.py @@ -84,6 +84,10 @@ class ContainerController(Controller): def GETorHEAD(self, req): """Handler for HTTP GET/HEAD requests.""" if not self.account_info(self.account_name, req)[1]: + if 'swift.authorize' in req.environ: + aresp = req.environ['swift.authorize'](req) + if aresp: + return aresp return HTTPNotFound(request=req) part = self.app.container_ring.get_part( self.account_name, self.container_name) diff --git a/test/unit/proxy/test_server.py b/test/unit/proxy/test_server.py index 99ab5af4f9..59dd320a45 100644 --- a/test/unit/proxy/test_server.py +++ b/test/unit/proxy/test_server.py @@ -6078,6 +6078,78 @@ class TestContainerController(unittest.TestCase): controller.HEAD(req) self.assert_(called[0]) + def test_unauthorized_requests_when_account_not_found(self): + # verify unauthorized container requests always return response + # from swift.authorize + called = [0, 0] + + def authorize(req): + called[0] += 1 + return HTTPUnauthorized(request=req) + + def account_info(*args): + called[1] += 1 + return None, None, None + + def _do_test(method): + with save_globals(): + swift.proxy.controllers.Controller.account_info = account_info + app = proxy_server.Application(None, FakeMemcache(), + account_ring=FakeRing(), + container_ring=FakeRing()) + set_http_connect(201, 201, 201) + req = Request.blank('/v1/a/c', {'REQUEST_METHOD': method}) + req.environ['swift.authorize'] = authorize + self.app.update_request(req) + res = app.handle_request(req) + return res + + for method in ('PUT', 'POST', 'DELETE'): + # no delay_denial on method, expect one call to authorize + called = [0, 0] + res = _do_test(method) + self.assertEqual(401, res.status_int) + self.assertEqual([1, 0], called) + + for method in ('HEAD', 'GET'): + # delay_denial on method, expect two calls to authorize + called = [0, 0] + res = _do_test(method) + self.assertEqual(401, res.status_int) + self.assertEqual([2, 1], called) + + def test_authorized_requests_when_account_not_found(self): + # verify authorized container requests always return 404 when + # account not found + called = [0, 0] + + def authorize(req): + called[0] += 1 + + def account_info(*args): + called[1] += 1 + return None, None, None + + def _do_test(method): + with save_globals(): + swift.proxy.controllers.Controller.account_info = account_info + app = proxy_server.Application(None, FakeMemcache(), + account_ring=FakeRing(), + container_ring=FakeRing()) + set_http_connect(201, 201, 201) + req = Request.blank('/v1/a/c', {'REQUEST_METHOD': method}) + req.environ['swift.authorize'] = authorize + self.app.update_request(req) + res = app.handle_request(req) + return res + + for method in ('PUT', 'POST', 'DELETE', 'HEAD', 'GET'): + # expect one call to authorize + called = [0, 0] + res = _do_test(method) + self.assertEqual(404, res.status_int) + self.assertEqual([1, 1], called) + def test_OPTIONS_get_info_drops_origin(self): with save_globals(): controller = proxy_server.ContainerController(self.app, 'a', 'c')