Merge pull request #9367 from lafirest/feat/kick_when_is_banned

feat(banned): kick session when it is banned by clientid
This commit is contained in:
lafirest 2022-11-16 21:53:56 +08:00 committed by GitHub
commit 780013d5fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 14 deletions

View File

@ -3,7 +3,7 @@
{id, "emqx"},
{description, "EMQX Core"},
% strict semver, bump manually!
{vsn, "5.0.10"},
{vsn, "5.0.11"},
{modules, []},
{registered, []},
{applications, [

View File

@ -21,6 +21,7 @@
-include("emqx.hrl").
-include("logger.hrl").
-include("types.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
%% Mnesia bootstrap
-export([mnesia/1]).
@ -180,7 +181,7 @@ create(#{
create(Banned = #banned{who = Who}) ->
case look_up(Who) of
[] ->
mria:dirty_write(?BANNED_TAB, Banned),
insert_banned(Banned),
{ok, Banned};
[OldBanned = #banned{until = Until}] ->
%% Don't support shorten or extend the until time by overwrite.
@ -190,7 +191,7 @@ create(Banned = #banned{who = Who}) ->
{error, {already_exist, OldBanned}};
%% overwrite expired one is ok.
false ->
mria:dirty_write(?BANNED_TAB, Banned),
insert_banned(Banned),
{ok, Banned}
end
end.
@ -266,3 +267,21 @@ expire_banned_items(Now) ->
ok,
?BANNED_TAB
).
insert_banned(Banned) ->
mria:dirty_write(?BANNED_TAB, Banned),
on_banned(Banned).
on_banned(#banned{who = {clientid, ClientId}}) ->
%% kick the session if the client is banned by clientid
?tp(
warning,
kick_session_due_to_banned,
#{
clientid => ClientId
}
),
emqx_cm:kick_session(ClientId),
ok;
on_banned(_) ->
ok.

View File

@ -21,18 +21,20 @@
-include_lib("emqx/include/emqx.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
all() -> emqx_common_test_helpers:all(?MODULE).
init_per_suite(Config) ->
application:load(emqx),
emqx_common_test_helpers:start_apps([]),
ok = ekka:start(),
Config.
end_per_suite(_Config) ->
ekka:stop(),
mria:stop(),
mria_mnesia:delete_schema().
mria_mnesia:delete_schema(),
emqx_common_test_helpers:stop_apps([]).
t_add_delete(_) ->
Banned = #banned{
@ -111,3 +113,23 @@ t_unused(_) ->
%% expiry timer
timer:sleep(500),
ok = emqx_banned:stop().
t_kick(_) ->
ClientId = <<"client">>,
snabbkaffe:start_trace(),
Now = erlang:system_time(second),
Who = {clientid, ClientId},
emqx_banned:create(#{
who => Who,
by => <<"test">>,
reason => <<"test">>,
at => Now,
until => Now + 120
}),
Trace = snabbkaffe:collect_trace(),
snabbkaffe:stop(),
emqx_banned:delete(Who),
?assertEqual(1, length(?of_kind(kick_session_due_to_banned, Trace))).

View File

@ -640,26 +640,25 @@ test_disable_then_start(_Config) ->
ok.
t_deliver_when_banned(_) ->
ClientId = <<"c1">>,
Client1 = <<"c1">>,
Client2 = <<"c2">>,
{ok, C1} = emqtt:start_link([{clientid, ClientId}, {clean_start, true}, {proto_ver, v5}]),
{ok, C1} = emqtt:start_link([{clientid, Client1}, {clean_start, true}, {proto_ver, v5}]),
{ok, _} = emqtt:connect(C1),
lists:foreach(
fun(I) ->
Topic = erlang:list_to_binary(io_lib:format("retained/~p", [I])),
emqtt:publish(
C1,
Topic,
<<"this is a retained message">>,
[{qos, 0}, {retain, true}]
)
Msg = emqx_message:make(Client2, 0, Topic, <<"this is a retained message">>),
Msg2 = emqx_message:set_flag(retain, Msg),
emqx:publish(Msg2)
end,
lists:seq(1, 3)
),
Now = erlang:system_time(second),
Who = {clientid, ClientId},
Who = {clientid, Client2},
emqx_banned:create(#{
who => Who,
by => <<"test">>,

View File

@ -7,6 +7,9 @@
- Security enhancement for the `subscribe` API [#9355](https://github.com/emqx/emqx/pull/9355).
- Enhance the `banned` feature [#9367](https://github.com/emqx/emqx/pull/9367).
Now the corresponding session will be kicked when client is banned by `clientid`.
## Bug fixes
- Return 404 for status of unknown authenticator in `/authenticator/{id}/status` [#9328](https://github.com/emqx/emqx/pull/9328).

View File

@ -7,6 +7,9 @@
- 增强订阅 API 的安全性 [#9355](https://github.com/emqx/emqx/pull/9355)。
- 增加 `封禁` 功能 [#9367](https://github.com/emqx/emqx/pull/9367)。
现在客户端通过 `clientid` 被封禁时将会踢掉对应的会话。
## 修复
- 通过 `/authenticator/{id}/status` 请求未知认证器的状态时,将会返回 404。