Просмотр исходного кода

chore(auth): removed direct usages of authn from emqx core app

Ilya Averyanov 2 лет назад
Родитель
Сommit
ca8c1e3ef8

+ 4 - 0
apps/emqx/include/emqx_access_control.hrl

@@ -14,6 +14,9 @@
 %% limitations under the License.
 %%--------------------------------------------------------------------
 
+-ifndef(EMQX_ACCESS_CONTROL_HRL).
+-define(EMQX_ACCESS_CONTROL_HRL, true).
+
 %% config root name all auth providers have to agree on.
 -define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME, "authorization").
 -define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_ATOM, authorization).
@@ -35,3 +38,4 @@
 
 -define(AUTHN_TRACE_TAG, "AUTHN").
 
+-endif.

+ 1 - 0
apps/emqx/include/emqx_hooks.hrl

@@ -29,6 +29,7 @@
 -define(HP_RETAINER, 930).
 -define(HP_AUTO_SUB, 920).
 -define(HP_RULE_ENGINE, 900).
+
 %% apps that can work with the republish action
 -define(HP_SLOW_SUB, 880).
 -define(HP_BRIDGE, 870).

+ 86 - 0
apps/emqx/src/emqx_authentication_listener_hooks.erl

@@ -0,0 +1,86 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2017-2023 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_authentication_listener_hooks).
+
+-include_lib("emqx/include/emqx_hooks.hrl").
+
+-export([
+    on_listener_started/4,
+    on_listener_stopped/4,
+    on_listener_updated/4
+]).
+
+-export([
+    load/0,
+    unload/0
+]).
+
+%%--------------------------------------------------------------------
+%% API
+%%--------------------------------------------------------------------
+
+load() ->
+    ok = emqx_hook:put('listener.started', {?MODULE, on_listener_started, []}, ?HP_AUTHN),
+    ok = emqx_hook:put('listener.stopped', {?MODULE, on_listener_stopped, []}, ?HP_AUTHN),
+    ok = emqx_hook:put('listener.updated', {?MODULE, on_listener_updated, []}, ?HP_AUTHN),
+    ok.
+
+unload() ->
+    ok = emqx_hooks:del('listener.started', {?MODULE, authenticate, []}),
+    ok = emqx_hooks:del('listener.stopped', {?MODULE, authenticate, []}),
+    ok = emqx_hooks:del('listener.updated', {?MODULE, authenticate, []}),
+    ok.
+
+%%--------------------------------------------------------------------
+%% Hooks
+%%--------------------------------------------------------------------
+
+on_listener_started(Type, Name, Conf, ok) ->
+    recreate_authenticators(Type, Name, Conf);
+on_listener_started(_Type, _Name, _Conf, _Error) ->
+    ok.
+
+on_listener_updated(Type, Name, {_OldConf, NewConf}, ok) ->
+    recreate_authenticators(Type, Name, NewConf);
+on_listener_updated(_Type, _Name, _Conf, _Error) ->
+    ok.
+
+on_listener_stopped(Type, Name, _OldConf, ok) ->
+    _ = emqx_authentication:delete_chain(emqx_listeners:listener_id(Type, Name)),
+    ok;
+on_listener_stopped(_Type, _Name, _Conf, _Error) ->
+    ok.
+
+%%--------------------------------------------------------------------
+%% Internal functions
+%%--------------------------------------------------------------------
+
+recreate_authenticators(Type, Name, Conf) ->
+    Chain = emqx_listeners:listener_id(Type, Name),
+    _ = emqx_authentication:delete_chain(Chain),
+    do_create_authneticators(Chain, maps:get(authentication, Conf, [])).
+
+do_create_authneticators(Chain, [AuthN | T]) ->
+    case emqx_authentication:create_authenticator(Chain, AuthN) of
+        {ok, _} ->
+            do_create_authneticators(Chain, T);
+        Error ->
+            _ = emqx_authentication:delete_chain(Chain),
+            {ok, Error}
+    end;
+do_create_authneticators(_Chain, []) ->
+    ok.

+ 6 - 29
apps/emqx/src/emqx_listeners.erl

@@ -531,41 +531,18 @@ post_config_update(_Path, _Request, _NewConf, _OldConf, _AppEnvs) ->
     ok.
 
 create_listener(Type, Name, NewConf) ->
