emqx/apps/emqx_authn/src/emqx_authn.erl

116 lines
3.5 KiB
Erlang

%%--------------------------------------------------------------------
%% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%--------------------------------------------------------------------
-module(emqx_authn).
-export([
providers/0,
check_config/1,
check_config/2,
check_configs/1,
%% for telemetry information
get_enabled_authns/0
]).
-include("emqx_authn.hrl").
providers() ->
[
{{password_based, built_in_database}, emqx_authn_mnesia},
{{password_based, mysql}, emqx_authn_mysql},
{{password_based, postgresql}, emqx_authn_pgsql},
{{password_based, mongodb}, emqx_authn_mongodb},
{{password_based, redis}, emqx_authn_redis},
{{password_based, http}, emqx_authn_http},
{jwt, emqx_authn_jwt},
{{scram, built_in_database}, emqx_enhanced_authn_scram_mnesia}
].
check_configs(C) when is_map(C) ->
check_configs([C]);
check_configs([]) ->
[];
check_configs([Config | Configs]) ->
[check_config(Config) | check_configs(Configs)].
check_config(Config) ->
check_config(Config, #{}).
check_config(Config, Opts) ->
case do_check_config(Config, Opts) of
#{?CONF_NS_ATOM := Checked} -> Checked;
#{?CONF_NS_BINARY := WithDefaults} -> WithDefaults
end.
do_check_config(#{<<"mechanism">> := Mec} = Config, Opts) ->
Key =
case maps:get(<<"backend">>, Config, false) of
false -> atom(Mec);
Backend -> {atom(Mec), atom(Backend)}
end,
case lists:keyfind(Key, 1, providers()) of
false ->
throw({unknown_handler, Key});
{_, ProviderModule} ->
hocon_tconf:check_plain(
ProviderModule,
#{?CONF_NS_BINARY => Config},
Opts#{atom_key => true}
)
end.
atom(Bin) ->
try
binary_to_existing_atom(Bin, utf8)
catch
_:_ ->
throw({unknown_auth_provider, Bin})
end.
-spec get_enabled_authns() ->
#{
authenticators => [authenticator_id()],
overridden_listeners => #{authenticator_id() => pos_integer()}
}.
get_enabled_authns() ->
%% at the moment of writing, `emqx_authentication:list_chains/0'
%% result is always wrapped in `{ok, _}', and it cannot return any
%% error values.
{ok, Chains} = emqx_authentication:list_chains(),
AuthnTypes = lists:usort([
Type
|| #{authenticators := As} <- Chains,
#{id := Type} <- As
]),
OverriddenListeners =
lists:foldl(
fun
(#{name := ?GLOBAL}, Acc) ->
Acc;
(#{authenticators := As}, Acc) ->
lists:foldl(fun tally_authenticators/2, Acc, As)
end,
#{},
Chains
),
#{
authenticators => AuthnTypes,
overridden_listeners => OverriddenListeners
}.
tally_authenticators(#{id := AuthenticatorName}, Acc) ->
maps:update_with(AuthenticatorName, fun(N) -> N + 1 end, 1, Acc).