feat(dashboard): dashboard admin password persistence
This commit is contained in:
parent
a9255032cd
commit
b3de664c64
|
@ -158,7 +158,8 @@ update_pwd(Username, Fun) ->
|
|||
lookup_user(Username) when is_binary(Username) ->
|
||||
case binenv(default_user_username) of
|
||||
Username ->
|
||||
[#mqtt_admin{username=Username, password=hashed_default_passwd()}];
|
||||
Password = hashed_default_passwd(),
|
||||
[#mqtt_admin{username=Username, password=Password, tags= <<"administrator">>}];
|
||||
_ ->
|
||||
mnesia:dirty_read(mqtt_admin, Username)
|
||||
end.
|
||||
|
@ -193,6 +194,7 @@ check(Username, Password) ->
|
|||
init([]) ->
|
||||
%% Add default admin user
|
||||
{ok, _} = mnesia:subscribe({table, mqtt_admin, simple}),
|
||||
add_default_user_hashed(binenv(default_user_username), hashed_default_passwd()),
|
||||
{ok, state}.
|
||||
|
||||
handle_call(_Req, _From, State) ->
|
||||
|
@ -240,13 +242,24 @@ salt() ->
|
|||
binenv(Key) ->
|
||||
iolist_to_binary(application:get_env(emqx_dashboard, Key, <<>>)).
|
||||
|
||||
add_default_user_hashed(Username, HashedPassword) ->
|
||||
case mnesia:dirty_read(mqtt_admin, Username) of
|
||||
[] ->
|
||||
Admin = #mqtt_admin{username=Username, password=HashedPassword, tags= <<"administrator">>},
|
||||
return(mnesia:transaction(fun add_user_/1, [Admin]));
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
hashed_default_passwd() ->
|
||||
case binenv(default_user_passwd_hashed) of
|
||||
Empty0 when ?EMPTY_KEY(Empty0) ->
|
||||
case binenv(default_user_passwd) of
|
||||
Empty when ?EMPTY_KEY(Empty) ->
|
||||
undefined;
|
||||
Password -> hash(Password)
|
||||
Password ->
|
||||
Hashed = hash(Password),
|
||||
application:set_env(emqx_dashboard, default_user_passwd_hashed, Hashed),
|
||||
Hashed
|
||||
end;
|
||||
HashedPassword -> HashedPassword
|
||||
end.
|
||||
|
|
|
@ -52,8 +52,8 @@ all() ->
|
|||
groups() ->
|
||||
[
|
||||
{overview, [sequence], [t_overview]},
|
||||
{admins, [sequence], [t_default_password_persists_after_leaving_cluster]},
|
||||
{rest, [sequence], [t_rest_api, t_auth_exhaustive_attack]},
|
||||
{admins, [sequence], [t_admins_add_delete, t_admins_persist_default_password, t_default_password_persists_after_leaving_cluster]},
|
||||
{rest, [sequence], [t_rest_api]},
|
||||
{cli, [sequence], [t_cli]}
|
||||
].
|
||||
|
||||
|
@ -90,10 +90,14 @@ t_admins_add_delete(_) ->
|
|||
|
||||
t_admins_persist_default_password(_) ->
|
||||
emqx_dashboard_admin:change_password(<<"admin">>, <<"new_password">>),
|
||||
[#mqtt_admin{password=Password}] = emqx_dashboard_admin:lookup_user(<<"admin">>),
|
||||
ct:sleep(100),
|
||||
[#mqtt_admin{password=Password, tags= <<"administrator">>}] = emqx_dashboard_admin:lookup_user(<<"admin">>),
|
||||
|
||||
%% To ensure that state persists even if the process dies
|
||||
exit(whereis(emqx_dashboard_admin), kill),
|
||||
application:stop(emqx_dashboard),
|
||||
application:start(emqx_dashboard),
|
||||
|
||||
ct:sleep(100),
|
||||
|
||||
%% It get's restarted by the app automatically
|
||||
[#mqtt_admin{password=PasswordAfterRestart}] = emqx_dashboard_admin:lookup_user(<<"admin">>),
|
||||
|
@ -147,6 +151,14 @@ t_default_password_persists_after_leaving_cluster(_) ->
|
|||
|
||||
debug(2, Slave),
|
||||
|
||||
rpc:call(Slave, application, stop, [emqx_dashboard]),
|
||||
|
||||
debug(3, Slave),
|
||||
|
||||
rpc:call(Slave, application, start, [emqx_dashboard]),
|
||||
|
||||
debug(4, Slave),
|
||||
|
||||
?assertEqual(
|
||||
ok,
|
||||
rpc:call(Slave, emqx_dashboard_admin, check, [<<"admin">>, <<"new_password">>])),
|
||||
|
@ -162,6 +174,7 @@ t_default_password_persists_after_leaving_cluster(_) ->
|
|||
t_rest_api(_Config) ->
|
||||
{ok, Res0} = http_get("users"),
|
||||
Users = get_http_data(Res0),
|
||||
ct:pal("~p", [emqx_dashboard_admin:all_users()]),
|
||||
?assert(lists:member(#{<<"username">> => <<"admin">>, <<"tags">> => <<"administrator">>},
|
||||
Users)),
|
||||
|
||||
|
@ -277,7 +290,6 @@ setup_node(Node, Apps) ->
|
|||
fun(emqx) ->
|
||||
application:set_env(emqx, listeners, []),
|
||||
application:set_env(gen_rpc, port_discovery, manual),
|
||||
mnesia:info(),
|
||||
ok;
|
||||
(emqx_management) ->
|
||||
application:set_env(emqx_management, listeners, []),
|
||||
|
|
|
@ -234,7 +234,7 @@ shutdown(Reason) ->
|
|||
).
|
||||
|
||||
reboot() ->
|
||||
case application_controller:is_running(emqx_dashboard) of
|
||||
case is_application_running(emqx_dashboard) of
|
||||
true ->
|
||||
application:stop(emqx_dashboard), %% dashboard must be started after mnesia
|
||||
lists:foreach(fun application:start/1 , default_started_applications()),
|
||||
|
@ -244,6 +244,10 @@ reboot() ->
|
|||
lists:foreach(fun application:start/1 , default_started_applications())
|
||||
end.
|
||||
|
||||
is_application_running(App) ->
|
||||
StartedApps = proplists:get_value(started, application:info()),
|
||||
proplists:is_defined(App, StartedApps).
|
||||
|
||||
-ifdef(EMQX_ENTERPRISE).
|
||||
default_started_applications() ->
|
||||
[gproc, esockd, ranch, cowboy, ekka, emqx].
|
||||
|
|
Loading…
Reference in New Issue