fix(authn): fix superuser in mongodb authn

This commit is contained in:
zhouzb 2021-09-08 10:58:00 +08:00
parent b5ded1ece0
commit 29cad91a47
5 changed files with 52 additions and 41 deletions

View File

@ -1320,8 +1320,8 @@ do_authenticate(#{auth_method := AuthMethod} = Credential, #channel{clientinfo =
do_authenticate(Credential, #channel{clientinfo = ClientInfo} = Channel) ->
case emqx_access_control:authenticate(Credential) of
{ok, #{is_superuser := Superuser}} ->
{ok, #{}, Channel#channel{clientinfo = ClientInfo#{is_superuser => Superuser}}};
{ok, #{is_superuser := IsSuperuser}} ->
{ok, #{}, Channel#channel{clientinfo = ClientInfo#{is_superuser => IsSuperuser}}};
{error, Reason} ->
{error, emqx_reason_codes:connack_error(Reason)}
end.

View File

@ -73,6 +73,7 @@
},
password_hash_field => <<"password_hash">>,
salt_field => <<"salt">>,
is_superuser_field => <<"is_superuser">>,
password_hash_algorithm => <<"sha256">>,
salt_position => <<"prefix">>
}).
@ -1398,6 +1399,10 @@ definitions() ->
type => string,
example => <<"salt">>
},
is_superuser_field => #{
type => string,
example => <<"is_superuser">>
},
password_hash_algorithm => #{
type => string,
enum => [<<"plain">>, <<"md5">>, <<"sha">>, <<"sha256">>, <<"sha512">>, <<"bcrypt">>],
@ -1882,10 +1887,10 @@ move_authenitcator(ConfKeyPath, ChainName0, AuthenticatorID, Position) ->
add_user(ChainName0, AuthenticatorID, #{<<"user_id">> := UserID, <<"password">> := Password} = UserInfo) ->
ChainName = to_atom(ChainName0),
Superuser = maps:get(<<"is_superuser">>, UserInfo, false),
IsSuperuser = maps:get(<<"is_superuser">>, UserInfo, false),
case ?AUTHN:add_user(ChainName, AuthenticatorID, #{ user_id => UserID
, password => Password
, is_superuser => Superuser}) of
, is_superuser => IsSuperuser}) of
{ok, User} ->
{201, User};
{error, Reason} ->

View File

