fix(auth_mnesia): don't force update default user.

This commit is contained in:
zhongwencool 2022-01-24 13:43:38 +08:00
parent fcb3ba6cc8
commit efa3e32ee5
5 changed files with 74 additions and 18 deletions

View File

@ -32,27 +32,32 @@
, description/0
]).
-export([match_password/3]).
-export([ match_password/3
, hash_type/0
]).
init(#{clientid_list := ClientidList, username_list := UsernameList}) ->
ok = ekka_mnesia:create_table(?TABLE, [
{disc_copies, [node()]},
{attributes, record_info(fields, emqx_user)},
{storage_properties, [{ets, [{read_concurrency, true}]}]}]),
_ = [ add_default_user({{clientid, iolist_to_binary(Clientid)}, iolist_to_binary(Password)})
|| {Clientid, Password} <- ClientidList],
_ = [ add_default_user({{username, iolist_to_binary(Username)}, iolist_to_binary(Password)})
|| {Username, Password} <- UsernameList],
ok = ekka_mnesia:copy_table(?TABLE, disc_copies).
lists:foreach(fun({Clientid, Password}) ->
emqx_auth_mnesia_cli:add_default_user(clientid, iolist_to_binary(Clientid), iolist_to_binary(Password))
end, ClientidList),
%% @private
add_default_user({Login, Password}) when is_tuple(Login) ->
emqx_auth_mnesia_cli:force_add_user(Login, Password).
lists:foreach(fun({Username, Password}) ->
emqx_auth_mnesia_cli:add_default_user(username, iolist_to_binary(Username), iolist_to_binary(Password))
end, UsernameList),
ok = ekka_mnesia:copy_table(?TABLE, disc_copies).
-spec(register_metrics() -> ok).
register_metrics() ->
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
hash_type() ->
application:get_env(emqx_auth_mnesia, password_hash, sha256).
check(ClientInfo = #{ clientid := Clientid
, password := NPassword
}, AuthResult, #{hash_type := HashType}) ->

View File

@ -57,9 +57,7 @@ load_auth_hook() ->
UsernameList = application:get_env(?APP, username_list, []),
ok = emqx_auth_mnesia:init(#{clientid_list => ClientidList, username_list => UsernameList}),
ok = emqx_auth_mnesia:register_metrics(),
Params = #{
hash_type => application:get_env(emqx_auth_mnesia, password_hash, sha256)
},
Params = #{hash_type => emqx_auth_mnesia:hash_type()},
emqx:hook('client.authenticate', fun emqx_auth_mnesia:check/3, [Params]).
load_acl_hook() ->

View File

@ -23,6 +23,7 @@
%% Auth APIs
-export([ add_user/2
, force_add_user/2
, add_default_user/3
, update_user/2
, remove_user/1
, lookup_user/1
@ -57,6 +58,39 @@ insert_user(User = #emqx_user{login = Login}) ->
[_|_] -> mnesia:abort(existed)
end.
-spec(add_default_user(clientid | username, tuple(), binary()) -> ok | {error, any()}).
add_default_user(Type, Key, Password) ->
Login = {Type, Key},
case add_user(Login, Password) of
ok -> ok;
{error, existed} ->
NewPwd = encrypted_data(Password),
[#emqx_user{password = OldPwd}] = emqx_auth_mnesia_cli:lookup_user(Login),
HashType = emqx_auth_mnesia:hash_type(),
case emqx_auth_mnesia:match_password(NewPwd, HashType, [OldPwd]) of
true -> ok;
false ->
%% We can't force add default,
%% otherwise passwords that have been updated via HTTP API will be reset after reboot.
TypeCtl =
case Type of
clientid -> clientid;
username -> user
end,
?LOG(warning,
"[Auth Mnesia] auth.client.x.~p=~s's password in the emqx_auth_mnesia.conf\n"
"does not match the password in the database(mnesia).\n"
"1. If you have already changed the password via the HTTP API, this warning has no effect.\n"
"You can remove the warning from emqx_auth_mnesia.conf to resolve the warning.\n"
"2. If you just want to update the password by manually changing the configuration file,\n"
"you need to delete the old user and password using `emqx_ctl ~p delete ~s` first\n"
"the new password in emqx_auth_mnesia.conf can take effect after reboot.",
[Type, Key, TypeCtl, Key]),
ok
end;
Error -> Error
end.
force_add_user(Login, Password) ->
User = #emqx_user{
login = Login,
@ -74,7 +108,7 @@ 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
case emqx_auth_mnesia:match_password(NewPwd, emqx_auth_mnesia:hash_type(), [Pwd]) of
true -> ok;
false ->
ok = mnesia:write(User),
@ -136,7 +170,7 @@ ret({atomic, Res}) -> Res;
ret({aborted, Error}) -> {error, Error}.
encrypted_data(Password) ->
HashType = hash_type(),
HashType = emqx_auth_mnesia:hash_type(),
SaltBin = salt(),
<<SaltBin/binary, (hash(Password, SaltBin, HashType))/binary>>.
@ -219,5 +253,3 @@ 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

@ -103,6 +103,17 @@ t_boot(_Config) ->
%% change default pwd
NewPwd = <<"emqx654321">>,
ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia],
fun(_) -> set_default(ClientId, UserName, NewPwd, sha256) end),
?assertEqual(Failed,
emqx_auth_mnesia:check(#{clientid => ClientId, password => NewPwd},
#{}, #{hash_type => sha256})),
?assertEqual(Failed,
emqx_auth_mnesia:check(#{clientid => <<"NotExited">>, username => UserName, password => NewPwd},
#{}, #{hash_type => sha256})),
clean_all_users(),
emqx_ct_helpers:stop_apps([emqx_auth_mnesia]),
ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia],
fun(_) -> set_default(ClientId, UserName, NewPwd, sha256) end),
?assertEqual(Ok,
@ -115,6 +126,17 @@ t_boot(_Config) ->
%% change hash_type
NewPwd2 = <<"emqx6543210">>,
ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia],
fun(_) -> set_default(ClientId, UserName, NewPwd2, plain) end),
?assertEqual(Failed,
emqx_auth_mnesia:check(#{clientid => ClientId, password => NewPwd2},
#{}, #{hash_type => plain})),
?assertEqual(Failed,
emqx_auth_mnesia:check(#{clientid => <<"NotExited">>, username => UserName, password => NewPwd2},
#{}, #{hash_type => plain})),
clean_all_users(),
emqx_ct_helpers:stop_apps([emqx_auth_mnesia]),
ok = emqx_ct_helpers:start_apps([emqx_auth_mnesia],
fun(_) -> set_default(ClientId, UserName, NewPwd2, plain) end),
?assertEqual(Ok,

View File

@ -98,8 +98,7 @@ add_meta(Params, List) ->
page => Page,
limit => Limit,
hasnext => Start + Limit - 1 < Count,
count => Count
},
count => Count},
data => Data,
code => 0
}.