emqx_authn.erl 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_authn).
  17. -export([
  18. providers/0,
  19. check_config/1,
  20. check_config/2,
  21. check_configs/1,
  22. %% for telemetry information
  23. get_enabled_authns/0
  24. ]).
  25. -include("emqx_authn.hrl").
  26. providers() ->
  27. [
  28. {{password_based, built_in_database}, emqx_authn_mnesia},
  29. {{password_based, mysql}, emqx_authn_mysql},
  30. {{password_based, postgresql}, emqx_authn_pgsql},
  31. {{password_based, mongodb}, emqx_authn_mongodb},
  32. {{password_based, redis}, emqx_authn_redis},
  33. {{password_based, http}, emqx_authn_http},
  34. {jwt, emqx_authn_jwt},
  35. {{scram, built_in_database}, emqx_enhanced_authn_scram_mnesia}
  36. ].
  37. check_configs(C) when is_map(C) ->
  38. check_configs([C]);
  39. check_configs([]) ->
  40. [];
  41. check_configs([Config | Configs]) ->
  42. [check_config(Config) | check_configs(Configs)].
  43. check_config(Config) ->
  44. check_config(Config, #{}).
  45. check_config(Config, Opts) ->
  46. case do_check_config(Config, Opts) of
  47. #{?CONF_NS_ATOM := Checked} -> Checked;
  48. #{?CONF_NS_BINARY := WithDefaults} -> WithDefaults
  49. end.
  50. do_check_config(#{<<"mechanism">> := Mec} = Config, Opts) ->
  51. Key =
  52. case maps:get(<<"backend">>, Config, false) of
  53. false -> atom(Mec);
  54. Backend -> {atom(Mec), atom(Backend)}
  55. end,
  56. case lists:keyfind(Key, 1, providers()) of
  57. false ->
  58. throw({unknown_handler, Key});
  59. {_, ProviderModule} ->
  60. hocon_tconf:check_plain(
  61. ProviderModule,
  62. #{?CONF_NS_BINARY => Config},
  63. Opts#{atom_key => true}
  64. )
  65. end.
  66. atom(Bin) ->
  67. try
  68. binary_to_existing_atom(Bin, utf8)
  69. catch
  70. _:_ ->
  71. throw({unknown_auth_provider, Bin})
  72. end.
  73. -spec get_enabled_authns() ->
  74. #{
  75. authenticators => [authenticator_id()],
  76. overridden_listeners => #{authenticator_id() => pos_integer()}
  77. }.
  78. get_enabled_authns() ->
  79. %% at the moment of writing, `emqx_authentication:list_chains/0'
  80. %% result is always wrapped in `{ok, _}', and it cannot return any
  81. %% error values.
  82. {ok, Chains} = emqx_authentication:list_chains(),
  83. AuthnTypes = lists:usort([
  84. Type
  85. || #{authenticators := As} <- Chains,
  86. #{id := Type} <- As
  87. ]),
  88. OverriddenListeners =
  89. lists:foldl(
  90. fun
  91. (#{name := ?GLOBAL}, Acc) ->
  92. Acc;
  93. (#{authenticators := As}, Acc) ->
  94. lists:foldl(fun tally_authenticators/2, Acc, As)
  95. end,
  96. #{},
  97. Chains
  98. ),
  99. #{
  100. authenticators => AuthnTypes,
  101. overridden_listeners => OverriddenListeners
  102. }.
  103. tally_authenticators(#{id := AuthenticatorName}, Acc) ->
  104. maps:update_with(AuthenticatorName, fun(N) -> N + 1 end, 1, Acc).