From 5521b7fa71a6070709a28fa073f9009aa5f92d4f Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Wed, 12 Jan 2022 17:18:12 +0800 Subject: [PATCH 1/8] fix(auth): force update default mqtt_user when password or hashtype changed. --- .../emqx_auth_mnesia/src/emqx_auth_mnesia.erl | 4 +- .../src/emqx_auth_mnesia_cli.erl | 27 ++++++++- .../test/emqx_auth_mnesia_SUITE.erl | 56 +++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl index 905bcaaf0..74c7c71ee 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.erl @@ -32,6 +32,8 @@ , description/0 ]). +-export([match_password/3]). + init(#{clientid_list := ClientidList, username_list := UsernameList}) -> ok = ekka_mnesia:create_table(?TABLE, [ {disc_copies, [node()]}, @@ -45,7 +47,7 @@ init(#{clientid_list := ClientidList, username_list := UsernameList}) -> %% @private add_default_user({Login, Password}) when is_tuple(Login) -> - emqx_auth_mnesia_cli:add_user(Login, Password). + emqx_auth_mnesia_cli:force_add_user(Login, Password). -spec(register_metrics() -> ok). register_metrics() -> diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl index d89e6836c..72a932aa1 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl @@ -22,6 +22,7 @@ -define(TABLE, emqx_user). %% Auth APIs -export([ add_user/2 + , force_add_user/2 , update_user/2 , remove_user/1 , lookup_user/1 @@ -56,6 +57,28 @@ insert_user(User = #emqx_user{login = Login}) -> [_|_] -> mnesia:abort(existed) end. +force_add_user(Login, Password) -> + User = #emqx_user{ + login = Login, + password = encrypted_data(Password), + created_at = erlang:system_time(millisecond) + }, + ret(mnesia:transaction(fun insert_or_update_user/2, [Password, User])). + +insert_or_update_user(NewPwd, User = #emqx_user{login = Login}) -> + case mnesia:read(?TABLE, Login) of + [] -> mnesia:write(User); + [#emqx_user{password = Pwd}] -> + case emqx_auth_mnesia:match_password(NewPwd, hash_type(), [Pwd]) of + true -> ok; + false -> + Res = mnesia:write(User), + ?LOG(warning, "[Mnesia] (~p)'s password has be updated.", [Login]), + Res + end + end. + + %% @doc Update User -spec(update_user(tuple(), binary()) -> ok | {error, any()}). update_user(Login, NewPassword) -> @@ -109,7 +132,7 @@ ret({atomic, ok}) -> ok; ret({aborted, Error}) -> {error, Error}. encrypted_data(Password) -> - HashType = application:get_env(emqx_auth_mnesia, password_hash, sha256), + HashType = hash_type(), SaltBin = salt(), <>. @@ -192,3 +215,5 @@ auth_username_cli(_) -> {"user add ", "Add username auth rule"}, {"user update ", "Update username auth rule"}, {"user delete ", "Delete username auth rule"}]). +hash_type() -> + application:get_env(emqx_auth_mnesia, password_hash, sha256). diff --git a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl index c5c0eb727..01dff1488 100644 --- a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl @@ -46,11 +46,15 @@ all() -> groups() -> []. +init_per_suite(t_boot) -> + ok; init_per_suite(Config) -> ok = emqx_ct_helpers:start_apps([emqx_management, emqx_auth_mnesia], fun set_special_configs/1), create_default_app(), Config. +end_per_suite(t_boot) -> + ok; end_per_suite(_Config) -> delete_default_app(), emqx_ct_helpers:stop_apps([emqx_management, emqx_auth_mnesia]). @@ -65,10 +69,62 @@ set_special_configs(emqx) -> set_special_configs(_App) -> ok. +set_default(ClientId, UserName, Pwd, HashType) -> + application:set_env(emqx_auth_mnesia, clientid_list, [{ClientId, Pwd}]), + application:set_env(emqx_auth_mnesia, username_list, [{UserName, Pwd}]), + application:set_env(emqx_auth_mnesia, password_hash, HashType), + ok. %%------------------------------------------------------------------------------ %% Testcases %%------------------------------------------------------------------------------ +t_boot(_Config) -> + clean_all_users(), + emqx_ct_helpers:stop_apps([emqx_auth_mnesia]), + ClientId = <<"clientid-test">>, + UserName = <<"username-test">>, + Pwd = <<"emqx123456">>, + ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia], + fun(_) -> set_default(ClientId, UserName, Pwd, sha256) end), + Ok = {stop, #{anonymous => false, auth_result => success}}, + Failed = {stop, #{anonymous => false, auth_result => password_error}}, + ?assertEqual(Ok, + emqx_auth_mnesia:check(#{clientid => ClientId, password => Pwd}, #{}, #{hash_type => sha256})), + ?assertEqual(Ok, + emqx_auth_mnesia:check(#{clientid => <<"NotExited">>, username => UserName, password => Pwd}, + #{}, #{hash_type => sha256})), + ?assertEqual(Failed, + emqx_auth_mnesia:check(#{clientid => ClientId, password => <>}, + #{}, #{hash_type => sha256})), + ?assertEqual(Failed, + emqx_auth_mnesia:check(#{clientid => ClientId, username => UserName, password => <>}, + #{}, #{hash_type => sha256})), + emqx_ct_helpers:stop_apps([emqx_auth_mnesia]), + + %% change default pwd + NewPwd = <<"emqx654321">>, + ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia], + fun(_) -> set_default(ClientId, UserName, NewPwd, sha256) end), + ?assertEqual(Ok, + emqx_auth_mnesia:check(#{clientid => ClientId, password => NewPwd}, + #{}, #{hash_type => sha256})), + ?assertEqual(Ok, + emqx_auth_mnesia:check(#{clientid => <<"NotExited">>, username => UserName, password => NewPwd}, + #{}, #{hash_type => sha256})), + emqx_ct_helpers:stop_apps([emqx_auth_mnesia]), + + %% change hash_type + NewPwd2 = <<"emqx6543210">>, + ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia], + fun(_) -> set_default(ClientId, UserName, NewPwd2, plain) end), + ?assertEqual(Ok, + emqx_auth_mnesia:check(#{clientid => ClientId, password => NewPwd2}, + #{}, #{hash_type => plain})), + ?assertEqual(Ok, + emqx_auth_mnesia:check(#{clientid => <<"NotExited">>, username => UserName, password => NewPwd2}, + #{}, #{hash_type => plain})), + ok. + t_management(_Config) -> clean_all_users(), From 88060c0f9b634e2fa80ec4414c628079008edd30 Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Wed, 12 Jan 2022 17:34:32 +0800 Subject: [PATCH 2/8] chore(auth): bump emqx_auth_mnesia version:4.3.5 --- apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src | 2 +- apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src index b15c7fdd3..d782f0272 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.app.src @@ -1,6 +1,6 @@ {application, emqx_auth_mnesia, [{description, "EMQ X Authentication with Mnesia"}, - {vsn, "4.3.4"}, % strict semver, bump manually + {vsn, "4.3.5"}, % strict semver, bump manually {modules, []}, {registered, []}, {applications, [kernel,stdlib,mnesia]}, diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src index 82df99b3a..2a6353760 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src @@ -7,10 +7,14 @@ {update, emqx_auth_mnesia_sup, supervisor}, {apply, {emqx_acl_mnesia_migrator, start_supervised, []}}, {load_module,emqx_auth_mnesia_api, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia, brutal_purge,soft_purge,[]}, + {load_module,emqx_acl_mnesia, brutal_purge, soft_purge,[]}, {load_module,emqx_acl_mnesia_api, brutal_purge,soft_purge,[]}, {load_module,emqx_acl_mnesia_cli, brutal_purge,soft_purge,[]} ]}, + {<<"4.3.4">>, [ + {load_module,emqx_auth_mnesia, brutal_purge, soft_purge,[]}, + {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]}, + ]}, {<<".*">>, [ ]} ], @@ -25,6 +29,10 @@ {delete_module,emqx_acl_mnesia_migrator}, {delete_module,emqx_acl_mnesia_db} ]}, + {<<"4.3.4">>, [ + {load_module,emqx_auth_mnesia, brutal_purge, soft_purge,[]}, + {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]}, + ]}, {<<".*">>, [ ]} ] From 85d568be602c94d6e99a00f63b9fc30c7429f4b5 Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Wed, 12 Jan 2022 18:46:05 +0800 Subject: [PATCH 3/8] chore(test): clean up auth_mnesia_SUITE:t_boot config --- apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src | 10 +++++----- apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src index 2a6353760..95a0c1877 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia.appup.src @@ -7,13 +7,13 @@ {update, emqx_auth_mnesia_sup, supervisor}, {apply, {emqx_acl_mnesia_migrator, start_supervised, []}}, {load_module,emqx_auth_mnesia_api, brutal_purge,soft_purge,[]}, - {load_module,emqx_acl_mnesia, brutal_purge, soft_purge,[]}, + {load_module,emqx_acl_mnesia, brutal_purge,soft_purge,[]}, {load_module,emqx_acl_mnesia_api, brutal_purge,soft_purge,[]}, {load_module,emqx_acl_mnesia_cli, brutal_purge,soft_purge,[]} ]}, {<<"4.3.4">>, [ - {load_module,emqx_auth_mnesia, brutal_purge, soft_purge,[]}, - {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia, brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]} ]}, {<<".*">>, [ ]} @@ -30,8 +30,8 @@ {delete_module,emqx_acl_mnesia_db} ]}, {<<"4.3.4">>, [ - {load_module,emqx_auth_mnesia, brutal_purge, soft_purge,[]}, - {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia, brutal_purge,soft_purge,[]}, + {load_module,emqx_auth_mnesia_cli, brutal_purge,soft_purge,[]} ]}, {<<".*">>, [ ]} diff --git a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl index 01dff1488..4246965d9 100644 --- a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl @@ -73,6 +73,7 @@ set_default(ClientId, UserName, Pwd, HashType) -> application:set_env(emqx_auth_mnesia, clientid_list, [{ClientId, Pwd}]), application:set_env(emqx_auth_mnesia, username_list, [{UserName, Pwd}]), application:set_env(emqx_auth_mnesia, password_hash, HashType), + application:set_env(emqx_auth_mnesia, password_hash, HashType), ok. %%------------------------------------------------------------------------------ %% Testcases @@ -123,6 +124,7 @@ t_boot(_Config) -> ?assertEqual(Ok, emqx_auth_mnesia:check(#{clientid => <<"NotExited">>, username => UserName, password => NewPwd2}, #{}, #{hash_type => plain})), + clean_all_users(), ok. t_management(_Config) -> From 27f5e765b584e51f5476bd602610a7c4d1e479f7 Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Thu, 13 Jan 2022 13:53:37 +0800 Subject: [PATCH 4/8] fix(export): emqx_auth_mnesia import failed after 4.3.x --- .../test/emqx_auth_mnesia_SUITE.erl | 1 - .../src/emqx_mgmt_data_backup.erl | 20 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl index 4246965d9..12b473815 100644 --- a/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl +++ b/apps/emqx_auth_mnesia/test/emqx_auth_mnesia_SUITE.erl @@ -73,7 +73,6 @@ set_default(ClientId, UserName, Pwd, HashType) -> application:set_env(emqx_auth_mnesia, clientid_list, [{ClientId, Pwd}]), application:set_env(emqx_auth_mnesia, username_list, [{UserName, Pwd}]), application:set_env(emqx_auth_mnesia, password_hash, HashType), - application:set_env(emqx_auth_mnesia, password_hash, HashType), ok. %%------------------------------------------------------------------------------ %% Testcases diff --git a/apps/emqx_management/src/emqx_mgmt_data_backup.erl b/apps/emqx_management/src/emqx_mgmt_data_backup.erl index 6e467a8ba..d17167785 100644 --- a/apps/emqx_management/src/emqx_mgmt_data_backup.erl +++ b/apps/emqx_management/src/emqx_mgmt_data_backup.erl @@ -602,7 +602,7 @@ import(Filename, OverridesJson) -> Overrides = emqx_json:decode(OverridesJson, [return_maps]), Data = maps:merge(Imported, Overrides), Version = to_version(maps:get(<<"version">>, Data)), - read_global_auth_type(Data), + read_global_auth_type(Data, Version), try do_import_data(Data, Version), logger:debug("The emqx data has been imported successfully"), @@ -621,7 +621,7 @@ import(Filename, OverridesJson) -> Overrides = emqx_json:decode(OverridesJson, [return_maps]), Data = maps:merge(Imported, Overrides), Version = to_version(maps:get(<<"version">>, Data)), - read_global_auth_type(Data), + read_global_auth_type(Data, Version), case is_version_supported(Data, Version) of true -> try @@ -696,17 +696,17 @@ is_version_supported2(Version) -> end. -endif. -read_global_auth_type(Data) -> +read_global_auth_type(Data, Version) -> case {maps:get(<<"auth_mnesia">>, Data, []), maps:get(<<"acl_mnesia">>, Data, [])} of {[], []} -> %% Auth mnesia plugin is not used: ok; _ -> - do_read_global_auth_type(Data) + do_read_global_auth_type(Data, Version) end. -ifdef(EMQX_ENTERPRISE). -do_read_global_auth_type(Data) -> +do_read_global_auth_type(Data, _Version) -> case Data of #{<<"auth.mnesia.as">> := <<"username">>} -> application:set_env(emqx_auth_mnesia, as, username); @@ -717,13 +717,15 @@ do_read_global_auth_type(Data) -> end. -else. -do_read_global_auth_type(Data) -> +do_read_global_auth_type(Data, FromVersion) -> case Data of #{<<"auth.mnesia.as">> := <<"username">>} -> application:set_env(emqx_auth_mnesia, as, username); #{<<"auth.mnesia.as">> := <<"clientid">>} -> application:set_env(emqx_auth_mnesia, as, clientid); - _ -> + _ when FromVersion =:= "4.0" orelse + FromVersion =:= "4.1" orelse + FromVersion =:= "4.2"-> logger:error("While importing data from EMQX versions prior to 4.3 " "it is necessary to specify the value of \"auth.mnesia.as\" parameter " "as it was configured in etc/plugins/emqx_auth_mnesia.conf.\n" @@ -732,7 +734,9 @@ do_read_global_auth_type(Data) -> "or\n" " $ emqx_ctl data import --env '{\"auth.mnesia.as\":\"clientid\"}'", []), - error(import_failed) + error(import_failed); + _ -> + ok end. -endif. From e96c9ada52049b8210f39eec2939a9956e768280 Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Thu, 13 Jan 2022 16:26:32 +0800 Subject: [PATCH 5/8] chore(test): fix typo error --- apps/emqx_management/test/emqx_mgmt_api_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl index e45acfd42..bbec02722 100644 --- a/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_api_SUITE.erl @@ -583,7 +583,7 @@ t_data(_) -> ?assertMatch({ok, _}, request_api(post, api_path(["data","import"]), [], auth_header_(), #{<<"filename">> => Filename, <<"node">> => Node})), ?assertMatch({ok, _}, request_api(post, api_path(["data","import"]), [], auth_header_(), #{<<"filename">> => Filename})), application:stop(emqx_rule_engine), - application:stop(emqx_dahboard), + application:stop(emqx_dashboard), ok. t_data_import_content(_) -> @@ -598,7 +598,7 @@ t_data_import_content(_) -> Content = emqx_json:decode(Bin), ?assertMatch({ok, "{\"code\":0}"}, request_api(post, api_path(["data","import"]), [], auth_header_(), Content)), application:stop(emqx_rule_engine), - application:stop(emqx_dahboard). + application:stop(emqx_dashboard). request_api(Method, Url, Auth) -> request_api(Method, Url, [], Auth, []). From 9a17bcfcc9ac64327e036cea52786d835ca0f33b Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Fri, 14 Jan 2022 11:03:27 +0800 Subject: [PATCH 6/8] chore(appup): update eqmx.appup.src --- src/emqx.appup.src | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/emqx.appup.src b/src/emqx.appup.src index c4885b7b1..f50a52e74 100644 --- a/src/emqx.appup.src +++ b/src/emqx.appup.src @@ -1,7 +1,8 @@ %% -*- mode: erlang -*- {VSN, [{"4.3.12", - [{load_module,emqx_channel,brutal_purge,soft_purge,[]}]}, + [{load_module,emqx_channel,brutal_purge,soft_purge,[]}, + {load_module,emqx_alarm,brutal_purge,soft_purge,[]}]}, {"4.3.11", [{load_module,emqx_connection,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]}, @@ -199,7 +200,8 @@ {load_module,emqx_app,brutal_purge,soft_purge,[]}]}, {<<".*">>,[]}], [{"4.3.12", - [{load_module,emqx_channel,brutal_purge,soft_purge,[]}]}, + [{load_module,emqx_channel,brutal_purge,soft_purge,[]}, + {load_module,emqx_alarm,brutal_purge,soft_purge,[]}]}, {"4.3.11", [{load_module,emqx_connection,brutal_purge,soft_purge,[]}, {load_module,emqx_channel,brutal_purge,soft_purge,[]}, From 4ba43d3aeacb54485ea7a29ecdd1680db700cf22 Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Fri, 14 Jan 2022 11:37:47 +0800 Subject: [PATCH 7/8] fix(auth): move log outside of transaction --- apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl index 72a932aa1..55e3e4966 100644 --- a/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl +++ b/apps/emqx_auth_mnesia/src/emqx_auth_mnesia_cli.erl @@ -63,7 +63,12 @@ force_add_user(Login, Password) -> password = encrypted_data(Password), created_at = erlang:system_time(millisecond) }, - ret(mnesia:transaction(fun insert_or_update_user/2, [Password, User])). + case ret(mnesia:transaction(fun insert_or_update_user/2, [Password, User])) of + {ok, override} -> + ?LOG(warning, "[Mnesia] (~p)'s password has be updated.", [Login]), + ok; + Other -> Other + end. insert_or_update_user(NewPwd, User = #emqx_user{login = Login}) -> case mnesia:read(?TABLE, Login) of @@ -72,9 +77,8 @@ insert_or_update_user(NewPwd, User = #emqx_user{login = Login}) -> case emqx_auth_mnesia:match_password(NewPwd, hash_type(), [Pwd]) of true -> ok; false -> - Res = mnesia:write(User), - ?LOG(warning, "[Mnesia] (~p)'s password has be updated.", [Login]), - Res + ok = mnesia:write(User), + {ok, override} end end. @@ -128,7 +132,7 @@ comparing({?TABLE, _, _, CreatedAt1}, {?TABLE, _, _, CreatedAt2}) -> CreatedAt1 >= CreatedAt2. -ret({atomic, ok}) -> ok; +ret({atomic, Res}) -> Res; ret({aborted, Error}) -> {error, Error}. encrypted_data(Password) -> From 5481723513d5d899fee4ef9f8b1c9efd2d223c8a Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Fri, 14 Jan 2022 14:55:31 +0800 Subject: [PATCH 8/8] chore(docs): update changes-4.3.md --- CHANGES-4.3.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES-4.3.md b/CHANGES-4.3.md index a442ff6c8..0e293d898 100644 --- a/CHANGES-4.3.md +++ b/CHANGES-4.3.md @@ -10,6 +10,13 @@ File format: - One list item per change topic Change log ends with a list of github PRs +## v4.3.12 +### Important changes + +### Minor changes +* Fix updating `emqx_auth_mnesia.conf` password and restarting the new password does not take effect [#6717] +* Fix import data crash when emqx_auth_mnesia's record is not empty [#6717] + ## v4.3.11 Important notes: