From 3e678a94a0a15117c99ca5065b13822f9edf7876 Mon Sep 17 00:00:00 2001 From: alex-smile <443677891@qq.com> Date: Tue, 27 Jun 2023 11:19:23 +0800 Subject: [PATCH] Fix cors allow origins by regex (#67) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cors allow_origins, allow_origins_by_regex 只能一个有效 * 更新翻译 --- .../apigateway/apps/plugin/plugin/checker.py | 3 +++ .../apigateway/fixtures/plugins.yaml | 8 ++++---- .../locale/en/LC_MESSAGES/django.mo | Bin 37936 -> 38083 bytes .../locale/en/LC_MESSAGES/django.po | 11 ++++++++--- .../tests/apps/plugin/plugin/test_checker.py | 17 ++++++++++++++++- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/dashboard/apigateway/apigateway/apps/plugin/plugin/checker.py b/src/dashboard/apigateway/apigateway/apps/plugin/plugin/checker.py index 56ac7a0c3..1befa4d8d 100644 --- a/src/dashboard/apigateway/apigateway/apps/plugin/plugin/checker.py +++ b/src/dashboard/apigateway/apigateway/apps/plugin/plugin/checker.py @@ -56,6 +56,9 @@ def check(self, yaml_: str): if not (loaded_data.get("allow_origins") or loaded_data.get("allow_origins_by_regex")): raise ValueError(_("allow_origins, allow_origins_by_regex 不能同时为空。")) + if loaded_data.get("allow_origins") and loaded_data.get("allow_origins_by_regex"): + raise ValueError(_("allow_origins, allow_origins_by_regex 只能一个有效。")) + def _check_allow_origins(self, allow_origins: Optional[str]): if not allow_origins: return diff --git a/src/dashboard/apigateway/apigateway/fixtures/plugins.yaml b/src/dashboard/apigateway/apigateway/fixtures/plugins.yaml index 0d83c09af..63c66b149 100644 --- a/src/dashboard/apigateway/apigateway/fixtures/plugins.yaml +++ b/src/dashboard/apigateway/apigateway/fixtures/plugins.yaml @@ -122,14 +122,14 @@ ], "properties": { "allow_origins": { - "description": "允许跨域访问的 Origin,格式为 scheme://host:port,示例如 https://example.com:8081。如果你有多个 Origin,请使用 , 分隔。当 allow_credential 为 false 时,可以使用 * 来表示允许所有 Origin 通过。你也可以在启用了 allow_credential 后使用 ** 强制允许所有 Origin 均通过,但请注意这样存在安全隐患。", + "description": "允许跨域访问的 Origin,格式为 scheme://host:port,示例如 https://example.com:8081。如果你有多个 Origin,请使用 , 分隔。当 allow_credential 为 false 时,可以使用 * 来表示允许所有 Origin 通过。你也可以在启用了 allow_credential 后使用 ** 强制允许所有 Origin 均通过,但请注意这样存在安全隐患。allow_origins、allow_origins_by_regex 只能一个有效。", "type": "string", "pattern": "^(|\\*|\\*\\*|null|http(s)?://[-a-zA-Z0-9:\\[\\]\\.]+(,http(s)?://[-a-zA-Z0-9:\\[\\]\\.]+)*)$", "maxLength": 4096, "default": "" }, "allow_origins_by_regex": { - "description": "使用正则表示的允许跨域访问的 Origin,示例如 '^https://.*\\.example\\.com:8081$',此正则允许 https://a.example.com:8081, https://b.example.com:8081。", + "description": "使用正则表示的允许跨域访问的 Origin,示例如 '^https://.*\\.example\\.com:8081$',此正则允许 https://a.example.com:8081, https://b.example.com:8081。allow_origins、allow_origins_by_regex 只能一个有效。", "type": "array", "uniqueItems": true, "items": { @@ -214,13 +214,13 @@ ], "properties": { "allow_origins": { - "description": "Origins to allow CORS. Use the scheme://host:port format. For example, https://example.com:8081. If you have multiple origins, use a , to list them. If allow_credential is set to false, you can enable CORS for all origins by using *. If allow_credential is set to true, you can forcefully allow CORS on all origins by using ** but it will pose some security issues.", + "description": "Origins to allow CORS. Use the scheme://host:port format. For example, https://example.com:8081. If you have multiple origins, use a , to list them. If allow_credential is set to false, you can enable CORS for all origins by using *. If allow_credential is set to true, you can forcefully allow CORS on all origins by using ** but it will pose some security issues. allow_origins, allow_origins_by_regex can only be one valid at a time.", "type": "string", "pattern": "^(|\\*|\\*\\*|null|http(s)?://[-a-zA-Z0-9:\\[\\]\\.]+(,http(s)?://[-a-zA-Z0-9:\\[\\]\\.]+)*)$", "default": "" }, "allow_origins_by_regex": { - "description": "Origin that allows CORS using regular expressions. You can use regex to allow specific origins when no credentials, for example, '^https://.*\\.example\\.com:8081$', this regular expression allows https://a.example.com:8081, https://b.example.com:8081.", + "description": "Origin that allows CORS using regular expressions. You can use regex to allow specific origins when no credentials, for example, '^https://.*\\.example\\.com:8081$', this regular expression allows https://a.example.com:8081, https://b.example.com:8081. allow_origins, allow_origins_by_regex can only be one valid at a time.", "type": "array", "uniqueItems": true, "items": { diff --git a/src/dashboard/apigateway/apigateway/locale/en/LC_MESSAGES/django.mo b/src/dashboard/apigateway/apigateway/locale/en/LC_MESSAGES/django.mo index ef4c9fd1d4f77496a8d5730afcf0138e1c188eab..bc48e6fb852ac9d1c24409bf664b1c23637f65d3 100644 GIT binary patch delta 8503 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 diff --git a/src/dashboard/apigateway/apigateway/locale/en/LC_MESSAGES/django.po b/src/dashboard/apigateway/apigateway/locale/en/LC_MESSAGES/django.po index ecb703ea8..fbabd8a87 100644 --- a/src/dashboard/apigateway/apigateway/locale/en/LC_MESSAGES/django.po +++ b/src/dashboard/apigateway/apigateway/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-06-21 15:03+0800\n" +"POT-Creation-Date: 2023-06-27 11:06+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1036,13 +1036,18 @@ msgid "allow_origins, allow_origins_by_regex 不能同时为空。" msgstr "" "allow_origins, allow_origins_by_regex cannot be empty at the same time." -#: apigateway/apps/plugin/plugin/checker.py:79 +#: apigateway/apps/plugin/plugin/checker.py:60 +msgid "allow_origins, allow_origins_by_regex 只能一个有效。" +msgstr "" +"allow_origins, allow_origins_by_regex can only be one valid at a time." + +#: apigateway/apps/plugin/plugin/checker.py:82 #, python-brace-format msgid "allow_origins_by_regex 中数据 '{re_rule}' 不是合法的正则表达式。" msgstr "" "The '{re_rule}' in allow_origins_by_regex is not a legal regex expression." -#: apigateway/apps/plugin/plugin/checker.py:84 +#: apigateway/apps/plugin/plugin/checker.py:87 msgid "{} 存在重复的元素:{}。" msgstr "Duplicate element in {}: {}." diff --git a/src/dashboard/apigateway/apigateway/tests/apps/plugin/plugin/test_checker.py b/src/dashboard/apigateway/apigateway/tests/apps/plugin/plugin/test_checker.py index fd52f0bb9..3ed5b50aa 100644 --- a/src/dashboard/apigateway/apigateway/tests/apps/plugin/plugin/test_checker.py +++ b/src/dashboard/apigateway/apigateway/tests/apps/plugin/plugin/test_checker.py @@ -27,6 +27,13 @@ class TestBkCorsChecker: [ { "allow_origins": "**", + "allow_methods": "**", + "allow_headers": "**", + "expose_headers": "", + "max_age": 100, + "allow_credential": True, + }, + { "allow_origins_by_regex": ["^http://.*\\.example\\.com$"], "allow_methods": "**", "allow_headers": "**", @@ -61,7 +68,6 @@ def test_check(self, data): "allow_credential": True, }, { - "allow_origins": "*", "allow_origins_by_regex": ["\\"], "allow_methods": "*", "allow_headers": "*", @@ -69,6 +75,15 @@ def test_check(self, data): "max_age": 100, "allow_credential": False, }, + { + "allow_origins": "*", + "allow_origins_by_regex": "http://.*.example.com", + "allow_methods": "*", + "allow_headers": "*", + "expose_headers": "*", + "max_age": 100, + "allow_credential": False, + }, { "allow_origins": "", "allow_origins_by_regex": [],