@ -147,9 +147,9 @@ add_user(#{user_id := UserID,
fun() ->
case mnesia:read(?TAB, {UserGroup, UserID}, write) of
[] ->
Superuser = maps:get(is_superuser, UserInfo, false),
add_user(UserID, Password, Superuser, State),
{ok, #{user_id => UserID, is_superuser => Superuser}};
IsSuperuser = maps:get(is_superuser, UserInfo, false),
add_user(UserID, Password, IsSuperuser, State),
{ok, #{user_id => UserID, is_superuser => IsSuperuser}};
[_] ->
{error, already_exist}
end
@ -173,8 +173,8 @@ update_user(UserID, User,
case mnesia:read(?TAB, {UserGroup, UserID}, write) of
[] ->
{error, not_found};
[#user_info{is_superuser = Superuser} = UserInfo] ->
UserInfo1 = UserInfo#user_info{is_superuser = maps:get(is_superuser, User, Superuser)},
[#user_info{is_superuser = IsSuperuser} = UserInfo] ->
UserInfo1 = UserInfo#user_info{is_superuser = maps:get(is_superuser, User, IsSuperuser)},
UserInfo2 = case maps:get(password, User, undefined) of
undefined ->
UserInfo1;
@ -229,24 +229,24 @@ check_client_first_message(Bin, _Cache, #{iteration_count := IterationCount} = S
{error, not_authorized}
end.
check_client_final_message(Bin, #{is_superuser := Superuser} = Cache, #{algorithm := Alg}) ->
check_client_final_message(Bin, #{is_superuser := IsSuperuser} = Cache, #{algorithm := Alg}) ->
case esasl_scram:check_client_final_message(
Bin,
Cache#{algorithm => Alg}
) of
{ok, ServerFinalMessage} ->
{ok, #{is_superuser => Superuser}, ServerFinalMessage};
{ok, #{is_superuser => IsSuperuser}, ServerFinalMessage};
{error, _Reason} ->
{error, not_authorized}
end.
add_user(UserID, Password, Superuser, State) ->
add_user(UserID, Password, IsSuperuser, State) ->
{StoredKey, ServerKey, Salt} = esasl_scram:generate_authentication_info(Password, State),
UserInfo = #user_info{user_id = UserID,
stored_key = StoredKey,
server_key = ServerKey,
salt = Salt,
is_superuser = Superuser},
is_superuser = IsSuperuser},
mnesia:write(?TAB, UserInfo, write).
retrieve(UserID, #{user_group := UserGroup}) ->
@ -254,11 +254,11 @@ retrieve(UserID, #{user_group := UserGroup}) ->
[#user_info{stored_key = StoredKey,
server_key = ServerKey,
salt = Salt,
is_superuser = Superuser}] ->
is_superuser = IsSuperuser}] ->
{ok, #{stored_key => StoredKey,
server_key => ServerKey,
salt => Salt,
is_superuser => Superuser}};
is_superuser => IsSuperuser}};
[] ->
{error, not_found}
end.
@ -273,5 +273,5 @@ trans(Fun, Args) ->
{aborted, Reason} -> {error, Reason}
end.
serialize_user_info(#user_info{user_id = {_, UserID}, is_superuser = Superuser}) ->
#{user_id => UserID, is_superuser => Superuser}.
serialize_user_info(#user_info{user_id = {_, UserID}, is_superuser = IsSuperuser}) ->
#{user_id => UserID, is_superuser => IsSuperuser}.

View File

@ -158,13 +158,13 @@ authenticate(#{password := Password} = Credential,
case mnesia:dirty_read(?TAB, {UserGroup, UserID}) of
[] ->
ignore;
[#user_info{password_hash = PasswordHash, salt = Salt0, is_superuser = Superuser}] ->
[#user_info{password_hash = PasswordHash, salt = Salt0, is_superuser = IsSuperuser}] ->
Salt = case Algorithm of
bcrypt -> PasswordHash;
_ -> Salt0
end,
case PasswordHash =:= hash(Algorithm, Password, Salt) of
true -> {ok, #{is_superuser => Superuser}};
true -> {ok, #{is_superuser => IsSuperuser}};
false -> {error, bad_username_or_password}
end
end.
@ -197,9 +197,9 @@ add_user(#{user_id := UserID,
case mnesia:read(?TAB, {UserGroup, UserID}, write) of
[] ->
{PasswordHash, Salt} = hash(Password, State),
Superuser = maps:get(is_superuser, UserInfo, false),
insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser),
{ok, #{user_id => UserID, is_superuser => Superuser}};
IsSuperuser = maps:get(is_superuser, UserInfo, false),
insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser),
{ok, #{user_id => UserID, is_superuser => IsSuperuser}};
[_] ->
{error, already_exist}
end
@ -225,8 +225,8 @@ update_user(UserID, UserInfo,
{error, not_found};
[#user_info{ password_hash = PasswordHash
, salt = Salt
, is_superuser = Superuser}] ->
NSuperuser = maps:get(is_superuser, UserInfo, Superuser),
, is_superuser = IsSuperuser}] ->
NSuperuser = maps:get(is_superuser, UserInfo, IsSuperuser),
{NPasswordHash, NSalt} = case maps:get(password, UserInfo, undefined) of
undefined ->
{PasswordHash, Salt};
@ -290,8 +290,8 @@ import(UserGroup, [#{<<"user_id">> := UserID,
<<"password_hash">> := PasswordHash} = UserInfo | More])
when is_binary(UserID) andalso is_binary(PasswordHash) ->
Salt = maps:get(<<"salt">>, UserInfo, <<>>),
Superuser = maps:get(<<"is_superuser">>, UserInfo, false),
insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser),
IsSuperuser = maps:get(<<"is_superuser">>, UserInfo, false),
insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser),
import(UserGroup, More);
import(_UserGroup, [_ | _More]) ->
{error, bad_format}.
@ -305,8 +305,8 @@ import(UserGroup, File, Seq) ->
{ok, #{user_id := UserID,
password_hash := PasswordHash} = UserInfo} ->
Salt = maps:get(salt, UserInfo, <<>>),
Superuser = maps:get(is_superuser, UserInfo, false),
insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser),
IsSuperuser = maps:get(is_superuser, UserInfo, false),
insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser),
import(UserGroup, File, Seq);
{error, Reason} ->
{error, Reason}
@ -368,11 +368,11 @@ hash(Password, #{password_hash_algorithm := Algorithm} = State) ->
PasswordHash = hash(Algorithm, Password, Salt),
{PasswordHash, Salt}.
insert_user(UserGroup, UserID, PasswordHash, Salt, Superuser) ->
insert_user(UserGroup, UserID, PasswordHash, Salt, IsSuperuser) ->
UserInfo = #user_info{user_id = {UserGroup, UserID},
password_hash = PasswordHash,
salt = Salt,
is_superuser = Superuser},
is_superuser = IsSuperuser},
mnesia:write(?TAB, UserInfo, write).
delete_user2(UserInfo) ->
@ -400,5 +400,5 @@ to_binary(B) when is_binary(B) ->
to_binary(L) when is_list(L) ->
iolist_to_binary(L).
serialize_user_info(#user_info{user_id = {_, UserID}, is_superuser = Superuser}) ->
#{user_id => UserID, is_superuser => Superuser}.
serialize_user_info(#user_info{user_id = {_, UserID}, is_superuser = IsSuperuser}) ->
#{user_id => UserID, is_superuser => IsSuperuser}.

View File

@ -64,6 +64,7 @@ common_fields() ->
, {selector, fun selector/1}
, {password_hash_field, fun password_hash_field/1}
, {salt_field, fun salt_field/1}
, {is_superuser_field, fun is_superuser_field/1}
, {password_hash_algorithm, fun password_hash_algorithm/1}
, {salt_position, fun salt_position/1}
] ++ emqx_authn_schema:common_fields().
@ -84,6 +85,10 @@ salt_field(type) -> binary();
salt_field(nullable) -> true;
salt_field(_) -> undefined.
is_superuser_field(type) -> binary();
is_superuser_field(nullable) -> true;
is_superuser_field(_) -> undefined.
password_hash_algorithm(type) -> {enum, [plain, md5, sha, sha256, sha512, bcrypt]};
password_hash_algorithm(default) -> sha256;
password_hash_algorithm(_) -> undefined.
@ -109,6 +114,7 @@ create(#{ selector := Selector
State = maps:with([ collection
, password_hash_field
, salt_field
, is_superuser_field
, password_hash_algorithm
, salt_position
, '_unique'], Config),
@ -230,8 +236,8 @@ check_password(Password,
end
end.
is_superuser(Doc, #{superuser_field := SuperuserField}) ->
maps:get(SuperuserField, Doc, false);
is_superuser(Doc, #{is_superuser_field := IsSuperuserField}) ->
maps:get(IsSuperuserField, Doc, false);
is_superuser(_, _) ->
false.