Merge pull request #11785 from zhongwencool/rbac-change-pwd

This commit is contained in:
zhongwencool 2023-10-19 09:02:15 +08:00 committed by GitHub
commit 9f197a6915
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 11 deletions

View File

@ -248,8 +248,8 @@ clean_expired_jwt(Now) ->
-if(?EMQX_RELEASE_EDITION == ee).
check_rbac(Req, JWT) ->
#?ADMIN_JWT{exptime = _ExpTime, extra = Extra, username = _Username} = JWT,
case emqx_dashboard_rbac:check_rbac(Req, Extra) of
#?ADMIN_JWT{exptime = _ExpTime, extra = Extra, username = Username} = JWT,
case emqx_dashboard_rbac:check_rbac(Req, Username, Extra) of
true ->
save_new_jwt(JWT);
_ ->

View File

@ -1,6 +1,6 @@
{application, emqx_dashboard_rbac, [
{description, "EMQX Dashboard RBAC"},
{vsn, "0.1.0"},
{vsn, "0.1.1"},
{registered, []},
{applications, [
kernel,

View File

@ -6,18 +6,18 @@
-include_lib("emqx_dashboard/include/emqx_dashboard.hrl").
-export([check_rbac/2, role/1, valid_role/1]).
-export([check_rbac/3, role/1, valid_role/1]).
-dialyzer({nowarn_function, role/1}).
%%=====================================================================
%% API
check_rbac(Req, Extra) ->
check_rbac(Req, Username, Extra) ->
Role = role(Extra),
Method = cowboy_req:method(Req),
AbsPath = cowboy_req:path(Req),
case emqx_dashboard_swagger:get_relative_uri(AbsPath) of
{ok, Path} ->
check_rbac(Role, Method, Path);
check_rbac(Role, Method, Path, Username);
_ ->
false
end.
@ -41,14 +41,21 @@ valid_role(Role) ->
{error, <<"Role does not exist">>}
end.
%% ===================================================================
check_rbac(?ROLE_SUPERUSER, _, _) ->
check_rbac(?ROLE_SUPERUSER, _, _, _) ->
true;
check_rbac(?ROLE_VIEWER, <<"GET">>, _) ->
check_rbac(?ROLE_VIEWER, <<"GET">>, _, _) ->
true;
%% this API is a special case
check_rbac(?ROLE_VIEWER, <<"POST">>, <<"/logout">>) ->
%% everyone should allow to logout
check_rbac(?ROLE_VIEWER, <<"POST">>, <<"/logout">>, _) ->
true;
check_rbac(_, _, _) ->
%% viewer should allow to change self password,
%% superuser should allow to change any user
check_rbac(?ROLE_VIEWER, <<"POST">>, <<"/users/", SubPath/binary>>, Username) ->
case binary:split(SubPath, <<"/">>, [global]) of
[Username, <<"change_pwd">>] -> true;
_ -> false
end;
check_rbac(_, _, _, _) ->
false.
role_list() ->

View File

@ -160,6 +160,34 @@ t_login_out(_) ->
{ok, Username} = emqx_dashboard_admin:verify_token(FakeReq, Token),
ok.
t_change_pwd(_) ->
Viewer1 = <<"viewer1">>,
Viewer2 = <<"viewer2">>,
SuperUser = <<"super_user">>,
Password = <<"public_www1">>,
Desc = <<"desc">>,
{ok, _} = emqx_dashboard_admin:add_user(Viewer1, Password, ?ROLE_VIEWER, Desc),
{ok, _} = emqx_dashboard_admin:add_user(Viewer2, Password, ?ROLE_VIEWER, Desc),
{ok, _} = emqx_dashboard_admin:add_user(SuperUser, Password, ?ROLE_SUPERUSER, Desc),
{ok, ?ROLE_VIEWER, Viewer1Token} = emqx_dashboard_admin:sign_token(Viewer1, Password),
{ok, ?ROLE_SUPERUSER, SuperToken} = emqx_dashboard_admin:sign_token(SuperUser, Password),
%% viewer can change own password
?assertEqual({ok, Viewer1}, change_pwd(Viewer1Token, Viewer1)),
%% viewer can't change other's password
?assertEqual({error, unauthorized_role}, change_pwd(Viewer1Token, Viewer2)),
?assertEqual({error, unauthorized_role}, change_pwd(Viewer1Token, SuperUser)),
%% superuser can change other's password
?assertEqual({ok, SuperUser}, change_pwd(SuperToken, Viewer1)),
?assertEqual({ok, SuperUser}, change_pwd(SuperToken, Viewer2)),
?assertEqual({ok, SuperUser}, change_pwd(SuperToken, SuperUser)),
ok.
change_pwd(Token, Username) ->
Path = "/users/" ++ binary_to_list(Username) ++ "/change_pwd",
Path1 = erlang:list_to_binary(emqx_dashboard_swagger:relative_uri(Path)),
Req = #{method => <<"POST">>, path => Path1},
emqx_dashboard_admin:verify_token(Req, Token).
add_default_superuser() ->
{ok, _NewUser} = emqx_dashboard_admin:add_user(
?DEFAULT_SUPERUSER,

View File

@ -0,0 +1 @@
Allow viewer to change their own passwords, viewer can't change other's password.