From 00bb0f8ba68f2108dcf2f3d486217de298114044 Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Wed, 9 Feb 2022 14:01:42 -0800 Subject: [PATCH] read-only: Only act on Swift paths ... and they must include an account. Change-Id: I632d58697a1026a6a581db27786ab9503c62f97e --- swift/common/middleware/read_only.py | 6 ++- test/unit/common/middleware/test_read_only.py | 54 ++++++++++++++----- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/swift/common/middleware/read_only.py b/swift/common/middleware/read_only.py index 3d54fdc5b4..b905ff1c97 100644 --- a/swift/common/middleware/read_only.py +++ b/swift/common/middleware/read_only.py @@ -12,7 +12,7 @@ # implied. # See the License for the specific language governing permissions and # limitations under the License. -from swift.common.constraints import check_account_format +from swift.common.constraints import check_account_format, valid_api_version from swift.common.swob import HTTPMethodNotAllowed, Request from swift.common.utils import get_logger, config_true_value from swift.common.registry import register_swift_info @@ -79,7 +79,9 @@ class ReadOnlyMiddleware(object): return self.app(env, start_response) try: - version, account, container, obj = req.split_path(1, 4, True) + version, account, container, obj = req.split_path(2, 4, True) + if not valid_api_version(version): + raise ValueError except ValueError: return self.app(env, start_response) diff --git a/test/unit/common/middleware/test_read_only.py b/test/unit/common/middleware/test_read_only.py index f54de9d31a..833df8a6fa 100644 --- a/test/unit/common/middleware/test_read_only.py +++ b/test/unit/common/middleware/test_read_only.py @@ -48,7 +48,7 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', return_value={}): for method in read_methods + write_methods: - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = method resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) @@ -64,13 +64,13 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', return_value={}): for method in read_methods: - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = method resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) for method in write_methods: - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = method resp = ro(req.environ, start_response) self.assertEqual(ro_resp, resp) @@ -84,13 +84,13 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', return_value={'sysmeta': {'read-only': 'true'}}): for method in read_methods: - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = method resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) for method in write_methods: - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = method resp = ro(req.environ, start_response) self.assertEqual(ro_resp, resp) @@ -104,7 +104,7 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', return_value={'sysmeta': {'read-only': 'false'}}): for method in read_methods + write_methods: - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = method resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) @@ -120,7 +120,7 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', return_value={'sysmeta': {'read-only': 'false'}}): for method in read_methods + write_methods: - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = method resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) @@ -136,7 +136,7 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', return_value={}): - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = "DELETE" resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) @@ -151,7 +151,7 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', return_value={'sysmeta': {'read-only': 'on'}}): - req = Request.blank('/v/a') + req = Request.blank('/v1/a') req.method = "DELETE" resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) @@ -172,7 +172,7 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', get_fake_read_only): headers = {'Destination-Account': 'b'} - req = Request.blank('/v/a', headers=headers) + req = Request.blank('/v1/a', headers=headers) req.method = "COPY" resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) @@ -191,7 +191,7 @@ class TestReadOnly(unittest.TestCase): with mock.patch('swift.common.middleware.read_only.get_info', get_fake_read_only): headers = {'Destination-Account': 'b'} - req = Request.blank('/v/a', headers=headers) + req = Request.blank('/v1/a', headers=headers) req.method = "COPY" resp = ro(req.environ, start_response) self.assertEqual(ro_resp, resp) @@ -212,7 +212,7 @@ class TestReadOnly(unittest.TestCase): 'account_read_only', fake_account_read_only): headers = {'Destination-Account': 'b'} - req = Request.blank('/v/a', headers=headers) + req = Request.blank('/v1/a', headers=headers) req.method = "COPY" resp = ro(req.environ, start_response) self.assertEqual(resp, [b'Some Content']) @@ -228,11 +228,39 @@ class TestReadOnly(unittest.TestCase): 'account_read_only', return_value='true'): headers = {'Destination-Account': 'b'} - req = Request.blank('/v/a', headers=headers) + req = Request.blank('/v1/a', headers=headers) req.method = "COPY" resp = ro(req.environ, start_response) self.assertEqual(ro_resp, resp) + def test_global_read_only_non_swift_path(self): + conf = {} + + ro = read_only.filter_factory(conf)(FakeApp()) + ro.logger = debug_logger() + + def fake_account_read_only(self, req, account): + return 'on' + + with mock.patch( + 'swift.common.middleware.read_only.ReadOnlyMiddleware.' + + 'account_read_only', + fake_account_read_only): + req = Request.blank('/auth/v3.14') + req.method = "POST" + resp = ro(req.environ, start_response) + self.assertEqual(resp, [b'Some Content']) + + req = Request.blank('/v1') + req.method = "PUT" + resp = ro(req.environ, start_response) + self.assertEqual(resp, [b'Some Content']) + + req = Request.blank('/v1.0/') + req.method = "DELETE" + resp = ro(req.environ, start_response) + self.assertEqual(resp, [b'Some Content']) + if __name__ == '__main__': unittest.main()