diff --git a/apps/emqx_management/src/emqx_management.app.src b/apps/emqx_management/src/emqx_management.app.src index 3eb690bdb..fe927c097 100644 --- a/apps/emqx_management/src/emqx_management.app.src +++ b/apps/emqx_management/src/emqx_management.app.src @@ -1,6 +1,6 @@ {application, emqx_management, [{description, "EMQ X Management API and CLI"}, - {vsn, "4.4.11"}, % strict semver, bump manually! + {vsn, "4.4.12"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_management_sup]}, {applications, [kernel,stdlib,emqx_plugin_libs,minirest]}, 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/apps/emqx_rule_engine/src/emqx_rule_engine.app.src b/apps/emqx_rule_engine/src/emqx_rule_engine.app.src index 8c1feb42f..99dfb77a8 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.app.src +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.app.src @@ -1,6 +1,6 @@ {application, emqx_rule_engine, [{description, "EMQ X Rule Engine"}, - {vsn, "4.4.13"}, % strict semver, bump manually! + {vsn, "4.4.14"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_rule_engine_sup, emqx_rule_registry, emqx_rule_engine_jwt_sup]}, {applications, [kernel,stdlib,rulesql,getopt,jose]}, diff --git a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src index 6a11776ed..544e21d30 100644 --- a/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src +++ b/apps/emqx_rule_engine/src/emqx_rule_engine.appup.src @@ -1,7 +1,8 @@ %% -*- mode: erlang -*- %% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{"4.4.12", + [{"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, + {"4.4.12", [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]}, {update,emqx_rule_engine_jwt_sup,supervisor}, @@ -220,7 +221,8 @@ {load_module,emqx_rule_engine,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_runtime,brutal_purge,soft_purge,[]}]}, {<<".*">>,[]}], - [{"4.4.12", + [{"4.4.13",[{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}]}, + {"4.4.12", [{load_module,emqx_rule_registry,brutal_purge,soft_purge,[]}, {load_module,emqx_rule_engine_jwt_worker,brutal_purge,soft_purge,[]}, {update,emqx_rule_engine_jwt_sup,supervisor}, 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)。 diff --git a/data/relup-paths.eterm b/data/relup-paths.eterm index c72c4bc50..1f075e888 100644 --- a/data/relup-paths.eterm +++ b/data/relup-paths.eterm @@ -57,7 +57,14 @@ <<"4.4.2">>,<<"4.4.3">>,<<"4.4.4">>,<<"4.4.5">>,<<"4.4.6">>, <<"4.4.7">>,<<"4.4.8">>,<<"4.4.9">>], otp => <<"24.3.4.2-1">>}}. +{<<"4.4.14">>, + #{from_versions => + [<<"4.4.0">>,<<"4.4.1">>,<<"4.4.10">>,<<"4.4.11">>,<<"4.4.12">>, + <<"4.4.13">>,<<"4.4.2">>,<<"4.4.3">>,<<"4.4.4">>,<<"4.4.5">>, + <<"4.4.6">>,<<"4.4.7">>,<<"4.4.8">>,<<"4.4.9">>], + otp => <<"24.3.4.2-1">>}}. {<<"4.5.0">>, #{from_versions => - [<<"4.4.10">>,<<"4.4.11">>,<<"4.4.13">>,<<"4.4.8">>,<<"4.4.9">>], + [<<"4.4.10">>,<<"4.4.11">>,<<"4.4.13">>,<<"4.4.14">>,<<"4.4.8">>, + <<"4.4.9">>], otp => <<"24.3.4.2-1">>}}. diff --git a/deploy/charts/emqx/Chart.yaml b/deploy/charts/emqx/Chart.yaml index 523793eef..092af1ab7 100644 --- a/deploy/charts/emqx/Chart.yaml +++ b/deploy/charts/emqx/Chart.yaml @@ -13,8 +13,8 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. -version: 4.4.13 +version: 4.4.14 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. -appVersion: 4.4.13 +appVersion: 4.4.14 diff --git a/include/emqx_release.hrl b/include/emqx_release.hrl index f31e4650b..f3d8a27da 100644 --- a/include/emqx_release.hrl +++ b/include/emqx_release.hrl @@ -29,7 +29,7 @@ -ifndef(EMQX_ENTERPRISE). --define(EMQX_RELEASE, {opensource, "4.4.13"}). +-define(EMQX_RELEASE, {opensource, "4.4.14"}). -else. diff --git a/lib-ce/emqx_dashboard/src/emqx_dashboard.app.src b/lib-ce/emqx_dashboard/src/emqx_dashboard.app.src index 38a5ee5a2..37b805ca3 100644 --- a/lib-ce/emqx_dashboard/src/emqx_dashboard.app.src +++ b/lib-ce/emqx_dashboard/src/emqx_dashboard.app.src @@ -1,6 +1,6 @@ {application, emqx_dashboard, [{description, "EMQX Web Dashboard"}, - {vsn, "4.4.12"}, % strict semver, bump manually! + {vsn, "4.4.13"}, % strict semver, bump manually! {modules, []}, {registered, [emqx_dashboard_sup]}, {applications, [kernel,stdlib,mnesia,minirest]}, diff --git a/src/emqx.app.src b/src/emqx.app.src index 6d9aeb76f..1f75f4220 100644 --- a/src/emqx.app.src +++ b/src/emqx.app.src @@ -6,7 +6,7 @@ %% the emqx `release' version, which in turn is comprised of several %% apps, one of which is this. See `emqx_release.hrl' for more %% info. - {vsn, "4.4.13"}, % strict semver, bump manually! + {vsn, "4.4.14"}, % strict semver, bump manually! {modules, []}, {registered, []}, {applications, [ kernel diff --git a/src/emqx.appup.src b/src/emqx.appup.src index b8cbdf684..69feb6a5d 100644 --- a/src/emqx.appup.src +++ b/src/emqx.appup.src @@ -1,7 +1,11 @@ %% -*- mode: erlang -*- %% Unless you know what you are doing, DO NOT edit manually!! {VSN, - [{"4.4.12", + [{"4.4.13", + [{load_module,emqx_cm,brutal_purge,soft_purge,[]}, + {load_module,emqx_relup,brutal_purge,soft_purge,[]}, + {load_module,emqx_app,brutal_purge,soft_purge,[]}]}, + {"4.4.12", [{load_module,emqx_cm,brutal_purge,soft_purge,[]}, {load_module,emqx_relup,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]}, @@ -393,7 +397,11 @@ {apply,{application,set_env, [gen_rpc,insecure_auth_fallback_allowed,true]}}]}, {<<".*">>,[]}], - [{"4.4.12", + [{"4.4.13", + [{load_module,emqx_cm,brutal_purge,soft_purge,[]}, + {load_module,emqx_relup,brutal_purge,soft_purge,[]}, + {load_module,emqx_app,brutal_purge,soft_purge,[]}]}, + {"4.4.12", [{load_module,emqx_cm,brutal_purge,soft_purge,[]}, {load_module,emqx_relup,brutal_purge,soft_purge,[]}, {load_module,emqx_app,brutal_purge,soft_purge,[]}]},