Merge pull request #9871 from lafirest/fix/authz_rules

feat(authz): allow the placeholder to be anywhere in the topic for authz rules
This commit is contained in:
lafirest 2023-02-01 00:12:06 +08:00 committed by GitHub
commit 3d59be6ab6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 27 deletions

View File

@ -1,7 +1,7 @@
%% -*- mode: erlang -*-
{application, emqx_authz, [
{description, "An OTP application"},
{vsn, "0.1.12"},
{vsn, "0.1.13"},
{registered, []},
{mod, {emqx_authz_app, []}},
{applications, [

View File

@ -100,15 +100,17 @@ compile_topic(<<"eq ", Topic/binary>>) ->
compile_topic({eq, Topic}) ->
{eq, emqx_topic:words(bin(Topic))};
compile_topic(Topic) ->
Words = emqx_topic:words(bin(Topic)),
case pattern(Words) of
true -> {pattern, Words};
false -> Words
TopicBin = bin(Topic),
case
emqx_placeholder:preproc_tmpl(
TopicBin,
#{placeholders => [?PH_USERNAME, ?PH_CLIENTID]}
)
of
[{str, _}] -> emqx_topic:words(TopicBin);
Tokens -> {pattern, Tokens}
end.
pattern(Words) ->
lists:member(?PH_USERNAME, Words) orelse lists:member(?PH_CLIENTID, Words).
atom(B) when is_binary(B) ->
try
binary_to_existing_atom(B, utf8)
@ -202,8 +204,8 @@ match_who(_, _) ->
match_topics(_ClientInfo, _Topic, []) ->
false;
match_topics(ClientInfo, Topic, [{pattern, PatternFilter} | Filters]) ->
TopicFilter = feed_var(ClientInfo, PatternFilter),
match_topic(emqx_topic:words(Topic), TopicFilter) orelse
TopicFilter = emqx_placeholder:proc_tmpl(PatternFilter, ClientInfo),
match_topic(emqx_topic:words(Topic), emqx_topic:words(TopicFilter)) orelse
match_topics(ClientInfo, Topic, Filters);
match_topics(ClientInfo, Topic, [TopicFilter | Filters]) ->
match_topic(emqx_topic:words(Topic), TopicFilter) orelse
@ -213,18 +215,3 @@ match_topic(Topic, {'eq', TopicFilter}) ->
Topic =:= TopicFilter;
match_topic(Topic, TopicFilter) ->
emqx_topic:match(Topic, TopicFilter).
feed_var(ClientInfo, Pattern) ->
feed_var(ClientInfo, Pattern, []).
feed_var(_ClientInfo, [], Acc) ->
lists:reverse(Acc);
feed_var(ClientInfo = #{clientid := undefined}, [?PH_CLIENTID | Words], Acc) ->
feed_var(ClientInfo, Words, [?PH_CLIENTID | Acc]);
feed_var(ClientInfo = #{clientid := ClientId}, [?PH_CLIENTID | Words], Acc) ->
feed_var(ClientInfo, Words, [ClientId | Acc]);
feed_var(ClientInfo = #{username := undefined}, [?PH_USERNAME | Words], Acc) ->
feed_var(ClientInfo, Words, [?PH_USERNAME | Acc]);
feed_var(ClientInfo = #{username := Username}, [?PH_USERNAME | Words], Acc) ->
feed_var(ClientInfo, Words, [Username | Acc]);
feed_var(ClientInfo, [W | Words], Acc) ->
feed_var(ClientInfo, Words, [W | Acc]).

View File

@ -35,6 +35,7 @@
]},
publish, [?PH_S_USERNAME, ?PH_S_CLIENTID]}
).
-define(SOURCE6, {allow, {username, "test"}, publish, ["t/foo${username}boo"]}).
all() ->
emqx_common_test_helpers:all(?MODULE).
@ -80,7 +81,7 @@ t_compile(_) ->
{{127, 0, 0, 1}, {127, 0, 0, 1}, 32},
{{192, 168, 1, 0}, {192, 168, 1, 255}, 24}
]},
subscribe, [{pattern, [?PH_CLIENTID]}]},
subscribe, [{pattern, [{var, {var, <<"clientid">>}}]}]},
emqx_authz_rule:compile(?SOURCE3)
),
@ -97,9 +98,18 @@ t_compile(_) ->
{username, {re_pattern, _, _, _, _}},
{clientid, {re_pattern, _, _, _, _}}
]},
publish, [{pattern, [?PH_USERNAME]}, {pattern, [?PH_CLIENTID]}]},
publish, [
{pattern, [{var, {var, <<"username">>}}]}, {pattern, [{var, {var, <<"clientid">>}}]}
]},
emqx_authz_rule:compile(?SOURCE5)
),
?assertEqual(
{allow, {username, {eq, <<"test">>}}, publish, [
{pattern, [{str, <<"t/foo">>}, {var, {var, <<"username">>}}, {str, <<"boo">>}]}
]},
emqx_authz_rule:compile(?SOURCE6)
),
ok.
t_match(_) ->
@ -307,4 +317,24 @@ t_match(_) ->
emqx_authz_rule:compile(?SOURCE5)
)
),
?assertEqual(
nomatch,
emqx_authz_rule:match(
ClientInfo1,
publish,
<<"t/foo${username}boo">>,
emqx_authz_rule:compile(?SOURCE6)
)
),
?assertEqual(
{matched, allow},
emqx_authz_rule:match(
ClientInfo4,
publish,
<<"t/footestboo">>,
emqx_authz_rule:compile(?SOURCE6)
)
),
ok.

View File

@ -0,0 +1,3 @@
Allow the placeholder to be anywhere in the topic for `authz` rules.
e.g:
`{allow, {username, "who"}, publish, ["t/foo${username}boo/${clientid}xxx"]}.`

View File

@ -0,0 +1,3 @@
允许占位符出现在 `authz` 规则中的主题里的任意位置。
例如:
`{allow, {username, "who"}, publish, ["t/foo${username}boo/${clientid}xxx"]}.`