From 1857fe643adf683c4c8df6c83aa93b4f994f397e Mon Sep 17 00:00:00 2001 From: JianBo He Date: Mon, 26 Sep 2022 11:06:59 +0800 Subject: [PATCH 1/6] fix(acl): support all rules in JWT ACL --- apps/emqx_auth_jwt/src/emqx_auth_jwt.erl | 16 +++++++++++----- apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl index 0b3f17b04..18b9ef675 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl @@ -109,11 +109,17 @@ string_to_number(_) -> %% Verify Claims %%-------------------------------------------------------------------- -verify_acl(ClientInfo, #{<<"sub">> := SubTopics}, subscribe, Topic) when is_list(SubTopics) -> - verify_acl(ClientInfo, SubTopics, Topic); -verify_acl(ClientInfo, #{<<"pub">> := PubTopics}, publish, Topic) when is_list(PubTopics) -> - verify_acl(ClientInfo, PubTopics, Topic); -verify_acl(_ClientInfo, _Acl, _PubSub, _Topic) -> {stop, deny}. +verify_acl(ClientInfo, Acl, PubSub, Topic) -> + Key = case PubSub of + subscribe -> <<"sub">>; + publish -> <<"pub">> + end, + case {maps:get(<<"all">>, Acl, []), maps:get(Key, Acl, [])} of + {Rules1, Rules2} when is_list(Rules1), is_list(Rules2) -> + verify_acl(ClientInfo, Rules1 ++ Rules2, Topic); + {_, _} -> + {stop, deny} + end. verify_acl(_ClientInfo, [], _Topic) -> {stop, deny}; verify_acl(ClientInfo, [AclTopic | AclTopics], Topic) -> diff --git a/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl index 62f753904..7452091bd 100644 --- a/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl +++ b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl @@ -297,7 +297,8 @@ t_check_jwt_acl(_Config) -> {username, <<"plain">>}, {sub, value}, {acl, [{sub, [<<"a/b">>]}, - {pub, [<<"c/d">>]}]}, + {pub, [<<"c/d">>]}, + {all, [<<"all">>]}]}, {exp, erlang:system_time(seconds) + 10}], <<"HS256">>, <<"emqxsecret">>), @@ -329,6 +330,19 @@ t_check_jwt_acl(_Config) -> after 100 -> ok end, + %% can pub/sub to all rules + ?assertMatch( + {ok, #{}, [0]}, + emqtt:subscribe(C, <<"all">>, 0)), + + ?assertMatch( + ok, + emqtt:publish(C, <<"all">>, <<"hi">>, 0)), + receive + {publish, #{topic := <<"all">>}} -> ok + after 2000 -> + ?assert(false, "Publish to `all` should be allowed") + end, ok = emqtt:disconnect(C). t_check_jwt_acl_no_recs(init, _Config) -> From 7b0acf2c4d919399b6c3a6e40c7e90be7a8090cc Mon Sep 17 00:00:00 2001 From: JianBo He Date: Fri, 21 Oct 2022 11:47:07 +0800 Subject: [PATCH 2/6] chore: update changes and appup.src --- .../emqx_auth_jwt/src/emqx_auth_jwt.appup.src | 22 ++----------------- changes/v4.3.22-en.md | 2 ++ changes/v4.3.22-zh.md | 2 ++ 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src index 7ee2349c3..4691f096e 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src @@ -2,31 +2,13 @@ %% Unless you know what you are doing, DO NOT edit manually!! {VSN, [{"4.3.7",[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]}, - {"4.3.6", - [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, - {"4.3.5", - [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, - {"4.3.4", - [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, - {"4.3.3", + {<<"4\\.3\\.[3-6]">>, [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, {<<"4\\.3\\.[0-2]">>,[{restart_application,emqx_auth_jwt}]}, {<<".*">>,[]}], [{"4.3.7",[{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}]}, - {"4.3.6", - [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, - {"4.3.5", - [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, - {"4.3.4", - [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, - {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, - {"4.3.3", + {<<"4\\.3\\.[3-6]">>, [{load_module,emqx_auth_jwt,brutal_purge,soft_purge,[]}, {load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, {<<"4\\.3\\.[0-2]">>,[{restart_application,emqx_auth_jwt}]}, diff --git a/changes/v4.3.22-en.md b/changes/v4.3.22-en.md index 77a197624..6e2df3367 100644 --- a/changes/v4.3.22-en.md +++ b/changes/v4.3.22-en.md @@ -3,6 +3,8 @@ - Add a warning log if the ACL check failed for subscription [#9124](https://github.com/emqx/emqx/pull/9124). This is to make the ACL deny logging for subscription behave the same as for publish. +- JWT authorization supports the `all` rules [#9044](https://github.com/emqx/emqx/pull/9044). + ### Bug fixes - Improve the display of rule's 'Maximum Speed' counter to only reserve 2 decimal places. [#9185](https://github.com/emqx/emqx/pull/9185) diff --git a/changes/v4.3.22-zh.md b/changes/v4.3.22-zh.md index 58c82588d..32a161a1f 100644 --- a/changes/v4.3.22-zh.md +++ b/changes/v4.3.22-zh.md @@ -3,6 +3,8 @@ - 订阅时,如果 ACL 检查不通过,打印一个警告日志 [#9124](https://github.com/emqx/emqx/pull/9124)。 该行为的改变主要是为了跟发布失败时的行为保持一致。 +- 基于 JWT 的发布订阅授权支持 `all` 规则 [#9044](https://github.com/emqx/emqx/pull/9044)。 + ### 修复 - 改进规则的 "最大执行速度" 的计数,只保留小数点之后 2 位 [#9185](https://github.com/emqx/emqx/pull/9185) From fa4203effa3da170f8749a9c2b70d780cf2ae8a0 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Fri, 21 Oct 2022 10:32:41 +0800 Subject: [PATCH 3/6] chore: apply suggestions from code review Co-authored-by: Zaiming (Stone) Shi --- apps/emqx_auth_jwt/src/emqx_auth_jwt.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl index 18b9ef675..92459b8ac 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl @@ -115,7 +115,7 @@ verify_acl(ClientInfo, Acl, PubSub, Topic) -> publish -> <<"pub">> end, case {maps:get(<<"all">>, Acl, []), maps:get(Key, Acl, [])} of - {Rules1, Rules2} when is_list(Rules1), is_list(Rules2) -> + {Rules1, Rules2} when is_list(Rules1) andalso is_list(Rules2) -> verify_acl(ClientInfo, Rules1 ++ Rules2, Topic); {_, _} -> {stop, deny} From 38e87579c060c8cb1a4086f454f966996061a9f7 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Fri, 21 Oct 2022 11:39:17 +0800 Subject: [PATCH 4/6] chore(jwt-acl): avoid the disruptions caused by rule formatting errors --- apps/emqx_auth_jwt/src/emqx_auth_jwt.erl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl index 92459b8ac..02ea764d7 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl @@ -114,12 +114,15 @@ verify_acl(ClientInfo, Acl, PubSub, Topic) -> subscribe -> <<"sub">>; publish -> <<"pub">> end, - case {maps:get(<<"all">>, Acl, []), maps:get(Key, Acl, [])} of - {Rules1, Rules2} when is_list(Rules1) andalso is_list(Rules2) -> - verify_acl(ClientInfo, Rules1 ++ Rules2, Topic); - {_, _} -> - {stop, deny} - end. + Rules0 = lists:foldl( + fun(K, Acc) -> + [case maps:get(K, Acl, undefined) of + R when is_list(R) -> R; + _ -> [] + end | Acc] + end, [], [<<"all">>, Key]), + Rules = lists:concat(Rules0), + verify_acl(ClientInfo, Rules, Topic). verify_acl(_ClientInfo, [], _Topic) -> {stop, deny}; verify_acl(ClientInfo, [AclTopic | AclTopics], Topic) -> From 4a9b5662f83d4d4e9fbb9eba2180c826a3d3e159 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Mon, 24 Oct 2022 09:51:05 +0800 Subject: [PATCH 5/6] chore: fix diaylzer warnings --- apps/emqx_auth_jwt/src/emqx_auth_jwt.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl index 02ea764d7..c315cd59e 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl @@ -121,7 +121,7 @@ verify_acl(ClientInfo, Acl, PubSub, Topic) -> _ -> [] end | Acc] end, [], [<<"all">>, Key]), - Rules = lists:concat(Rules0), + Rules = lists:append(Rules0), verify_acl(ClientInfo, Rules, Topic). verify_acl(_ClientInfo, [], _Topic) -> {stop, deny}; From bd59197a5828bc73e0a032ab437964b9d83b4f72 Mon Sep 17 00:00:00 2001 From: JianBo He Date: Mon, 24 Oct 2022 15:32:37 +0800 Subject: [PATCH 6/6] chore: apply suggestions from code review Co-authored-by: Zaiming (Stone) Shi --- apps/emqx_auth_jwt/src/emqx_auth_jwt.erl | 14 +++++++------- changes/v4.3.22-en.md | 2 +- changes/v4.3.22-zh.md | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl index c315cd59e..623fa25c5 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl @@ -114,13 +114,13 @@ verify_acl(ClientInfo, Acl, PubSub, Topic) -> subscribe -> <<"sub">>; publish -> <<"pub">> end, - Rules0 = lists:foldl( - fun(K, Acc) -> - [case maps:get(K, Acl, undefined) of - R when is_list(R) -> R; - _ -> [] - end | Acc] - end, [], [<<"all">>, Key]), + Rules0 = lists:map( + fun(K) -> + case maps:get(K, Acl, undefined) of + R when is_list(R) -> R; + _ -> [] + end + end, [<<"all">>, Key]), Rules = lists:append(Rules0), verify_acl(ClientInfo, Rules, Topic). diff --git a/changes/v4.3.22-en.md b/changes/v4.3.22-en.md index 6e2df3367..dde805195 100644 --- a/changes/v4.3.22-en.md +++ b/changes/v4.3.22-en.md @@ -3,7 +3,7 @@ - Add a warning log if the ACL check failed for subscription [#9124](https://github.com/emqx/emqx/pull/9124). This is to make the ACL deny logging for subscription behave the same as for publish. -- JWT authorization supports the `all` rules [#9044](https://github.com/emqx/emqx/pull/9044). +- JWT ACL claim supports `all` action to imply the rules applie to both `pub` and `sub` [#9044](https://github.com/emqx/emqx/pull/9044). ### Bug fixes diff --git a/changes/v4.3.22-zh.md b/changes/v4.3.22-zh.md index 32a161a1f..1ee55be61 100644 --- a/changes/v4.3.22-zh.md +++ b/changes/v4.3.22-zh.md @@ -3,7 +3,7 @@ - 订阅时,如果 ACL 检查不通过,打印一个警告日志 [#9124](https://github.com/emqx/emqx/pull/9124)。 该行为的改变主要是为了跟发布失败时的行为保持一致。 -- 基于 JWT 的发布订阅授权支持 `all` 规则 [#9044](https://github.com/emqx/emqx/pull/9044)。 +- 基于 JWT 的 ACL 支持 `all` 动作,指定同时适用于 `pub` 和 `sub` 两个动作的规则列表 [#9044](https://github.com/emqx/emqx/pull/9044)。 ### 修复