fix(auth): force update default mqtt_user when password or hashtype changed.

This commit is contained in:
zhongwencool 2022-01-12 17:18:12 +08:00
parent 449854fa11
commit 5521b7fa71
3 changed files with 85 additions and 2 deletions

View File

@ -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() ->

View File

@ -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(),
<<SaltBin/binary, (hash(Password, SaltBin, HashType))/binary>>.
@ -192,3 +215,5 @@ auth_username_cli(_) ->
{"user add <Username> <Password>", "Add username auth rule"},
{"user update <Username> <NewPassword>", "Update username auth rule"},
{"user delete <Username>", "Delete username auth rule"}]).
hash_type() ->
application:get_env(emqx_auth_mnesia, password_hash, sha256).

View File

@ -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 => <<Pwd/binary, "bad">>},
#{}, #{hash_type => sha256})),
?assertEqual(Failed,
emqx_auth_mnesia:check(#{clientid => ClientId, username => UserName, password => <<Pwd/binary, "bad">>},
#{}, #{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(),