fix(authn): fix password hash algorithm for mysql and pgsql authn
This commit is contained in:
parent
a6b95afda8
commit
76d6949cd1
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
-module(emqx_authn_utils).
|
-module(emqx_authn_utils).
|
||||||
|
|
||||||
-export([ replace_placeholder/2
|
-export([ replace_placeholders/2
|
||||||
, gen_salt/0
|
, gen_salt/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -24,23 +24,23 @@
|
||||||
%% APIs
|
%% APIs
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
replace_placeholder(PlaceHolders, Data) ->
|
replace_placeholders(PlaceHolders, Data) ->
|
||||||
replace_placeholder(PlaceHolders, Data, []).
|
replace_placeholders(PlaceHolders, Data, []).
|
||||||
|
|
||||||
replace_placeholder([], _Data, Acc) ->
|
replace_placeholders([], _Data, Acc) ->
|
||||||
lists:reverse(Acc);
|
lists:reverse(Acc);
|
||||||
replace_placeholder([<<"${mqtt-username}">> | More], #{username := Username} = Data, Acc) ->
|
replace_placeholders([<<"${mqtt-username}">> | More], #{username := Username} = Data, Acc) ->
|
||||||
replace_placeholder(More, Data, [convert_to_sql_param(Username) | Acc]);
|
replace_placeholders(More, Data, [convert_to_sql_param(Username) | Acc]);
|
||||||
replace_placeholder([<<"${mqtt-clientid}">> | More], #{clientid := ClientID} = Data, Acc) ->
|
replace_placeholders([<<"${mqtt-clientid}">> | More], #{clientid := ClientID} = Data, Acc) ->
|
||||||
replace_placeholder(More, Data, [convert_to_sql_param(ClientID) | Acc]);
|
replace_placeholders(More, Data, [convert_to_sql_param(ClientID) | Acc]);
|
||||||
replace_placeholder([<<"${ip-address}">> | More], #{peerhost := IPAddress} = Data, Acc) ->
|
replace_placeholders([<<"${ip-address}">> | More], #{peerhost := IPAddress} = Data, Acc) ->
|
||||||
replace_placeholder(More, Data, [convert_to_sql_param(IPAddress) | Acc]);
|
replace_placeholders(More, Data, [convert_to_sql_param(IPAddress) | Acc]);
|
||||||
replace_placeholder([<<"${cert-subject}">> | More], #{dn := Subject} = Data, Acc) ->
|
replace_placeholders([<<"${cert-subject}">> | More], #{dn := Subject} = Data, Acc) ->
|
||||||
replace_placeholder(More, Data, [convert_to_sql_param(Subject) | Acc]);
|
replace_placeholders(More, Data, [convert_to_sql_param(Subject) | Acc]);
|
||||||
replace_placeholder([<<"${cert-common-name}">> | More], #{cn := CommonName} = Data, Acc) ->
|
replace_placeholders([<<"${cert-common-name}">> | More], #{cn := CommonName} = Data, Acc) ->
|
||||||
replace_placeholder(More, Data, [convert_to_sql_param(CommonName) | Acc]);
|
replace_placeholders(More, Data, [convert_to_sql_param(CommonName) | Acc]);
|
||||||
replace_placeholder([_ | More], Data, Acc) ->
|
replace_placeholders([_ | More], Data, Acc) ->
|
||||||
replace_placeholder(More, Data, [null | Acc]).
|
replace_placeholders(More, Data, [null | Acc]).
|
||||||
|
|
||||||
gen_salt() ->
|
gen_salt() ->
|
||||||
<<X:128/big-unsigned-integer>> = crypto:strong_rand_bytes(16),
|
<<X:128/big-unsigned-integer>> = crypto:strong_rand_bytes(16),
|
||||||
|
|
|
@ -46,25 +46,12 @@ fields(config) ->
|
||||||
, {query, fun query/1}
|
, {query, fun query/1}
|
||||||
, {query_timeout, fun query_timeout/1}
|
, {query_timeout, fun query_timeout/1}
|
||||||
] ++ emqx_connector_schema_lib:relational_db_fields()
|
] ++ emqx_connector_schema_lib:relational_db_fields()
|
||||||
++ emqx_connector_schema_lib:ssl_fields();
|
++ emqx_connector_schema_lib:ssl_fields().
|
||||||
|
|
||||||
fields(bcrypt) ->
|
password_hash_algorithm(type) -> {enum, [plain, md5, sha, sha256, sha512, bcrypt]};
|
||||||
[ {name, {enum, [bcrypt]}}
|
password_hash_algorithm(default) -> sha256;
|
||||||
, {salt_rounds, fun salt_rounds/1}
|
|
||||||
];
|
|
||||||
|
|
||||||
fields(other_algorithms) ->
|
|
||||||
[ {name, {enum, [plain, md5, sha, sha256, sha512]}}
|
|
||||||
].
|
|
||||||
|
|
||||||
password_hash_algorithm(type) -> {union, [hoconsc:ref(bcrypt), hoconsc:ref(other_algorithms)]};
|
|
||||||
password_hash_algorithm(default) -> #{<<"name">> => sha256};
|
|
||||||
password_hash_algorithm(_) -> undefined.
|
password_hash_algorithm(_) -> undefined.
|
||||||
|
|
||||||
salt_rounds(type) -> integer();
|
|
||||||
salt_rounds(default) -> 10;
|
|
||||||
salt_rounds(_) -> undefined.
|
|
||||||
|
|
||||||
salt_position(type) -> {enum, [prefix, suffix]};
|
salt_position(type) -> {enum, [prefix, suffix]};
|
||||||
salt_position(default) -> prefix;
|
salt_position(default) -> prefix;
|
||||||
salt_position(_) -> undefined.
|
salt_position(_) -> undefined.
|
||||||
|
@ -118,7 +105,7 @@ authenticate(#{password := Password} = Credential,
|
||||||
placeholders := PlaceHolders,
|
placeholders := PlaceHolders,
|
||||||
query := Query,
|
query := Query,
|
||||||
query_timeout := Timeout} = State) ->
|
query_timeout := Timeout} = State) ->
|
||||||
Params = emqx_authn_utils:replace_placeholder(PlaceHolders, Credential),
|
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
|
||||||
case emqx_resource:query(ResourceID, {sql, Query, Params, Timeout}) of
|
case emqx_resource:query(ResourceID, {sql, Query, Params, Timeout}) of
|
||||||
{ok, _Columns, []} -> ignore;
|
{ok, _Columns, []} -> ignore;
|
||||||
{ok, Columns, Rows} ->
|
{ok, Columns, Rows} ->
|
||||||
|
@ -137,7 +124,7 @@ destroy(#{resource_id := ResourceID}) ->
|
||||||
%% Internal functions
|
%% Internal functions
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
check_password(undefined, _Algorithm, _Selected) ->
|
check_password(undefined, _Selected, _State) ->
|
||||||
{error, bad_username_or_password};
|
{error, bad_username_or_password};
|
||||||
check_password(Password,
|
check_password(Password,
|
||||||
#{password_hash := Hash},
|
#{password_hash := Hash},
|
||||||
|
|
|
@ -45,7 +45,8 @@ fields(config) ->
|
||||||
] ++ emqx_connector_schema_lib:relational_db_fields()
|
] ++ emqx_connector_schema_lib:relational_db_fields()
|
||||||
++ emqx_connector_schema_lib:ssl_fields().
|
++ emqx_connector_schema_lib:ssl_fields().
|
||||||
|
|
||||||
password_hash_algorithm(type) -> string();
|
password_hash_algorithm(type) -> {enum, [plain, md5, sha, sha256, sha512, bcrypt]};
|
||||||
|
password_hash_algorithm(default) -> sha256;
|
||||||
password_hash_algorithm(_) -> undefined.
|
password_hash_algorithm(_) -> undefined.
|
||||||
|
|
||||||
query(type) -> string();
|
query(type) -> string();
|
||||||
|
@ -90,7 +91,7 @@ authenticate(#{password := Password} = Credential,
|
||||||
#{resource_id := ResourceID,
|
#{resource_id := ResourceID,
|
||||||
query := Query,
|
query := Query,
|
||||||
placeholders := PlaceHolders} = State) ->
|
placeholders := PlaceHolders} = State) ->
|
||||||
Params = emqx_authn_utils:replace_placeholder(PlaceHolders, Credential),
|
Params = emqx_authn_utils:replace_placeholders(PlaceHolders, Credential),
|
||||||
case emqx_resource:query(ResourceID, {sql, Query, Params}) of
|
case emqx_resource:query(ResourceID, {sql, Query, Params}) of
|
||||||
{ok, _Columns, []} -> ignore;
|
{ok, _Columns, []} -> ignore;
|
||||||
{ok, Columns, Rows} ->
|
{ok, Columns, Rows} ->
|
||||||
|
@ -109,7 +110,7 @@ destroy(#{resource_id := ResourceID}) ->
|
||||||
%% Internal functions
|
%% Internal functions
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
|
|
||||||
check_password(undefined, _Algorithm, _Selected) ->
|
check_password(undefined, _Selected, _State) ->
|
||||||
{error, bad_username_or_password};
|
{error, bad_username_or_password};
|
||||||
check_password(Password,
|
check_password(Password,
|
||||||
#{password_hash := Hash},
|
#{password_hash := Hash},
|
||||||
|
|
|
@ -149,11 +149,14 @@ connect(Opts) ->
|
||||||
WorkerOptions = proplists:get_value(worker_options, Opts, []),
|
WorkerOptions = proplists:get_value(worker_options, Opts, []),
|
||||||
mongo_api:connect(Type, Hosts, Options, WorkerOptions).
|
mongo_api:connect(Type, Hosts, Options, WorkerOptions).
|
||||||
|
|
||||||
mongo_query(Conn, find, Collection, Selector, Docs) ->
|
mongo_query(Conn, find, Collection, Selector, Projector) ->
|
||||||
mongo_api:find(Conn, Collection, Selector, Docs);
|
mongo_api:find(Conn, Collection, Selector, Projector);
|
||||||
|
|
||||||
|
mongo_query(Conn, find_one, Collection, Selector, Projector) ->
|
||||||
|
mongo_api:find_one(Conn, Collection, Selector, Projector);
|
||||||
|
|
||||||
%% Todo xxx
|
%% Todo xxx
|
||||||
mongo_query(_Conn, _Action, _Collection, _Selector, _Docs) ->
|
mongo_query(_Conn, _Action, _Collection, _Selector, _Projector) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
do_start(InstId, Opts0, Config = #{mongo_type := Type,
|
do_start(InstId, Opts0, Config = #{mongo_type := Type,
|
||||||
|
|
Loading…
Reference in New Issue