Merge pull request #9475 from zhongwencool/dashboard-password-validate

fix: add dashboard password validation
This commit is contained in:
zhongwencool 2022-12-09 11:17:35 +08:00 committed by GitHub
commit 925787bc59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 9 deletions

View File

@ -7,3 +7,5 @@
- Fixed load bootstrap file when no bootstrap user in `mqtt_app` [#9474](https://github.com/emqx/emqx/pull/9474). - Fixed load bootstrap file when no bootstrap user in `mqtt_app` [#9474](https://github.com/emqx/emqx/pull/9474).
- Trigger `message.dropped` hook when QoS2 message is resend by client with a same packet id, or 'awaiting_rel' queue is full [#9486](https://github.com/emqx/emqx/pull/9486). - Trigger `message.dropped` hook when QoS2 message is resend by client with a same packet id, or 'awaiting_rel' queue is full [#9486](https://github.com/emqx/emqx/pull/9486).
- When dashboard creates a new user, the password length must match 3-32 and the format is `^[A-Za-z0-9]+[A-Za-z0-9-_]*$` [#9475](https://github.com/emqx/emqx-enterprise/pull/9475).

View File

@ -2,9 +2,10 @@
- HTTP 客户端库 `ehttpc``0.2.1` 升级到 `0.4.2` [#9456](https://github.com/emqx/emqx/pull/9456)。 - HTTP 客户端库 `ehttpc``0.2.1` 升级到 `0.4.2` [#9456](https://github.com/emqx/emqx/pull/9456)。
### 修复 ### 修复
- 修复 mqtt_app 表内没有 boostrap user 里未导入用户的问题 [#9474](https://github.com/emqx/emqx/pull/9474). - 修复 mqtt_app 表内没有 boostrap user 里未导入用户的问题 [#9474](https://github.com/emqx/emqx/pull/9474).
- 当 QoS2 消息被重发(使用相同 Packet ID),或当 'awaiting_rel' 队列已满时,触发消息丢弃钩子(`message.dropped`)及计数器 [#9486](https://github.com/emqx/emqx-enterprise/pull/9486)。 - 当 QoS2 消息被重发(使用相同 Packet ID),或当 'awaiting_rel' 队列已满时,触发消息丢弃钩子(`message.dropped`)及计数器 [#9486](https://github.com/emqx/emqx-enterprise/pull/9486)。
- 当控制台创建新用户时,密码长度必须在 3-32 之间,且格式为 `^[A-Za-z0-9]+[A-Za-z0-9-_]*$` [#9475](https://github.com/emqx/emqx-enterprise/pull/9475)。

View File

@ -79,16 +79,17 @@ start_link() ->
-spec(add_user(binary(), binary(), binary()) -> ok | {error, any()}). -spec(add_user(binary(), binary(), binary()) -> ok | {error, any()}).
add_user(Username, Password, Tags) when is_binary(Username), is_binary(Password) -> add_user(Username, Password, Tags) when is_binary(Username), is_binary(Password) ->
case emqx_misc:is_sane_id(Username) of case {emqx_misc:is_sane_id(Username), emqx_misc:is_sane_id(Password, 2, 32)} of
ok -> {ok, ok} ->
Admin = #mqtt_admin{username = Username, password = hash(Password), tags = Tags}, Admin = #mqtt_admin{username = Username, password = hash(Password), tags = Tags},
return(mnesia:transaction(fun add_user_/1, [Admin])); return(mnesia:transaction(fun add_user_/1, [Admin]));
{error, Reason} -> {error, Reason} {{error, Reason}, _} -> {error, Reason};
{_, {error, Reason}} -> {error, Reason}
end. end.
force_add_user(Username, Password, Tags) -> force_add_user(Username, Password, Tags) ->
case emqx_misc:is_sane_id(Username) of case {emqx_misc:is_sane_id(Username), emqx_misc:is_sane_id(Password, 2, 32)} of
ok -> {ok, ok} ->
AddFun = fun() -> AddFun = fun() ->
mnesia:write(#mqtt_admin{username = Username, password = Password, tags = Tags}) mnesia:write(#mqtt_admin{username = Username, password = Password, tags = Tags})
end, end,
@ -96,7 +97,8 @@ force_add_user(Username, Password, Tags) ->
{atomic, ok} -> ok; {atomic, ok} -> ok;
{aborted, Reason} -> {error, Reason} {aborted, Reason} -> {error, Reason}
end; end;
{error, Reason} -> {error, Reason} {{error, Reason}, _} -> {error, Reason};
{_, {error, Reason}} -> {error, Reason}
end. end.
%% @private %% @private

View File

@ -82,6 +82,20 @@ t_overview(_) ->
t_admins_add_delete({init, Config}) -> Config; t_admins_add_delete({init, Config}) -> Config;
t_admins_add_delete({'end', _Config}) -> ok; t_admins_add_delete({'end', _Config}) -> ok;
t_admins_add_delete(_) -> t_admins_add_delete(_) ->
?assertEqual({error,<<"0 < Length =< 256">>},
emqx_dashboard_admin:add_user(<<"">>, <<"password">>, <<"tag1">>)),
?assertEqual({error,<<"2 < Length =< 32">>},
emqx_dashboard_admin:add_user(<<"badusername">>, <<"">>, <<"tag1">>)),
?assertEqual({error,<<"2 < Length =< 32">>},
emqx_dashboard_admin:add_user(<<"badusername">>, <<"p">>, <<"tag1">>)),
P33 = iolist_to_binary(lists:duplicate(33, <<"p">>)),
?assertEqual({error,<<"2 < Length =< 32">>},
emqx_dashboard_admin:add_user(<<"badusername">>, P33, <<"tag1">>)),
P32 = iolist_to_binary(lists:duplicate(32, <<"p">>)),
?assertEqual(ok, emqx_dashboard_admin:add_user(<<"goodusername">>, P32, <<"tag1">>)),
ok = emqx_dashboard_admin:remove_user(<<"goodusername">>),
ok = emqx_dashboard_admin:add_user(<<"username">>, <<"password">>, <<"tag">>), ok = emqx_dashboard_admin:add_user(<<"username">>, <<"password">>, <<"tag">>),
ok = emqx_dashboard_admin:add_user(<<"username1">>, <<"password1">>, <<"tag1">>), ok = emqx_dashboard_admin:add_user(<<"username1">>, <<"password1">>, <<"tag1">>),
ok = emqx_dashboard_admin:add_user(<<"1username1">>, <<"password1">>, <<"tag1">>), ok = emqx_dashboard_admin:add_user(<<"1username1">>, <<"password1">>, <<"tag1">>),

View File

@ -4,6 +4,7 @@
[{"4.4.11", [{"4.4.11",
[{add_module,emqx_cover}, [{add_module,emqx_cover},
{load_module,emqx_relup,brutal_purge,soft_purge,[]}, {load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_misc,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,brutal_purge,soft_purge,[]}, {load_module,emqx_cm,brutal_purge,soft_purge,[]},
{load_module,emqx_session,brutal_purge,soft_purge,[]}, {load_module,emqx_session,brutal_purge,soft_purge,[]},
@ -380,6 +381,7 @@
[{"4.4.11", [{"4.4.11",
[{load_module,emqx_relup,brutal_purge,soft_purge,[]}, [{load_module,emqx_relup,brutal_purge,soft_purge,[]},
{load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]},
{load_module,emqx_misc,brutal_purge,soft_purge,[]},
{load_module,emqx_cm,brutal_purge,soft_purge,[]}, {load_module,emqx_cm,brutal_purge,soft_purge,[]},
{load_module,emqx_channel,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]},
{load_module,emqx_session,brutal_purge,soft_purge,[]}, {load_module,emqx_session,brutal_purge,soft_purge,[]},

View File

@ -59,6 +59,7 @@
]). ]).
-export([ is_sane_id/1 -export([ is_sane_id/1
, is_sane_id/3
]). ]).
-export([ -export([
@ -73,14 +74,21 @@
-spec is_sane_id(list() | binary()) -> ok | {error, Reason::binary()}. -spec is_sane_id(list() | binary()) -> ok | {error, Reason::binary()}.
is_sane_id(Str) -> is_sane_id(Str) ->
is_sane_id(Str, 0, 256).
is_sane_id(Str, Min, Max) ->
StrLen = len(Str), StrLen = len(Str),
case StrLen > 0 andalso StrLen =< 256 of case StrLen > Min andalso StrLen =< Max of
true -> true ->
case re:run(Str, ?VALID_STR_RE) of case re:run(Str, ?VALID_STR_RE) of
nomatch -> {error, <<"required: " ?VALID_STR_RE>>}; nomatch -> {error, <<"required: " ?VALID_STR_RE>>};
_ -> ok _ -> ok
end; end;
false -> {error, <<"0 < Length =< 256">>} false ->
Msg = <<(integer_to_binary(Min))/binary,
<<" < Length =< ">>/binary,
(integer_to_binary(Max))/binary>>,
{error, Msg}
end. end.
len(Bin) when is_binary(Bin) -> byte_size(Bin); len(Bin) when is_binary(Bin) -> byte_size(Bin);