fix(authn): fix superuser in mongodb authn
This commit is contained in:
parent
b5ded1ece0
commit
29cad91a47
|
@ -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.
|
||||
|
|
|
@ -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} ->
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
Loading…
Reference in New Issue