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

fix(ee): emqx no longer deps on emqx_auth_ext

William Yang 1 год назад
Родитель
Сommit
a1aa9a4375

+ 5 - 0
apps/emqx/include/emqx_schema.hrl

@@ -21,4 +21,9 @@
 -define(TOMBSTONE_CONFIG_CHANGE_REQ, mark_it_for_deletion).
 -define(CONFIG_NOT_FOUND_MAGIC, '$0tFound').
 
+%%--------------------------------------------------------------------
+%% EE injections
+%%--------------------------------------------------------------------
+-define(EMQX_SSL_FUN_MFA(Name), {emqx_ssl_fun_mfa, Name}).
+
 -endif.

+ 4 - 19
apps/emqx/src/emqx_listeners.erl

@@ -75,10 +75,6 @@
 -define(TYPES_STRING, ["tcp", "ssl", "ws", "wss", "quic"]).
 -define(MARK_DEL, ?TOMBSTONE_CONFIG_CHANGE_REQ).
 
--ifndef(EMQX_RELEASE_EDITION).
--define(EMQX_RELEASE_EDITION, ce).
--endif.
-
 -spec id_example() -> atom().
 id_example() -> 'tcp:default'.
 
@@ -978,21 +974,10 @@ quic_listener_optional_settings() ->
         stateless_operation_expiration_ms
     ].
 
