diff --git a/apps/emqx_management/src/emqx_mgmt_auth.erl b/apps/emqx_management/src/emqx_mgmt_auth.erl index 19aa48081..eea93f725 100644 --- a/apps/emqx_management/src/emqx_mgmt_auth.erl +++ b/apps/emqx_management/src/emqx_mgmt_auth.erl @@ -36,7 +36,6 @@ , del_app/1 , list_apps/0 , init_bootstrap_apps/0 - , need_bootstrap/0 , clear_bootstrap_apps/0 ]). @@ -83,21 +82,8 @@ add_default_app() -> end. init_bootstrap_apps() -> - case need_bootstrap() of - true -> - Bootstrap = application:get_env(emqx_management, bootstrap_apps_file, undefined), - init_bootstrap_apps(Bootstrap); - false -> - ok - end. - -need_bootstrap() -> - {atomic, Res} = mnesia:transaction( - fun() -> - Spec = [{#mqtt_app{id = '$1', desc = ?BOOTSTRAP_TAG, _ = '_'}, [], ['$1']}], - mnesia:select(mqtt_app, Spec, 1, read) =:= '$end_of_table' - end), - Res. + Bootstrap = application:get_env(emqx_management, bootstrap_apps_file, undefined), + init_bootstrap_apps(Bootstrap). clear_bootstrap_apps() -> {atomic, ok} = @@ -113,13 +99,7 @@ init_bootstrap_apps(File) -> case file:open(File, [read, binary]) of {ok, Dev} -> {ok, MP} = re:compile(<<"(\.+):(\.+$)">>, [ungreedy]), - case init_bootstrap_apps(File, Dev, MP) of - ok -> ok; - Error -> - %% if failed add bootstrap users, we should clear all bootstrap apps - clear_bootstrap_apps(), - Error - end; + init_bootstrap_apps(File, Dev, MP); {error, Reason} = Error -> ?LOG(error, "failed to open the mgmt bootstrap apps file(~s) for ~p", @@ -145,8 +125,8 @@ add_bootstrap_app(File, Dev, MP, Line) -> case re:run(Bin, MP, [global, {capture, all_but_first, binary}]) of {match, [[AppId, AppSecret]]} -> Name = <<"bootstraped">>, - case add_app(AppId, Name, AppSecret, ?BOOTSTRAP_TAG, true, undefined) of - {ok, _} -> + case force_add_app(AppId, Name, AppSecret, ?BOOTSTRAP_TAG, true, undefined) of + ok -> add_bootstrap_app(File, Dev, MP, Line + 1); {error, Reason} -> throw(#{file => File, line => Line, content => Bin, reason => Reason}) diff --git a/apps/emqx_management/test/emqx_auth_mnesia_data_export_import_SUITE.erl b/apps/emqx_management/test/emqx_auth_mnesia_data_export_import_SUITE.erl index da27fa2ee..dc9a3e19f 100644 --- a/apps/emqx_management/test/emqx_auth_mnesia_data_export_import_SUITE.erl +++ b/apps/emqx_management/test/emqx_auth_mnesia_data_export_import_SUITE.erl @@ -66,6 +66,70 @@ t_importee430(_) -> {ok, _} = emqx_mgmt_data_backup:export(), remove_all_users_and_acl(). +t_import_test(_) -> + SimpleAdmin = <<"simpleAdmin">>, + SimplePassword = <<"simplepassword">>, + SimplePasswordHash = emqx_dashboard_admin:hash(SimplePassword), + + Admins = [<<"Admin1">>, <<"Admin2">>, <<"Admin3">>, <<"Admin4">>, <<"Admin5">>], + Passwords = [<<"password1">>, <<"PAssword2">>,<<"3&*)dkdKlkd">>,<<"&*qwl4kd>">>,<<"PASSWORD5D">>], + + %% add some users + add_admins(Admins, Passwords), + %% Allow force import simple password. + ok = emqx_dashboard_admin:force_add_user(SimpleAdmin, SimplePasswordHash, <<"test">>), + + ct:pal("1111~p~n", [ets:info(mqtt_admin)]), + ct:pal("~p~n", [ets:tab2list(mqtt_admin)]), + check_admins_ok(Admins, Passwords), + + {ok, #{filename := FileName}} = emqx_mgmt_data_backup:export(), + + remove_admins(Admins), + ok = emqx_dashboard_admin:remove_user(SimpleAdmin), + ct:pal("0000~n"), + check_admins_failed(Admins, Passwords), + {error, _} = emqx_dashboard_admin:check(SimpleAdmin, SimplePassword), + + ok = emqx_mgmt_data_backup:import(FileName, <<"{}">>), + ct:pal("2222~n"), + check_admins_ok(Admins, Passwords), + ok = emqx_dashboard_admin:check(SimpleAdmin, SimplePassword), + + remove_admins(Admins), + ok = emqx_dashboard_admin:remove_user(SimpleAdmin), + + remove_all_users_and_acl(), + ok. + +add_admins(Admins, Passwords) -> + lists:foreach( + fun({Admin, Password}) -> + ok = emqx_dashboard_admin:add_user(Admin, Password, <<"test">>) + end, lists:zip(Admins, Passwords)), + ok. + +check_admins_ok(Admins, Passwords) -> + lists:foreach( + fun({Admin, Password}) -> + ?assertMatch(ok, emqx_dashboard_admin:check(Admin, Password), {Admin, Password}) + end, lists:zip(Admins, Passwords)), + ok. + +check_admins_failed(Admins, Passwords) -> + lists:foreach( + fun({Admin, Password}) -> + ?assertMatch({error, _}, emqx_dashboard_admin:check(Admin, Password), {Admin, Password}) + end, lists:zip(Admins, Passwords)), + ok. + +remove_admins(Admins) -> + lists:foreach( + fun(Admin) -> + ok = emqx_dashboard_admin:remove_user(Admin) + end, Admins), + ok. + remove_all_users_and_acl() -> mnesia:delete_table(emqx_user), mnesia:delete_table(emqx_acl). diff --git a/apps/emqx_management/test/emqx_mgmt_bootstrap_app_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_bootstrap_app_SUITE.erl index d2c12cc39..734ec8e5e 100644 --- a/apps/emqx_management/test/emqx_mgmt_bootstrap_app_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_bootstrap_app_SUITE.erl @@ -68,10 +68,10 @@ t_load_ok(_) -> ok = file:write_file(File, Bin1), application:set_env(emqx_management, bootstrap_apps_file, File), {ok, _} = application:ensure_all_started(emqx_management), - ?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"secret-1">>)), - ?assert(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"secret-2">>)), - ?assertNot(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"new-secret-1">>)), - ?assertNot(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"new-secret-2">>)), + ?assertNot(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"secret-1">>)), + ?assertNot(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"secret-2">>)), + ?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"new-secret-1">>)), + ?assert(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"new-secret-2">>)), application:stop(emqx_management). t_bootstrap_user_file_not_found(_) -> @@ -84,13 +84,17 @@ t_load_invalid_username_failed(_) -> File = "./bootstrap_apps.txt", ok = file:write_file(File, Bin), check_load_failed(File), + ?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"password-1">>)), + ?assertNot(emqx_mgmt_auth:is_authorized(<<"test&2">>, <<"password-2">>)), ok. t_load_invalid_format_failed(_) -> - Bin = <<"test-1:password-1\ntest-2password-2">>, + Bin = <<"test-1:password-1\ntest-2 password-2">>, File = "./bootstrap_apps.txt", ok = file:write_file(File, Bin), check_load_failed(File), + ?assert(emqx_mgmt_auth:is_authorized(<<"test-1">>, <<"password-1">>)), + ?assertNot(emqx_mgmt_auth:is_authorized(<<"test-2">>, <<"password-2">>)), ok. check_load_failed(File) -> @@ -98,5 +102,4 @@ check_load_failed(File) -> application:stop(emqx_management), application:set_env(emqx_management, bootstrap_apps_file, File), ?assertMatch({error, _}, application:ensure_all_started(emqx_management)), - ?assertNot(lists:member(emqx_management, application:which_applications())), - ?assert(emqx_mgmt_auth:need_bootstrap()). + ?assertNot(lists:member(emqx_management, application:which_applications())). diff --git a/changes/v4.4.14-en.md b/changes/v4.4.14-en.md new file mode 100644 index 000000000..c4a0cb64d --- /dev/null +++ b/changes/v4.4.14-en.md @@ -0,0 +1,11 @@ +# v4.4.14 + +## Enhancements +- Add a password complexity requirement when adding or modifying Dashboard users via the API. Now passwords must contain at least 2 of alphabetic, numeric and special characters, and must be 8 to 64 characters long [#1696](https://github.com/emqx/emqx-enterprise/pull/1696). + +## Bug fixes + +- Fix dashboard password validator is too simple. Now dashboard password must contain at least two different kind of characters from groups of letters, numbers and special characters. [#1696](https://github.com/emqx/emqx-enterprise/pull/1696). +- Fix the problem that adding or importing Dashboard users via the API fails to add complex passwords due to incorrect checksum of the passwords [#1696](https://github.com/emqx/emqx-enterprise/pull/1696). + +- Fix load bootstrap_app_file's apps is not sync when reboot. [#1697](https://github.com/emqx/emqx-enterprise/pull/1697). diff --git a/changes/v4.4.14-zh.md b/changes/v4.4.14-zh.md new file mode 100644 index 000000000..0d6679046 --- /dev/null +++ b/changes/v4.4.14-zh.md @@ -0,0 +1,11 @@ +# v4.4.14 + +## 增强 + +- 通过 API 添加、修改 Dashboard 用户时,增加对密码复杂度的要求。现在密码必须包含字母、数字以及特殊字符中的至少 2 种,并且长度范围必须是 8~64 个字符 [#1696](https://github.com/emqx/emqx-enterprise/pull/1696)。 + +## 修复 + +- 修复通过 API 添加或者导入 Dashboard 用户时,对密码进行了错误的校验,导致复杂密码添加失败的问题 [#1696](https://github.com/emqx/emqx-enterprise/pull/1696)。 + +- 修复 boostrap_apps_file 文件更新后没有同步更新至数据库导致文件中新加 apps 未生效 [#1697](https://github.com/emqx/emqx-enterprise/pull/1697)。