-    Res = start_listener(Type, Name, NewConf),
-    recreate_authenticators(Res, Type, Name, NewConf).
-
-recreate_authenticators(ok, Type, Name, Conf) ->
-    Chain = listener_id(Type, Name),
-    _ = emqx_authentication:delete_chain(Chain),
-    do_create_authneticators(Chain, maps:get(authentication, Conf, []));
-recreate_authenticators(Error, _Type, _Name, _NewConf) ->
-    Error.
-
-do_create_authneticators(Chain, [AuthN | T]) ->
-    case emqx_authentication:create_authenticator(Chain, AuthN) of
-        {ok, _} ->
-            do_create_authneticators(Chain, T);
-        Error ->
-            _ = emqx_authentication:delete_chain(Chain),
-            Error
-    end;
-do_create_authneticators(_Chain, []) ->
-    ok.
+    StartRes = start_listener(Type, Name, NewConf),
+    emqx_hooks:run_fold('listener.started', [Type, Name, NewConf], StartRes).
 
 remove_listener(Type, Name, OldConf) ->
     ok = unregister_ocsp_stapling_refresh(Type, Name),
-    case stop_listener(Type, Name, OldConf) of
-        ok ->
-            _ = emqx_authentication:delete_chain(listener_id(Type, Name)),
-            ok;
-        Err ->
-            Err
-    end.
+    StopRes = stop_listener(Type, Name, OldConf),
+    emqx_hooks:run_fold('listener.stopped', [Type, Name, OldConf], StopRes).
 
 update_listener(Type, Name, {OldConf, NewConf}) ->
     ok = maybe_unregister_ocsp_stapling_refresh(Type, Name, NewConf),
-    Res = restart_listener(Type, Name, {OldConf, NewConf}),
-    recreate_authenticators(Res, Type, Name, NewConf).
+    RestartRes = restart_listener(Type, Name, {OldConf, NewConf}),
+    emqx_hooks:run_fold('listener.restarted', [Type, Name, {OldConf, NewConf}], RestartRes).
 
 perform_listener_changes([]) ->
     ok;

+ 12 - 19
apps/emqx/test/emqx_broker_SUITE.erl

@@ -26,6 +26,7 @@
 -include_lib("snabbkaffe/include/snabbkaffe.hrl").
 
 -include_lib("emqx/include/emqx.hrl").
+-include_lib("emqx/include/emqx_hooks.hrl").
 -include_lib("emqx/include/emqx_mqtt.hrl").
 
 all() ->
@@ -680,28 +681,17 @@ t_connect_client_never_negative({'end', _Config}) ->
 
 t_connack_auth_error({init, Config}) ->
     process_flag(trap_exit, true),
-    ChainName = 'mqtt:global',
-    AuthenticatorConfig = #{
-        enable => true,
-        mechanism => password_based,
-        backend => built_in_database,
-        user_id_type => username,
-        password_hash_algorithm => #{
-            name => plain,
-            salt_position => disable
-        },
-        user_group => <<"global:mqtt">>
-    },
-    ok = emqx_authentication:register_providers(
-        [{{password_based, built_in_database}, emqx_authentication_SUITE}]
+    emqx_hooks:put(
+        'client.authenticate',
+        {?MODULE, authenticate_deny, []},
+        ?HP_AUTHN
     ),
-    emqx_authentication:initialize_authentication(ChainName, AuthenticatorConfig),
     Config;
 t_connack_auth_error({'end', _Config}) ->
-    ChainName = 'mqtt:global',
-    AuthenticatorID = <<"password_based:built_in_database">>,
-    ok = emqx_authentication:deregister_provider({password_based, built_in_database}),
-    ok = emqx_authentication:delete_authenticator(ChainName, AuthenticatorID),
+    emqx_hooks:del(
+        'client.authenticate',
+        {?MODULE, authenticate_deny, []}
+    ),
     ok;
 t_connack_auth_error(Config) when is_list(Config) ->
     %% MQTT 3.1
@@ -733,6 +723,9 @@ t_handle_in_empty_client_subscribe_hook(Config) when is_list(Config) ->
         emqtt:disconnect(C)
     end.
 
+authenticate_deny(_Credentials, _Default) ->
+    {stop, {error, bad_username_or_password}}.
+
 wait_for_events(Action, Kinds) ->
     wait_for_events(Action, Kinds, 500).