--if(?EMQX_RELEASE_EDITION == ee).
-inject_root_fun(#{ssl_options := SslOpts} = Opts) ->
-    Opts#{ssl_options := emqx_auth_ext_tls_lib:opt_partial_chain(SslOpts)}.
--else.
-inject_root_fun(Opts) ->
-    Opts.
--endif.
-
--if(?EMQX_RELEASE_EDITION == ee).
-inject_verify_fun(#{ssl_options := SslOpts} = Opts) ->
-    Opts#{ssl_options := emqx_auth_ext_tls_lib:opt_verify_fun(SslOpts)}.
--else.
-inject_verify_fun(Opts) ->
-    Opts.
--endif.
+inject_root_fun(#{ssl_options := SSLOpts} = Opts) ->
+    Opts#{ssl_options := emqx_tls_lib:maybe_inject_ssl_fun(root_fun, SSLOpts)}.
+inject_verify_fun(#{ssl_options := SSLOpts} = Opts) ->
+    Opts#{ssl_options := emqx_tls_lib:maybe_inject_ssl_fun(verify_fun, SSLOpts)}.
 
 inject_sni_fun(ListenerId, Conf = #{ssl_options := #{ocsp := #{enable_ocsp_stapling := true}}}) ->
     emqx_ocsp_cache:inject_sni_fun(ListenerId, Conf);

+ 14 - 0
apps/emqx/src/emqx_tls_lib.erl

@@ -45,10 +45,13 @@
     to_client_opts/2
 ]).
 
+-export([maybe_inject_ssl_fun/2]).
+
 %% ssl:tls_version/0 is not exported.
 -type tls_version() :: tlsv1 | 'tlsv1.1' | 'tlsv1.2' | 'tlsv1.3'.
 
 -include("logger.hrl").
+-include("emqx_schema.hrl").
 
 -define(IS_TRUE(Val), ((Val =:= true) orelse (Val =:= <<"true">>))).
 -define(IS_FALSE(Val), ((Val =:= false) orelse (Val =:= <<"false">>))).
@@ -686,3 +689,14 @@ ensure_ssl_file_key(SSL, RequiredKeyPaths) ->
         [] -> ok;
         Miss -> {error, #{reason => ssl_file_option_not_found, which_options => Miss}}
     end.
+
+-spec maybe_inject_ssl_fun(root_fun | verify_fun, map()) -> map().
+maybe_inject_ssl_fun(FunName, SslOpts) ->
+    case persistent_term:get(?EMQX_SSL_FUN_MFA(FunName), undefined) of
+        undefined ->
+            SslOpts;
+        {M, F, A} ->
+            %% We should have one entry not a list of {M,F,A},
+            %% as ordering matters in validations
+            erlang:apply(M, F, [SslOpts | A])
+    end.

+ 22 - 0
apps/emqx_auth_ext/src/emqx_auth_ext.erl

@@ -3,4 +3,26 @@
 %%--------------------------------------------------------------------
 -module(emqx_auth_ext).
 
+-include_lib("emqx/include/emqx_schema.hrl").
+
+-on_load(on_load/0).
+
 -export([]).
+
+-spec on_load() -> ok.
+on_load() ->
+    init_ssl_fun_cb().
+
+init_ssl_fun_cb() ->
+    lists:foreach(
+        fun({FunName, {_, _, _} = MFA}) ->
+            persistent_term:put(
+                ?EMQX_SSL_FUN_MFA(FunName),
+                MFA
+            )
+        end,
+        [
+            {root_fun, {emqx_auth_ext_tls_lib, opt_partial_chain, []}},
+            {verify_fun, {emqx_auth_ext_tls_lib, opt_verify_fun, []}}
+        ]
+    ).

+ 66 - 0
apps/emqx_auth_ext/test/emqx_auth_ext_schema_SUITE.erl

@@ -0,0 +1,66 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2024 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_auth_ext_schema_SUITE).
+-compile(nowarn_export_all).
+-compile(export_all).
+
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+-define(BASE_CONF,
+    "\n"
+    "    listeners.ssl.auth_ext.bind = 28883\n"
+    "    listeners.ssl.auth_ext.enable = true\n"
+    "    listeners.ssl.auth_ext.ssl_options.partial_chain = true\n"
+    "    listeners.ssl.auth_ext.ssl_options.verify = verify_peer\n"
+    "    listeners.ssl.auth_ext.ssl_options.verify_peer_ext_key_usage = \"clientAuth\"\n"
+    "    "
+).
+
+all() ->
+    emqx_common_test_helpers:all(?MODULE).
+
+init_per_suite(Config) ->
+    %% injection happens when module is loaded.
+    code:load_file(emqx_auth_ext),
+    Apps = emqx_cth_suite:start(
+        [
+            emqx,
+            {emqx_conf, ?BASE_CONF}
+        ],
+        #{work_dir => emqx_cth_suite:work_dir(Config)}
+    ),
+    emqx_listeners:restart(),
+    [{apps, Apps} | Config].
+
+end_per_suite(Config) ->
+    Apps = ?config(apps, Config),
+    ok = emqx_cth_suite:stop(Apps),
+    code:delete(emqx_auth_ext),
+    code:purge(emqx_auth_ext),
+    ok.
+
+t_conf_check_default(_Config) ->
+    Opts = esockd:get_options({'ssl:default', {{0, 0, 0, 0}, 8883}}),
+    SSLOpts = proplists:get_value(ssl_options, Opts),
+    ?assertEqual(none, proplists:lookup(partial_chain, SSLOpts)),
+    ?assertEqual(none, proplists:lookup(verify_fun, SSLOpts)).
+
+t_conf_check_auth_ext(_Config) ->
+    Opts = esockd:get_options({'ssl:auth_ext', 28883}),
+    SSLOpts = proplists:get_value(ssl_options, Opts),
+    ?assertMatch(Fun when is_function(Fun), proplists:get_value(partial_chain, SSLOpts)),
+    ?assertMatch({Fun, _} when is_function(Fun), proplists:get_value(verify_fun, SSLOpts)).

+ 2 - 12
apps/emqx_gateway/src/emqx_gateway_utils.erl

@@ -588,21 +588,11 @@ ssl_server_opts(SSLOpts, ssl_options) ->
 ssl_server_opts(SSLOpts, dtls_options) ->
     emqx_tls_lib:to_server_opts(dtls, SSLOpts).
 
--if(defined(EMQX_RELEASE_EDITION) andalso ?EMQX_RELEASE_EDITION == ee).
 ssl_partial_chain(SSLOpts, _Options) ->
-    emqx_auth_ext_tls_lib:opt_partial_chain(SSLOpts).
--else.
-ssl_partial_chain(SSLOpts, _) ->
-    SSLOpts.
--endif.
+    emqx_tls_lib:maybe_inject_ssl_fun(root_fun, SSLOpts).
 
--if(defined(EMQX_RELEASE_EDITION) andalso ?EMQX_RELEASE_EDITION == ee).
 ssl_verify_fun(SSLOpts, _Options) ->
-    emqx_auth_ext_tls_lib:opt_verify_fun(SSLOpts).
--else.
-ssl_verify_fun(SSLOpts, _) ->
-    SSLOpts.
--endif.
+    emqx_tls_lib:maybe_inject_ssl_fun(verify_fun, SSLOpts).
 
 ranch_opts(Type, ListenOn, Opts) ->
     NumAcceptors = maps:get(acceptors, Opts, 4),