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

fix: support https (#5606)

* fix: support https
DDDHuang 4 лет назад
Родитель
Сommit
c4e279bb76

Разница между файлами не показана из-за своего большого размера
+ 18 - 23
apps/emqx_dashboard/etc/emqx_dashboard.conf


+ 63 - 48
apps/emqx_dashboard/src/emqx_dashboard.erl

@@ -20,9 +20,7 @@
 
 
 -export([ start_listeners/0
-        , stop_listeners/0
-        , start_listener/1
-        , stop_listener/1]).
+        , stop_listeners/0]).
 
 %% Authorization
 -export([authorize_appid/1]).
@@ -36,15 +34,8 @@
 %%--------------------------------------------------------------------
 
 start_listeners() ->
-    lists:foreach(fun start_listener/1, listeners()).
-
-stop_listeners() ->
-    lists:foreach(fun stop_listener/1, listeners()).
-
-start_listener({Proto, Port, Options}) ->
     {ok, _} = application:ensure_all_started(minirest),
     Authorization = {?MODULE, authorize_appid},
-    RanchOptions = ranch_opts(Port, Options),
     GlobalSpec = #{
         openapi => "3.0.0",
         info => #{title => "EMQ X Dashboard API", version => "5.0.0"},
@@ -56,20 +47,33 @@ start_listener({Proto, Port, Options}) ->
                     type => apiKey,
                     name => "authorization",
                     in => header}}}},
-    Dispatch = [{"/", cowboy_static, {priv_file, emqx_dashboard, "www/index.html"}},
-                {"/static/[...]", cowboy_static, {priv_dir, emqx_dashboard, "www/static"}},
-                {'_', cowboy_static, {priv_file, emqx_dashboard, "www/index.html"}}],
-    Minirest = #{
-        protocol => Proto,
+    Dispatch = [
+        {"/", cowboy_static, {priv_file, emqx_dashboard, "www/index.html"}},
+        {"/static/[...]", cowboy_static, {priv_dir, emqx_dashboard, "www/static"}},
+        {'_', cowboy_static, {priv_file, emqx_dashboard, "www/index.html"}}
+    ],
+    BaseMinirest = #{
         base_path => ?BASE_PATH,
         modules => minirest_api:find_api_modules(apps()),
         authorization => Authorization,
         security => [#{application => []}],
         swagger_global_spec => GlobalSpec,
-        dispatch => Dispatch},
-    MinirestOptions = maps:merge(Minirest, RanchOptions),
-    {ok, _} = minirest:start(listener_name(Proto), MinirestOptions),
-    ?ULOG("Start ~p listener on ~p successfully.~n", [listener_name(Proto), Port]).
+        dispatch => Dispatch
+    },
+    [begin
+        Minirest = maps:put(protocol, Protocol, BaseMinirest),
+        {ok, _} = minirest:start(Name, RanchOptions, Minirest),
+        ?ULOG("Start listener ~s on ~p successfully.~n", [Name, Port])
+    end || {Name, Protocol, Port, RanchOptions} <- listeners()].
+
+stop_listeners() ->
+    [begin
+        ok = minirest:stop(Name),
+        ?ULOG("Stop listener ~s on ~p successfully.~n", [Name, Port])
+    end || {Name, _, Port, _} <- listeners()].
+
+%%--------------------------------------------------------------------
+%% internal
 
 apps() ->
     [App || {App, _, _} <- application:loaded_applications(),
@@ -78,30 +82,48 @@ apps() ->
             _ -> false
         end].
 
-ranch_opts(Port, Options0) ->
-    Options = lists:foldl(
-                  fun
-                      ({K, _V}, Acc) when K =:= max_connections orelse K =:= num_acceptors -> Acc;
-                      ({inet6, true}, Acc) -> [inet6 | Acc];
-                      ({inet6, false}, Acc) -> Acc;
-                      ({ipv6_v6only, true}, Acc) -> [{ipv6_v6only, true} | Acc];
-                      ({ipv6_v6only, false}, Acc) -> Acc;
-                      ({K, V}, Acc)->
-                          [{K, V} | Acc]
-                  end, [], Options0),
-    maps:from_list([{port, Port} | Options]).
-
-stop_listener({Proto, Port, _}) ->
-    ?ULOG("Stop dashboard listener on ~s successfully.~n", [format(Port)]),
-    minirest:stop(listener_name(Proto)).
-
 listeners() ->
