diff --git a/apps/emqx_dashboard/etc/emqx_dashboard.conf b/apps/emqx_dashboard/etc/emqx_dashboard.conf index 70b1d1d71..ba2a68eeb 100644 --- a/apps/emqx_dashboard/etc/emqx_dashboard.conf +++ b/apps/emqx_dashboard/etc/emqx_dashboard.conf @@ -37,4 +37,7 @@ emqx_dashboard { # ciphers = ["TLS_AES_256_GCM_SHA384","TLS_AES_128_GCM_SHA256","TLS_CHACHA20_POLY1305_SHA256","TLS_AES_128_CCM_SHA256","TLS_AES_128_CCM_8_SHA256","ECDHE-ECDSA-AES256-GCM-SHA384","ECDHE-RSA-AES256-GCM-SHA384","ECDHE-ECDSA-AES256-SHA384","ECDHE-RSA-AES256-SHA384","ECDHE-ECDSA-DES-CBC3-SHA","ECDH-ECDSA-AES256-GCM-SHA384","ECDH-RSA-AES256-GCM-SHA384","ECDH-ECDSA-AES256-SHA384","ECDH-RSA-AES256-SHA384","DHE-DSS-AES256-GCM-SHA384","DHE-DSS-AES256-SHA256","AES256-GCM-SHA384","AES256-SHA256","ECDHE-ECDSA-AES128-GCM-SHA256","ECDHE-RSA-AES128-GCM-SHA256","ECDHE-ECDSA-AES128-SHA256","ECDHE-RSA-AES128-SHA256","ECDH-ECDSA-AES128-GCM-SHA256","ECDH-RSA-AES128-GCM-SHA256","ECDH-ECDSA-AES128-SHA256","ECDH-RSA-AES128-SHA256","DHE-DSS-AES128-GCM-SHA256","DHE-DSS-AES128-SHA256","AES128-GCM-SHA256","AES128-SHA256","ECDHE-ECDSA-AES256-SHA","ECDHE-RSA-AES256-SHA","DHE-DSS-AES256-SHA","ECDH-ECDSA-AES256-SHA","ECDH-RSA-AES256-SHA","AES256-SHA","ECDHE-ECDSA-AES128-SHA","ECDHE-RSA-AES128-SHA","DHE-DSS-AES128-SHA","ECDH-ECDSA-AES128-SHA","ECDH-RSA-AES128-SHA","AES128-SHA"] # } ] + + ## CORS Support. don't set cors true if you don't know what it means. + # cors = false } diff --git a/apps/emqx_dashboard/src/emqx_dashboard.erl b/apps/emqx_dashboard/src/emqx_dashboard.erl index 2a5066d50..7e24c73ab 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard.erl @@ -29,6 +29,8 @@ -define(BASE_PATH, "/api/v5"). +-define(EMQX_MIDDLE, emqx_dashboard_middleware). + %%-------------------------------------------------------------------- %% Start/Stop Listeners %%-------------------------------------------------------------------- @@ -42,9 +44,9 @@ start_listeners() -> servers => [#{url => ?BASE_PATH}], components => #{ schemas => #{}, - securitySchemes => #{ + 'securitySchemes' => #{ application => #{ - type => apiKey, + type => 'apiKey', name => "authorization", in => header}}}}, Dispatch = [{"/", cowboy_static, {priv_file, emqx_dashboard, "www/index.html"}}, @@ -57,7 +59,8 @@ start_listeners() -> authorization => Authorization, security => [#{application => []}], swagger_global_spec => GlobalSpec, - dispatch => Dispatch + dispatch => Dispatch, + middlewares => [cowboy_router, ?EMQX_MIDDLE, cowboy_handler] }, [begin Minirest = maps:put(protocol, Protocol, BaseMinirest), @@ -101,19 +104,16 @@ ranch_opts(RanchOptions) -> R#{socket_opts => maps:fold(fun key_only/3, [], S)}. -key_take({K, K1}, {All, R}) -> +key_take(Key, {All, R}) -> + {K, KX} = case Key of + {K1, K2} -> {K1, K2}; + _ -> {Key, Key} + end, 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}} + {maps:remove(K, All), R#{KX => V}} end. key_only(K , true , S) -> [K | S]; diff --git a/apps/emqx_dashboard/src/emqx_dashboard_middleware.erl b/apps/emqx_dashboard/src/emqx_dashboard_middleware.erl new file mode 100644 index 000000000..8a7de99b8 --- /dev/null +++ b/apps/emqx_dashboard/src/emqx_dashboard_middleware.erl @@ -0,0 +1,33 @@ +%%-------------------------------------------------------------------- +%% Copyright (c) 2020-2021 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_dashboard_middleware). + +-behaviour(cowboy_middleware). + +-export([execute/2]). + +execute(Req, Env) -> + CORS = emqx_conf:get([emqx_dashboard, cors], false), + case CORS andalso cowboy_req:header(<<"origin">>, Req, undefined) of + false -> + {ok, Req, Env}; + undefined -> + {ok, Req, Env}; + _ -> + Req2 = cowboy_req:set_resp_header(<<"Access-Control-Allow-Origin">>, <<"*">>, Req), + {ok, Req2, Env} + end. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl index 58e154da8..8ef95a8cf 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl @@ -31,6 +31,7 @@ fields("emqx_dashboard") -> , {default_password, fun default_password/1} , {sample_interval, sc(emqx_schema:duration_s(), #{default => "10s"})} , {token_expired_time, sc(emqx_schema:duration(), #{default => "30m"})} + , {cors, fun cors/1} ]; fields("http") -> @@ -41,7 +42,7 @@ fields("http") -> , {"backlog", sc(integer(), #{default => 1024})} , {"send_timeout", sc(emqx_schema:duration(), #{default => "5s"})} , {"inet6", sc(boolean(), #{default => false})} - , {"ipv6_v6only", sc(boolean(), #{dfeault => false})} + , {"ipv6_v6only", sc(boolean(), #{default => false})} ]; fields("https") -> @@ -63,4 +64,9 @@ The initial default password for dashboard 'admin' user. For safty, it should be changed as soon as possible."""; default_password(_) -> undefined. +cors(type) -> boolean(); +cors(default) -> false; +cors(nullable) -> true; +cors(_) -> undefined. + sc(Type, Meta) -> hoconsc:mk(Type, Meta). diff --git a/rebar.config b/rebar.config index 02a6abd30..fd4b1aa1f 100644 --- a/rebar.config +++ b/rebar.config @@ -54,7 +54,7 @@ , {esockd, {git, "https://github.com/emqx/esockd", {tag, "5.9.0"}}} , {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.1"}}} , {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.5.1"}}} - , {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.6"}}} + , {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.7"}}} , {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"}}}