-    [{Protocol, Port, maps:to_list(maps:without([protocol, port], Map))}
-        || Map = #{protocol := Protocol,port := Port}
-        <- emqx:get_config([emqx_dashboard, listeners], [])].
+    [begin
+        Protocol = maps:get(protocol, ListenerOptions, http),
+        Port = maps:get(port, ListenerOptions, 18083),
+        Name = listener_name(Protocol, Port),
+        RanchOptions = ranch_opts(maps:without([protocol], ListenerOptions)),
+        {Name, Protocol, Port, RanchOptions}
+    end || ListenerOptions <- emqx_config:get([emqx_dashboard, listeners], [])].
+
+ranch_opts(RanchOptions) ->
+    Keys = [ {ack_timeout, handshake_timeout}
+            , connection_type
+            , max_connections
+            , num_acceptors
+            , shutdown
+            , socket],
+    {S, R} = lists:foldl(fun key_take/2, {RanchOptions, #{}}, Keys),
+    R#{socket_opts => maps:fold(fun key_only/3, [], S)}.
+
+
+key_take({K, K1}, {All, R})  ->
+    case maps:get(K, All, undefined) of
+        undefined ->
+            {All, R};
+        V ->
+            {maps:remove(K, All), R#{K1 => V}}
+    end;
+key_take(K, {All, R})  ->
+    case maps:get(K, All, undefined) of
+        undefined ->
+            {All, R};
+        V ->
+            {maps:remove(K, All), R#{K => V}}
+    end.
 
-listener_name(Proto) ->
-    list_to_atom(atom_to_list(Proto) ++ ":dashboard").
+key_only(K , true , S)  -> [K | S];
+key_only(_K, false, S)  -> S;
+key_only(K , V    , S)  -> [{K, V} | S].
+
+listener_name(Protocol, Port) ->
+    Name = "dashboard:" ++ atom_to_list(Protocol) ++ ":" ++ integer_to_list(Port),
+    list_to_atom(Name).
 
 authorize_appid(Req) ->
     case cowboy_req:parse_header(<<"authorization">>, Req) of
@@ -127,10 +149,3 @@ authorize_appid(Req) ->
                   #{code => <<"UNAUTHORIZED">>,
                     message => <<"POST '/login'">>}}
     end.
-
-format(Port) when is_integer(Port) ->
-    io_lib:format("0.0.0.0:~w", [Port]);
-format({Addr, Port}) when is_list(Addr) ->
-    io_lib:format("~s:~w", [Addr, Port]);
-format({Addr, Port}) when is_tuple(Addr) ->
-    io_lib:format("~s:~w", [inet:ntoa(Addr), Port]).

+ 1 - 1
apps/emqx_dashboard/src/emqx_dashboard_app.erl

@@ -27,7 +27,7 @@
 start(_StartType, _StartArgs) ->
     {ok, Sup} = emqx_dashboard_sup:start_link(),
     ok = ekka_rlog:wait_for_shards([?DASHBOARD_SHARD], infinity),
-    emqx_dashboard:start_listeners(),
+    _ = emqx_dashboard:start_listeners(),
     emqx_dashboard_cli:load(),
     ok = emqx_dashboard_admin:add_default_user(),
     {ok, Sup}.

+ 2 - 3
apps/emqx_dashboard/src/emqx_dashboard_schema.erl

@@ -37,14 +37,13 @@ fields("http") ->
     , {"num_acceptors", emqx_schema:t(integer(), undefined, 4)}
     , {"max_connections", emqx_schema:t(integer(), undefined, 512)}
     , {"backlog", emqx_schema:t(integer(), undefined, 1024)}
-    , {"send_timeout", emqx_schema:t(emqx_schema:duration(), undefined, "15s")}
-    , {"send_timeout_close", emqx_schema:t(boolean(), undefined, true)}
+    , {"send_timeout", emqx_schema:t(emqx_schema:duration(), undefined, "5s")}
     , {"inet6", emqx_schema:t(boolean(), undefined, false)}
     , {"ipv6_v6only", emqx_schema:t(boolean(), undefined, false)}
     ];
 
 fields("https") ->
-    emqx_schema:ssl(#{enable => true}) ++ fields("http").
+    proplists:delete("fail_if_no_peer_cert", emqx_schema:ssl(#{})) ++ fields("http").
 
 default_username(type) -> string();
 default_username(default) -> "admin";

+ 1 - 1
rebar.config

@@ -51,7 +51,7 @@
     , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.8.2"}}}
     , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.10.8"}}}
     , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.5.1"}}}
-    , {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.0"}}}
+    , {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.1"}}}
     , {ecpool, {git, "https://github.com/emqx/ecpool", {tag, "0.5.1"}}}
     , {replayq, "0.3.3"}
     , {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}}