diff --git a/.ci/build_packages/tests.sh b/.ci/build_packages/tests.sh index d3a2a6858..87c19621a 100755 --- a/.ci/build_packages/tests.sh +++ b/.ci/build_packages/tests.sh @@ -48,7 +48,7 @@ emqx_test(){ exit 1 fi IDLE_TIME=0 - while ! curl http://localhost:8081/api/v5/status >/dev/null 2>&1; do + while ! curl http://localhost:18083/api/v5/status >/dev/null 2>&1; do if [ $IDLE_TIME -gt 10 ] then echo "emqx running error" @@ -139,7 +139,7 @@ EOF exit 1 fi IDLE_TIME=0 - while ! curl http://localhost:8081/api/v5/status >/dev/null 2>&1; do + while ! curl http://localhost:18083/api/v5/status >/dev/null 2>&1; do if [ $IDLE_TIME -gt 10 ] then echo "emqx running error" @@ -168,7 +168,7 @@ EOF exit 1 fi IDLE_TIME=0 - while ! curl http://localhost:8081/api/v5/status >/dev/null 2>&1; do + while ! curl http://localhost:18083/api/v5/status >/dev/null 2>&1; do if [ $IDLE_TIME -gt 10 ] then echo "emqx service error" diff --git a/.ci/docker-compose-file/haproxy/haproxy.cfg b/.ci/docker-compose-file/haproxy/haproxy.cfg index 4361ccadb..b658789da 100644 --- a/.ci/docker-compose-file/haproxy/haproxy.cfg +++ b/.ci/docker-compose-file/haproxy/haproxy.cfg @@ -33,7 +33,7 @@ defaults frontend emqx_mgmt mode tcp option tcplog - bind *:8081 + bind *:18083 default_backend emqx_mgmt_back frontend emqx_dashboard @@ -45,8 +45,8 @@ frontend emqx_dashboard backend emqx_mgmt_back mode http # balance static-rr - server emqx-1 node1.emqx.io:8081 - server emqx-2 node2.emqx.io:8081 + server emqx-1 node1.emqx.io:18083 + server emqx-2 node2.emqx.io:18083 backend emqx_dashboard_back mode http diff --git a/.github/workflows/build_packages.yaml b/.github/workflows/build_packages.yaml index f42835a18..0c6d065a9 100644 --- a/.github/workflows/build_packages.yaml +++ b/.github/workflows/build_packages.yaml @@ -197,7 +197,7 @@ jobs: ./emqx/bin/emqx start || cat emqx/log/erlang.log.1 ready='no' for i in {1..10}; do - if curl -fs 127.0.0.1:8081/api/v5/status > /dev/null; then + if curl -fs 127.0.0.1:18083/api/v5/status > /dev/null; then ready='yes' break fi diff --git a/.github/workflows/build_slim_packages.yaml b/.github/workflows/build_slim_packages.yaml index 9e19889fc..9578c6f9d 100644 --- a/.github/workflows/build_slim_packages.yaml +++ b/.github/workflows/build_slim_packages.yaml @@ -113,7 +113,7 @@ jobs: ./emqx/bin/emqx start || cat emqx/log/erlang.log.1 ready='no' for i in {1..10}; do - if curl -fs 127.0.0.1:8081/api/v5/status > /dev/null; then + if curl -fs 127.0.0.1:18083/api/v5/status > /dev/null; then ready='yes' break fi diff --git a/apps/emqx/rebar.config b/apps/emqx/rebar.config index 60f257f30..c2229ce0f 100644 --- a/apps/emqx/rebar.config +++ b/apps/emqx/rebar.config @@ -28,7 +28,7 @@ [{deps, [ meck , {bbmustache,"1.10.0"} - , {emqx_ct_helpers, {git,"https://github.com/emqx/emqx-ct-helpers", {branch,"hocon"}}} + , {emqx_ct_helpers, {git,"https://github.com/emqx/emqx-ct-helpers.git", {branch,"hocon"}}} , {emqtt, {git, "https://github.com/emqx/emqtt", {tag, "1.4.2"}}} ]}, {extra_src_dirs, [{"test",[recursive]}]} diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config index 888a03bc4..57bf1245c 100644 --- a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config +++ b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_hocon_plugin/rebar.config @@ -17,7 +17,7 @@ {profiles, [{test, [ - {deps, [ {emqx_ct_helper, {git, "https://github.com/emqx/emqx-ct-helpers", {tag, "v1.1.4"}}} + {deps, [{emqx_ct_helpers, {git,"https://github.com/emqx/emqx-ct-helpers.git", {branch,"hocon"}}} ]} ]} ]}. diff --git a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config index 4c49da1dc..b2bf39c55 100644 --- a/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config +++ b/apps/emqx/test/emqx_plugins_SUITE_data/emqx_mini_plugin/rebar.config @@ -17,7 +17,7 @@ {profiles, [{test, [ - {deps, [ {emqx_ct_helper, {git, "https://github.com/emqx/emqx-ct-helpers", {tag, "v1.1.4"}}} + {deps, [{emqx_ct_helpers, {git,"https://github.com/emqx/emqx-ct-helpers.git", {branch,"hocon"}}} ]} ]} ]}. diff --git a/apps/emqx_authz/test/emqx_authz_api_SUITE.erl b/apps/emqx_authz/test/emqx_authz_api_SUITE.erl index 56d0170c1..b88afc57b 100644 --- a/apps/emqx_authz/test/emqx_authz_api_SUITE.erl +++ b/apps/emqx_authz/test/emqx_authz_api_SUITE.erl @@ -33,7 +33,7 @@ , auth_header/2 ]). --define(HOST, "http://127.0.0.1:8081/"). +-define(HOST, "http://127.0.0.1:18083/"). -define(API_VERSION, "v5"). -define(BASE_PATH, "api"). @@ -100,11 +100,9 @@ init_per_suite(Config) -> meck:expect(emqx_resource, health_check, fun(_) -> ok end), meck:expect(emqx_resource, remove, fun(_) -> ok end ), - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - ok = emqx_config:init_load(emqx_authz_schema, ?CONF_DEFAULT), - ok = emqx_ct_helpers:start_apps([emqx_management, emqx_authz], fun set_special_configs/1), + + ok = emqx_ct_helpers:start_apps([emqx_authz, emqx_dashboard], fun set_special_configs/1), {ok, _} = emqx:update_config([authorization, cache, enable], false), {ok, _} = emqx:update_config([authorization, no_match], deny), @@ -112,13 +110,20 @@ init_per_suite(Config) -> end_per_suite(_Config) -> {ok, _} = emqx_authz:update(replace, []), - emqx_ct_helpers:stop_apps([emqx_resource, emqx_authz, emqx_management]), + emqx_ct_helpers:stop_apps([emqx_resource, emqx_authz, emqx_dashboard]), meck:unload(emqx_resource), ok. -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), +set_special_configs(emqx_dashboard) -> + Config = #{ + default_username => <<"admin">>, + default_password => <<"public">>, + listeners => [#{ + protocol => http, + port => 18083 + }] + }, + emqx_config:put([emqx_dashboard], Config), ok; set_special_configs(emqx_authz) -> emqx_config:put([authorization_rules], #{rules => []}), @@ -225,8 +230,8 @@ t_move_rule(_) -> request(Method, Url, Body) -> Request = case Body of - [] -> {Url, [auth_header("admin", "public")]}; - _ -> {Url, [auth_header("admin", "public")], "application/json", jsx:encode(Body)} + [] -> {Url, [auth_header_()]}; + _ -> {Url, [auth_header_()], "application/json", jsx:encode(Body)} end, ct:pal("Method: ~p, Request: ~p", [Method, Request]), case httpc:request(Method, Request, [], [{body_format, binary}]) of @@ -245,3 +250,9 @@ uri(Parts) when is_list(Parts) -> get_rules(Result) -> maps:get(<<"rules">>, jsx:decode(Result), []). + +auth_header_() -> + Username = <<"admin">>, + Password = <<"public">>, + {ok, Token} = emqx_dashboard_admin:sign_token(Username, Password), + {"Authorization", "Bearer " ++ binary_to_list(Token)}. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl index 6cca17390..018061ff6 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_schema.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_schema.erl @@ -33,7 +33,7 @@ fields("emqx_dashboard") -> fields("http") -> [ {"protocol", hoconsc:enum([http, https])} - , {"port", emqx_schema:t(integer(), undefined, 8081)} + , {"port", emqx_schema:t(integer(), undefined, 18083)} , {"num_acceptors", emqx_schema:t(integer(), undefined, 4)} , {"max_connections", emqx_schema:t(integer(), undefined, 512)} , {"backlog", emqx_schema:t(integer(), undefined, 1024)} diff --git a/apps/emqx_machine/src/emqx_machine_schema.erl b/apps/emqx_machine/src/emqx_machine_schema.erl index 7dd193e63..a8cba047d 100644 --- a/apps/emqx_machine/src/emqx_machine_schema.erl +++ b/apps/emqx_machine/src/emqx_machine_schema.erl @@ -51,7 +51,6 @@ , emqx_auto_subscribe_schema , emqx_bridge_mqtt_schema , emqx_modules_schema - , emqx_management_schema , emqx_dashboard_schema , emqx_gateway_schema , emqx_prometheus_schema diff --git a/apps/emqx_management/etc/emqx_management.conf b/apps/emqx_management/etc/emqx_management.conf index 8517aec7f..e69de29bb 100644 --- a/apps/emqx_management/etc/emqx_management.conf +++ b/apps/emqx_management/etc/emqx_management.conf @@ -1,42 +0,0 @@ -emqx_management { - applications = [ - { - id = "admin", - secret = "public" - } - ] - max_row_limit = 10000 - listeners = [ - { - num_acceptors = 4 - max_connections = 512 - protocol = http - port = 8081 - backlog = 512 - send_timeout = 15s - send_timeout_close = true - inet6 = false - ipv6_v6only = false - } -## , -## { -## protocol: https -## port: 8081 -## acceptors: 2 -## backlog: 512 -## send_timeout: 15s -## send_timeout_close: true -## inet6: false -## ipv6_v6only: false -## certfile = "etc/certs/cert.pem" -## keyfile = "etc/certs/key.pem" -## cacertfile = "etc/certs/cacert.pem" -## verify = verify_peer -## tls_versions = "tlsv1.3,tlsv1.2,tlsv1.1,tlsv1" -## 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" -## fail_if_no_peer_cert = true -## inet6 = false -## ipv6_v6only = false -## } - ] -} diff --git a/apps/emqx_management/include/emqx_mgmt.hrl b/apps/emqx_management/include/emqx_mgmt.hrl index 40baec4e1..ea8687dcd 100644 --- a/apps/emqx_management/include/emqx_mgmt.hrl +++ b/apps/emqx_management/include/emqx_mgmt.hrl @@ -14,50 +14,6 @@ %% limitations under the License. %%-------------------------------------------------------------------- -%% Return Codes --define(SUCCESS, 0). %% Success --define(ERROR1, 101). %% badrpc --define(ERROR2, 102). %% Unknown error --define(ERROR3, 103). %% Username or password error --define(ERROR4, 104). %% Empty username or password --define(ERROR5, 105). %% User does not exist --define(ERROR6, 106). %% Admin can not be deleted --define(ERROR7, 107). %% Missing request parameter --define(ERROR8, 108). %% Request parameter type error --define(ERROR9, 109). %% Request parameter is not a json --define(ERROR10, 110). %% Plugin has been loaded --define(ERROR11, 111). %% Plugin has been unloaded --define(ERROR12, 112). %% Client not online --define(ERROR13, 113). %% User already exist --define(ERROR14, 114). %% OldPassword error --define(ERROR15, 115). %% bad topic - --define(VERSIONS, ["4.0", "4.1", "4.2", "4.3"]). - -define(MANAGEMENT_SHARD, emqx_management_shard). --define(GENERATE_API_METADATA(MetaData), - maps:fold( - fun(Method, MethodDef0, NextMetaData) -> - Default = #{ - tags => [?MODULE], - security => [#{application => []}]}, - MethodDef = - lists:foldl( - fun(Key, NMethodDef) -> - case maps:is_key(Key, NMethodDef) of - true -> - NMethodDef; - false -> - maps:put(Key, maps:get(Key, Default), NMethodDef) - end - end, MethodDef0, maps:keys(Default)), - maps:put(Method, MethodDef, NextMetaData) - end, - #{}, MetaData)). - --define(GENERATE_API(Path, MetaData, Function), - {Path, ?GENERATE_API_METADATA(MetaData), Function}). - --define(GENERATE_APIS(Apis), - [?GENERATE_API(Path, MetaData, Function) || {Path, MetaData, Function} <- Apis]). +-define(MAX_ROW_LIMIT, 100). diff --git a/apps/emqx_management/src/emqx_management_schema.erl b/apps/emqx_management/src/emqx_management_schema.erl index f9543697f..a0da91d86 100644 --- a/apps/emqx_management/src/emqx_management_schema.erl +++ b/apps/emqx_management/src/emqx_management_schema.erl @@ -22,36 +22,6 @@ -export([ structs/0 , fields/1]). -structs() -> ["emqx_management"]. +structs() -> []. -fields("emqx_management") -> - [ {applications, hoconsc:array(hoconsc:ref(?MODULE, "application"))} - , {max_row_limit, fun max_row_limit/1} - , {listeners, hoconsc:array(hoconsc:union([hoconsc:ref(?MODULE, "http"), hoconsc:ref(?MODULE, "https")]))} - ]; - -fields("application") -> - [ {"id", emqx_schema:t(string(), undefined, "admin")} - , {"secret", emqx_schema:t(string(), undefined, "public")} - ]; - - -fields("http") -> - [ {"protocol", hoconsc:enum([http, https])} - , {"port", emqx_schema:t(integer(), undefined, 8081)} - , {"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)} - , {"inet6", emqx_schema:t(boolean(), undefined, false)} - , {"ipv6_v6only", emqx_schema:t(boolean(), undefined, false)} - ]; - -fields("https") -> - emqx_schema:ssl(#{enable => true}) ++ fields("http"). - -max_row_limit(type) -> integer(); -max_row_limit(default) -> 1000; -max_row_limit(nullable) -> false; -max_row_limit(_) -> undefined. +fields(_) -> []. diff --git a/apps/emqx_management/src/emqx_mgmt.erl b/apps/emqx_management/src/emqx_mgmt.erl index 4a7fefb2d..29f8de0d3 100644 --- a/apps/emqx_management/src/emqx_mgmt.erl +++ b/apps/emqx_management/src/emqx_mgmt.erl @@ -114,8 +114,6 @@ -export([ return/0 , return/1]). --define(MAX_ROW_LIMIT, 10000). - -define(APP, emqx_management). %% TODO: remove these function after all api use minirest version 1.X @@ -590,7 +588,7 @@ check_row_limit([Tab|Tables], Limit) -> end. max_row_limit() -> - emqx:get_config([?APP, max_row_limit], ?MAX_ROW_LIMIT). + ?MAX_ROW_LIMIT. table_size(Tab) -> ets:info(Tab, size). diff --git a/apps/emqx_management/src/emqx_mgmt_api_apps.erl b/apps/emqx_management/src/emqx_mgmt_api_apps.erl deleted file mode 100644 index 64a84b381..000000000 --- a/apps/emqx_management/src/emqx_mgmt_api_apps.erl +++ /dev/null @@ -1,214 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_api_apps). - --behaviour(minirest_api). - --import(emqx_mgmt_util, [ schema/1 - , schema/2 - , object_schema/1 - , object_schema/2 - , object_array_schema/2 - , error_schema/1 - , error_schema/2 - , properties/1 - ]). - --export([api_spec/0]). - --export([ apps/2 - , app/2]). - --define(BAD_APP_ID, 'BAD_APP_ID'). --define(APP_ID_NOT_FOUND, <<"{\"code\": \"BAD_APP_ID\", \"reason\": \"App id not found\"}">>). - -api_spec() -> - { - [apps_api(), app_api()], - [] - }. - -properties() -> - properties([ - {app_id, string, <<"App ID">>}, - {secret, string, <<"App Secret">>}, - {name, string, <<"Dsiplay name">>}, - {desc, string, <<"App description">>}, - {status, boolean, <<"Enable or disable">>}, - {expired, integer, <<"Expired time">>} - ]). - -%% not export schema -app_without_secret_schema() -> - maps:without([secret], properties()). - -apps_api() -> - Metadata = #{ - get => #{ - description => <<"List EMQ X apps">>, - responses => #{ - <<"200">> => - object_array_schema(app_without_secret_schema(), <<"All apps">>) - } - }, - post => #{ - description => <<"EMQ X create apps">>, - 'requestBody' => schema(app), - responses => #{ - <<"200">> => - schema(app_secret, <<"Create apps">>), - <<"400">> => - error_schema(<<"App ID already exist">>, [?BAD_APP_ID]) - } - } - }, - {"/apps", Metadata, apps}. - -app_api() -> - Metadata = #{ - get => #{ - description => <<"EMQ X apps">>, - parameters => [#{ - name => app_id, - in => path, - required => true, - schema => #{type => string}}], - responses => #{ - <<"404">> => - error_schema(<<"App id not found">>), - <<"200">> => - object_schema(app_without_secret_schema(), <<"Get App">>)}}, - delete => #{ - description => <<"EMQ X apps">>, - parameters => [#{ - name => app_id, - in => path, - required => true, - schema => #{type => string} - }], - responses => #{ - <<"200">> => schema(<<"Remove app ok">>)}}, - put => #{ - description => <<"EMQ X update apps">>, - parameters => [#{ - name => app_id, - in => path, - required => true, - schema => #{type => string} - }], - 'requestBody' => object_schema(app_without_secret_schema()), - responses => #{ - <<"404">> => - error_schema(<<"App id not found">>, [?BAD_APP_ID]), - <<"200">> => - object_schema(app_without_secret_schema(), <<"Update ok">>)}}}, - {"/apps/:app_id", Metadata, app}. - -%%%============================================================================================== -%% parameters trans -apps(get, _Params) -> - list(#{}); - -apps(post, #{body := Data}) -> - Parameters = #{ - app_id => maps:get(<<"app_id">>, Data), - name => maps:get(<<"name">>, Data), - secret => maps:get(<<"secret">>, Data), - desc => maps:get(<<"desc">>, Data), - status => maps:get(<<"status">>, Data), - expired => maps:get(<<"expired">>, Data, undefined) - }, - create(Parameters). - -app(get, #{bindings := #{app_id := AppID}}) -> - lookup(#{app_id => AppID}); - -app(delete, #{bindings := #{app_id := AppID}}) -> - delete(#{app_id => AppID}); - -app(put, #{bindings := #{app_id := AppID}, body := Data}) -> - Parameters = #{ - app_id => AppID, - name => maps:get(<<"name">>, Data), - desc => maps:get(<<"desc">>, Data), - status => maps:get(<<"status">>, Data), - expired => maps:get(<<"expired">>, Data, undefined) - }, - update(Parameters). - - -%%%============================================================================================== -%% api apply -list(_) -> - {200, [format_without_app_secret(Apps) || Apps <- emqx_mgmt_auth:list_apps()]}. - -create(#{app_id := AppID, name := Name, secret := Secret, - desc := Desc, status := Status, expired := Expired}) -> - case emqx_mgmt_auth:add_app(AppID, Name, Secret, Desc, Status, Expired) of - {ok, AppSecret} -> - {200, #{secret => AppSecret}}; - {error, alread_existed} -> - Message = list_to_binary(io_lib:format("appid ~p already existed", [AppID])), - {400, #{code => 'BAD_APP_ID', message => Message}}; - {error, Reason} -> - Response = #{code => 'UNKNOW_ERROR', - message => list_to_binary(io_lib:format("~p", [Reason]))}, - {500, Response} - end. - -lookup(#{app_id := AppID}) -> - case emqx_mgmt_auth:lookup_app(AppID) of - undefined -> - {404, ?APP_ID_NOT_FOUND}; - App -> - Response = format_with_app_secret(App), - {200, Response} - end. - -delete(#{app_id := AppID}) -> - _ = emqx_mgmt_auth:del_app(AppID), - {200}. - -update(App = #{app_id := AppID, name := Name, desc := Desc, status := Status, expired := Expired}) -> - case emqx_mgmt_auth:update_app(AppID, Name, Desc, Status, Expired) of - ok -> - {200, App}; - {error, not_found} -> - {404, ?APP_ID_NOT_FOUND}; - {error, Reason} -> - Response = #{code => 'UNKNOW_ERROR', message => list_to_binary(io_lib:format("~p", [Reason]))}, - {500, Response} - end. - -%%%============================================================================================== -%% format -format_without_app_secret(App) -> - format_without([secret], App). - -format_with_app_secret(App) -> - format_without([], App). - -format_without(List, {AppID, AppSecret, Name, Desc, Status, Expired}) -> - Data = #{ - app_id => AppID, - secret => AppSecret, - name => Name, - desc => Desc, - status => Status, - expired => Expired - }, - maps:without(List, Data). diff --git a/apps/emqx_management/src/emqx_mgmt_api_authz.erl b/apps/emqx_management/src/emqx_mgmt_api_authz.erl deleted file mode 100644 index 6da16ff30..000000000 --- a/apps/emqx_management/src/emqx_mgmt_api_authz.erl +++ /dev/null @@ -1,47 +0,0 @@ -%%-------------------------------------------------------------------- -%% Copyright (c) 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_mgmt_api_authz). - --include("emqx_mgmt.hrl"). - --rest_api(#{name => clean_authz_cache_all, - method => 'DELETE', - path => "/authz-cache", - func => clean_all, - descr => "Clean authz cache on all nodes"}). - --rest_api(#{name => clean_authz_cache_node, - method => 'DELETE', - path => "nodes/:atom:node/authz-cache", - func => clean_node, - descr => "Clean authz cache on specific node"}). - --export([ clean_all/2 - , clean_node/2 - ]). - -clean_all(_Bindings, _Params) -> - case emqx_mgmt:clean_authz_cache_all() of - ok -> emqx_mgmt:return(); - {error, Reason} -> emqx_mgmt:return({error, ?ERROR1, Reason}) - end. - -clean_node(#{node := Node}, _Params) -> - case emqx_mgmt:clean_authz_cache_all(Node) of - ok -> emqx_mgmt:return(); - {error, Reason} -> emqx_mgmt:return({error, ?ERROR1, Reason}) - end. diff --git a/apps/emqx_management/src/emqx_mgmt_api_banned.erl b/apps/emqx_management/src/emqx_mgmt_api_banned.erl deleted file mode 100644 index bdd43b35c..000000000 --- a/apps/emqx_management/src/emqx_mgmt_api_banned.erl +++ /dev/null @@ -1,166 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_api_banned). - --include_lib("emqx/include/emqx.hrl"). - --include("emqx_mgmt.hrl"). - --rest_api(#{name => list_banned, - method => 'GET', - path => "/banned/", - func => list, - descr => "List banned"}). - --rest_api(#{name => create_banned, - method => 'POST', - path => "/banned/", - func => create, - descr => "Create banned"}). - --rest_api(#{name => delete_banned, - method => 'DELETE', - path => "/banned/:as/:who", - func => delete, - descr => "Delete banned"}). - --export([ list/2 - , create/2 - , delete/2 - ]). - -list(_Bindings, Params) -> - emqx_mgmt:return({ok, emqx_mgmt_api:paginate(emqx_banned, Params, fun format/1)}). - -create(_Bindings, Params) -> - case pipeline([fun ensure_required/1, - fun validate_params/1], Params) of - {ok, NParams} -> - {ok, Banned} = pack_banned(NParams), - ok = emqx_mgmt:create_banned(Banned), - emqx_mgmt:return({ok, maps:from_list(Params)}); - {error, Code, Message} -> - emqx_mgmt:return({error, Code, Message}) - end. - -delete(#{as := As, who := Who}, _) -> - Params = [{<<"who">>, bin(emqx_mgmt_util:urldecode(Who))}, - {<<"as">>, bin(emqx_mgmt_util:urldecode(As))}], - case pipeline([fun ensure_required/1, - fun validate_params/1], Params) of - {ok, NParams} -> - do_delete(proplists:get_value(<<"as">>, NParams), proplists:get_value(<<"who">>, NParams)), - emqx_mgmt:return(); - {error, Code, Message} -> - emqx_mgmt:return({error, Code, Message}) - end. - -pipeline([], Params) -> - {ok, Params}; -pipeline([Fun|More], Params) -> - case Fun(Params) of - {ok, NParams} -> - pipeline(More, NParams); - {error, Code, Message} -> - {error, Code, Message} - end. - -%% Plugs -ensure_required(Params) when is_list(Params) -> - #{required_params := RequiredParams, message := Msg} = required_params(), - AllIncluded = lists:all(fun(Key) -> - lists:keymember(Key, 1, Params) - end, RequiredParams), - case AllIncluded of - true -> {ok, Params}; - false -> - {error, ?ERROR7, Msg} - end. - -validate_params(Params) -> - #{enum_values := AsEnums, message := Msg} = enum_values(as), - case lists:member(proplists:get_value(<<"as">>, Params), AsEnums) of - true -> {ok, Params}; - false -> - {error, ?ERROR8, Msg} - end. - -pack_banned(Params) -> - Now = erlang:system_time(second), - do_pack_banned(Params, #{by => <<"user">>, at => Now, until => Now + 300}). - -do_pack_banned([], #{who := Who, by := By, reason := Reason, at := At, until := Until}) -> - {ok, #banned{who = Who, by = By, reason = Reason, at = At, until = Until}}; -do_pack_banned([{<<"who">>, Who} | Params], Banned) -> - case lists:keytake(<<"as">>, 1, Params) of - {value, {<<"as">>, <<"peerhost">>}, Params2} -> - {ok, IPAddress} = inet:parse_address(str(Who)), - do_pack_banned(Params2, Banned#{who => {peerhost, IPAddress}}); - {value, {<<"as">>, <<"clientid">>}, Params2} -> - do_pack_banned(Params2, Banned#{who => {clientid, Who}}); - {value, {<<"as">>, <<"username">>}, Params2} -> - do_pack_banned(Params2, Banned#{who => {username, Who}}) - end; -do_pack_banned([P1 = {<<"as">>, _}, P2 | Params], Banned) -> - do_pack_banned([P2, P1 | Params], Banned); -do_pack_banned([{<<"by">>, By} | Params], Banned) -> - do_pack_banned(Params, Banned#{by => By}); -do_pack_banned([{<<"reason">>, Reason} | Params], Banned) -> - do_pack_banned(Params, Banned#{reason => Reason}); -do_pack_banned([{<<"at">>, At} | Params], Banned) -> - do_pack_banned(Params, Banned#{at => At}); -do_pack_banned([{<<"until">>, Until} | Params], Banned) -> - do_pack_banned(Params, Banned#{until => Until}); -do_pack_banned([_P | Params], Banned) -> %% ignore other params - do_pack_banned(Params, Banned). - -do_delete(<<"peerhost">>, Who) -> - {ok, IPAddress} = inet:parse_address(str(Who)), - emqx_mgmt:delete_banned({peerhost, IPAddress}); -do_delete(<<"username">>, Who) -> - emqx_mgmt:delete_banned({username, bin(Who)}); -do_delete(<<"clientid">>, Who) -> - emqx_mgmt:delete_banned({clientid, bin(Who)}). - -required_params() -> - #{required_params => [<<"who">>, <<"as">>], - message => <<"missing mandatory params: ['who', 'as']">> }. - -enum_values(as) -> - #{enum_values => [<<"clientid">>, <<"username">>, <<"peerhost">>], - message => <<"value of 'as' must be one of: ['clientid', 'username', 'peerhost']">> }. - -%% Internal Functions - -format(BannedList) when is_list(BannedList) -> - [format(Ban) || Ban <- BannedList]; -format(#banned{who = {As, Who}, by = By, reason = Reason, at = At, until = Until}) -> - #{who => case As of - peerhost -> bin(inet:ntoa(Who)); - _ -> Who - end, - as => As, by => By, reason => Reason, at => At, until => Until}. - -bin(L) when is_list(L) -> - list_to_binary(L); -bin(B) when is_binary(B) -> - B. - -str(B) when is_binary(B) -> - binary_to_list(B); -str(L) when is_list(L) -> - L. diff --git a/apps/emqx_management/src/emqx_mgmt_api_brokers.erl b/apps/emqx_management/src/emqx_mgmt_api_brokers.erl deleted file mode 100644 index 836f097cb..000000000 --- a/apps/emqx_management/src/emqx_mgmt_api_brokers.erl +++ /dev/null @@ -1,47 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_api_brokers). - --include("emqx_mgmt.hrl"). - --rest_api(#{name => list_brokers, - method => 'GET', - path => "/brokers/", - func => list, - descr => "A list of brokers in the cluster"}). - --rest_api(#{name => get_broker, - method => 'GET', - path => "/brokers/:atom:node", - func => get, - descr => "Get broker info of a node"}). - --export([ list/2 - , get/2 - ]). - -list(_Bindings, _Params) -> - emqx_mgmt:return({ok, [Info || {_Node, Info} <- emqx_mgmt:list_brokers()]}). - -get(#{node := Node}, _Params) -> - case emqx_mgmt:lookup_broker(Node) of - {error, Reason} -> - emqx_mgmt:return({error, ?ERROR2, Reason}); - Info -> - emqx_mgmt:return({ok, Info}) - end. - diff --git a/apps/emqx_management/src/emqx_mgmt_api_plugins.erl b/apps/emqx_management/src/emqx_mgmt_api_plugins.erl deleted file mode 100644 index fda7151d7..000000000 --- a/apps/emqx_management/src/emqx_mgmt_api_plugins.erl +++ /dev/null @@ -1,113 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_api_plugins). - --include("emqx_mgmt.hrl"). - --include_lib("emqx/include/emqx.hrl"). - --rest_api(#{name => list_all_plugins, - method => 'GET', - path => "/plugins/", - func => list, - descr => "List all plugins in the cluster"}). - --rest_api(#{name => list_node_plugins, - method => 'GET', - path => "/nodes/:atom:node/plugins/", - func => list, - descr => "List all plugins on a node"}). - --rest_api(#{name => load_node_plugin, - method => 'PUT', - path => "/nodes/:atom:node/plugins/:atom:plugin/load", - func => load, - descr => "Load a plugin"}). - --rest_api(#{name => unload_node_plugin, - method => 'PUT', - path => "/nodes/:atom:node/plugins/:atom:plugin/unload", - func => unload, - descr => "Unload a plugin"}). - --rest_api(#{name => reload_node_plugin, - method => 'PUT', - path => "/nodes/:atom:node/plugins/:atom:plugin/reload", - func => reload, - descr => "Reload a plugin"}). - --rest_api(#{name => unload_plugin, - method => 'PUT', - path => "/plugins/:atom:plugin/unload", - func => unload, - descr => "Unload a plugin in the cluster"}). - --rest_api(#{name => reload_plugin, - method => 'PUT', - path => "/plugins/:atom:plugin/reload", - func => reload, - descr => "Reload a plugin in the cluster"}). - --export([ list/2 - , load/2 - , unload/2 - , reload/2 - ]). - -list(#{node := Node}, _Params) -> - emqx_mgmt:return({ok, [format(Plugin) || Plugin <- emqx_mgmt:list_plugins(Node)]}); - -list(_Bindings, _Params) -> - emqx_mgmt:return({ok, [format({Node, Plugins}) || {Node, Plugins} <- emqx_mgmt:list_plugins()]}). - -load(#{node := Node, plugin := Plugin}, _Params) -> - emqx_mgmt:return(emqx_mgmt:load_plugin(Node, Plugin)). - -unload(#{node := Node, plugin := Plugin}, _Params) -> - emqx_mgmt:return(emqx_mgmt:unload_plugin(Node, Plugin)); - -unload(#{plugin := Plugin}, _Params) -> - Results = [emqx_mgmt:unload_plugin(Node, Plugin) || {Node, _Info} <- emqx_mgmt:list_nodes()], - case lists:filter(fun(Item) -> Item =/= ok end, Results) of - [] -> - emqx_mgmt:return(ok); - Errors -> - emqx_mgmt:return(lists:last(Errors)) - end. - -reload(#{node := Node, plugin := Plugin}, _Params) -> - emqx_mgmt:return(emqx_mgmt:reload_plugin(Node, Plugin)); - -reload(#{plugin := Plugin}, _Params) -> - Results = [emqx_mgmt:reload_plugin(Node, Plugin) || {Node, _Info} <- emqx_mgmt:list_nodes()], - case lists:filter(fun(Item) -> Item =/= ok end, Results) of - [] -> - emqx_mgmt:return(ok); - Errors -> - emqx_mgmt:return(lists:last(Errors)) - end. - -format({Node, Plugins}) -> - #{node => Node, plugins => [format(Plugin) || Plugin <- Plugins]}; - -format(#plugin{name = Name, - descr = Descr, - active = Active}) -> - #{name => Name, - description => iolist_to_binary(Descr), - active => Active}. - diff --git a/apps/emqx_management/src/emqx_mgmt_api_pubsub.erl b/apps/emqx_management/src/emqx_mgmt_api_pubsub.erl deleted file mode 100644 index 28e67c9f1..000000000 --- a/apps/emqx_management/src/emqx_mgmt_api_pubsub.erl +++ /dev/null @@ -1,247 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_api_pubsub). - --include_lib("emqx/include/emqx.hrl"). --include_lib("emqx/include/emqx_mqtt.hrl"). --include("emqx_mgmt.hrl"). - --rest_api(#{name => mqtt_subscribe, - method => 'POST', - path => "/mqtt/subscribe", - func => subscribe, - descr => "Subscribe a topic"}). - --rest_api(#{name => mqtt_publish, - method => 'POST', - path => "/mqtt/publish", - func => publish, - descr => "Publish a MQTT message"}). - --rest_api(#{name => mqtt_unsubscribe, - method => 'POST', - path => "/mqtt/unsubscribe", - func => unsubscribe, - descr => "Unsubscribe a topic"}). - --rest_api(#{name => mqtt_subscribe_batch, - method => 'POST', - path => "/mqtt/subscribe_batch", - func => subscribe_batch, - descr => "Batch subscribes topics"}). - --rest_api(#{name => mqtt_publish_batch, - method => 'POST', - path => "/mqtt/publish_batch", - func => publish_batch, - descr => "Batch publish MQTT messages"}). - --rest_api(#{name => mqtt_unsubscribe_batch, - method => 'POST', - path => "/mqtt/unsubscribe_batch", - func => unsubscribe_batch, - descr => "Batch unsubscribes topics"}). - --export([ subscribe/2 - , publish/2 - , unsubscribe/2 - , subscribe_batch/2 - , publish_batch/2 - , unsubscribe_batch/2 - ]). - -subscribe(_Bindings, Params) -> - logger:debug("API subscribe Params:~p", [Params]), - {ClientId, Topic, QoS} = parse_subscribe_params(Params), - emqx_mgmt:return(do_subscribe(ClientId, Topic, QoS)). - -publish(_Bindings, Params) -> - logger:debug("API publish Params:~p", [Params]), - {ClientId, Topic, Qos, Retain, Payload} = parse_publish_params(Params), - case do_publish(ClientId, Topic, Qos, Retain, Payload) of - {ok, MsgIds} -> - case proplists:get_value(<<"return">>, Params, undefined) of - undefined -> emqx_mgmt:return(ok); - _Val -> - case proplists:get_value(<<"topics">>, Params, undefined) of - undefined -> emqx_mgmt:return({ok, #{msgid => lists:last(MsgIds)}}); - _ -> emqx_mgmt:return({ok, #{msgids => MsgIds}}) - end - end; - Result -> - emqx_mgmt:return(Result) - end. - -unsubscribe(_Bindings, Params) -> - logger:debug("API unsubscribe Params:~p", [Params]), - {ClientId, Topic} = parse_unsubscribe_params(Params), - emqx_mgmt:return(do_unsubscribe(ClientId, Topic)). - -subscribe_batch(_Bindings, Params) -> - logger:debug("API subscribe batch Params:~p", [Params]), - emqx_mgmt:return({ok, loop_subscribe(Params)}). - -publish_batch(_Bindings, Params) -> - logger:debug("API publish batch Params:~p", [Params]), - emqx_mgmt:return({ok, loop_publish(Params)}). - -unsubscribe_batch(_Bindings, Params) -> - logger:debug("API unsubscribe batch Params:~p", [Params]), - emqx_mgmt:return({ok, loop_unsubscribe(Params)}). - -loop_subscribe(Params) -> - loop_subscribe(Params, []). -loop_subscribe([], Result) -> - lists:reverse(Result); -loop_subscribe([Params | ParamsN], Acc) -> - {ClientId, Topic, QoS} = parse_subscribe_params(Params), - Code = case do_subscribe(ClientId, Topic, QoS) of - ok -> 0; - {_, Code0, _Reason} -> Code0 - end, - Result = #{clientid => ClientId, - topic => resp_topic(proplists:get_value(<<"topic">>, Params), proplists:get_value(<<"topics">>, Params, <<"">>)), - code => Code}, - loop_subscribe(ParamsN, [Result | Acc]). - -loop_publish(Params) -> - loop_publish(Params, []). -loop_publish([], Result) -> - lists:reverse(Result); -loop_publish([Params | ParamsN], Acc) -> - {ClientId, Topic, Qos, Retain, Payload} = parse_publish_params(Params), - Code = case do_publish(ClientId, Topic, Qos, Retain, Payload) of - {ok, _} -> 0; - {_, Code0, _} -> Code0 - end, - Result = #{topic => resp_topic(proplists:get_value(<<"topic">>, Params), proplists:get_value(<<"topics">>, Params, <<"">>)), - code => Code}, - loop_publish(ParamsN, [Result | Acc]). - -loop_unsubscribe(Params) -> - loop_unsubscribe(Params, []). -loop_unsubscribe([], Result) -> - lists:reverse(Result); -loop_unsubscribe([Params | ParamsN], Acc) -> - {ClientId, Topic} = parse_unsubscribe_params(Params), - Code = case do_unsubscribe(ClientId, Topic) of - ok -> 0; - {_, Code0, _} -> Code0 - end, - Result = #{clientid => ClientId, - topic => resp_topic(proplists:get_value(<<"topic">>, Params), proplists:get_value(<<"topics">>, Params, <<"">>)), - code => Code}, - loop_unsubscribe(ParamsN, [Result | Acc]). - -do_subscribe(_ClientId, [], _QoS) -> - {ok, ?ERROR15, bad_topic}; -do_subscribe(ClientId, Topics, QoS) -> - TopicTable = parse_topic_filters(Topics, QoS), - case emqx_mgmt:subscribe(ClientId, TopicTable) of - {error, Reason} -> {ok, ?ERROR12, Reason}; - _ -> ok - end. - -do_publish(_ClientId, [], _Qos, _Retain, _Payload) -> - {ok, ?ERROR15, bad_topic}; -do_publish(ClientId, Topics, Qos, Retain, Payload) -> - MsgIds = lists:map(fun(Topic) -> - Msg = emqx_message:make(ClientId, Qos, Topic, Payload), - _ = emqx_mgmt:publish(Msg#message{flags = #{retain => Retain}}), - emqx_guid:to_hexstr(Msg#message.id) - end, Topics), - {ok, MsgIds}. - -do_unsubscribe(ClientId, Topic) -> - case validate_by_filter(Topic) of - true -> - case emqx_mgmt:unsubscribe(ClientId, Topic) of - {error, Reason} -> {ok, ?ERROR12, Reason}; - _ -> ok - end; - false -> - {ok, ?ERROR15, bad_topic} - end. - -parse_subscribe_params(Params) -> - ClientId = proplists:get_value(<<"clientid">>, Params), - Topics = topics(filter, proplists:get_value(<<"topic">>, Params), proplists:get_value(<<"topics">>, Params, <<"">>)), - QoS = proplists:get_value(<<"qos">>, Params, 0), - {ClientId, Topics, QoS}. - -parse_publish_params(Params) -> - Topics = topics(name, proplists:get_value(<<"topic">>, Params), proplists:get_value(<<"topics">>, Params, <<"">>)), - ClientId = proplists:get_value(<<"clientid">>, Params), - Payload = decode_payload(proplists:get_value(<<"payload">>, Params, <<>>), - proplists:get_value(<<"encoding">>, Params, <<"plain">>)), - Qos = proplists:get_value(<<"qos">>, Params, 0), - Retain = proplists:get_value(<<"retain">>, Params, false), - Payload1 = maybe_maps_to_binary(Payload), - {ClientId, Topics, Qos, Retain, Payload1}. - -parse_unsubscribe_params(Params) -> - ClientId = proplists:get_value(<<"clientid">>, Params), - Topic = proplists:get_value(<<"topic">>, Params), - {ClientId, Topic}. - -topics(Type, undefined, Topics0) -> - Topics = binary:split(Topics0, <<",">>, [global]), - case Type of - name -> lists:filter(fun(T) -> validate_by_name(T) end, Topics); - filter -> lists:filter(fun(T) -> validate_by_filter(T) end, Topics) - end; - -topics(Type, Topic, _) -> - topics(Type, undefined, Topic). - -%%TODO: -% validate(qos, Qos) -> -% (Qos >= ?QOS_0) and (Qos =< ?QOS_2). - -validate_by_filter(Topic) -> - validate_topic({filter, Topic}). - -validate_by_name(Topic) -> - validate_topic({name, Topic}). - -validate_topic({Type, Topic}) -> - try emqx_topic:validate({Type, Topic}) of - true -> true - catch - error:_Reason -> false - end. - -parse_topic_filters(Topics, Qos) -> - [begin - {Topic, Opts} = emqx_topic:parse(Topic0), - {Topic, Opts#{qos => Qos}} - end || Topic0 <- Topics]. - -resp_topic(undefined, Topics) -> Topics; -resp_topic(Topic, _) -> Topic. - -decode_payload(Payload, <<"base64">>) -> base64:decode(Payload); -decode_payload(Payload, _) -> Payload. - -maybe_maps_to_binary(Payload) when is_binary(Payload) -> Payload; -maybe_maps_to_binary(Payload) -> - try - emqx_json:encode(Payload) - catch - _C : _E : S -> - error({encode_payload_fail, S}) - end. diff --git a/apps/emqx_management/src/emqx_mgmt_app.erl b/apps/emqx_management/src/emqx_mgmt_app.erl index ff85666b3..8dc1651da 100644 --- a/apps/emqx_management/src/emqx_mgmt_app.erl +++ b/apps/emqx_management/src/emqx_mgmt_app.erl @@ -29,10 +29,8 @@ start(_Type, _Args) -> {ok, Sup} = emqx_mgmt_sup:start_link(), ok = ekka_rlog:wait_for_shards([?MANAGEMENT_SHARD], infinity), - _ = emqx_mgmt_auth:add_default_app(), - emqx_mgmt_http:start_listeners(), emqx_mgmt_cli:load(), {ok, Sup}. stop(_State) -> - emqx_mgmt_http:stop_listeners(). + ok. diff --git a/apps/emqx_management/src/emqx_mgmt_auth.erl b/apps/emqx_management/src/emqx_mgmt_auth.erl deleted file mode 100644 index 7c0eb8e82..000000000 --- a/apps/emqx_management/src/emqx_mgmt_auth.erl +++ /dev/null @@ -1,216 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_auth). - -%% Mnesia Bootstrap --export([mnesia/1]). --boot_mnesia({mnesia, [boot]}). --copy_mnesia({mnesia, [copy]}). - -%% APP Management API --export([ add_default_app/0 - , add_app/2 - , add_app/5 - , add_app/6 - , force_add_app/6 - , lookup_app/1 - , get_appsecret/1 - , update_app/2 - , update_app/5 - , del_app/1 - , list_apps/0 - ]). - -%% APP Auth/Authorization API --export([is_authorized/2]). - --define(APP, emqx_management). - --record(mqtt_app, {id, secret, name, desc, status, expired}). - --type(appid() :: binary()). - --type(appsecret() :: binary()). - --include("emqx_mgmt.hrl"). - -%%-------------------------------------------------------------------- -%% Mnesia Bootstrap -%%-------------------------------------------------------------------- - -mnesia(boot) -> - ok = ekka_mnesia:create_table(mqtt_app, [ - {rlog_shard, ?MANAGEMENT_SHARD}, - {disc_copies, [node()]}, - {record_name, mqtt_app}, - {attributes, record_info(fields, mqtt_app)}]); - -mnesia(copy) -> - ok = ekka_mnesia:copy_table(mqtt_app, disc_copies). - -%%-------------------------------------------------------------------- -%% Manage Apps -%%-------------------------------------------------------------------- --spec(add_default_app() -> list()). -add_default_app() -> - Apps = emqx:get_config([?APP, applications], []), - [ begin - case {AppId, AppSecret} of - {undefined, _} -> ok; - {_, undefined} -> ok; - {_, _} -> - AppId1 = to_binary(AppId), - AppSecret1 = to_binary(AppSecret), - add_app(AppId1, <<"Default">>, AppSecret1, <<"Application user">>, true, undefined) - end - end - || #{id := AppId, secret := AppSecret} <- Apps]. - --spec(add_app(appid(), binary()) -> {ok, appsecret()} | {error, term()}). -add_app(AppId, Name) when is_binary(AppId) -> - add_app(AppId, Name, <<"Application user">>, true, undefined). - --spec(add_app(appid(), binary(), binary(), boolean(), integer() | undefined) - -> {ok, appsecret()} - | {error, term()}). -add_app(AppId, Name, Desc, Status, Expired) when is_binary(AppId) -> - add_app(AppId, Name, undefined, Desc, Status, Expired). - --spec(add_app(appid(), binary(), binary() | undefined, binary(), boolean(), integer() | undefined) - -> {ok, appsecret()} - | {error, term()}). -add_app(AppId, Name, Secret, Desc, Status, Expired) when is_binary(AppId) -> - Secret1 = generate_appsecret_if_need(Secret), - App = #mqtt_app{id = AppId, - secret = Secret1, - name = Name, - desc = Desc, - status = Status, - expired = Expired}, - AddFun = fun() -> - case mnesia:wread({mqtt_app, AppId}) of - [] -> mnesia:write(App); - _ -> mnesia:abort(alread_existed) - end - end, - case ekka_mnesia:transaction(?MANAGEMENT_SHARD, AddFun) of - {atomic, ok} -> {ok, Secret1}; - {aborted, Reason} -> {error, Reason} - end. - -force_add_app(AppId, Name, Secret, Desc, Status, Expired) -> - AddFun = fun() -> - mnesia:write(#mqtt_app{id = AppId, - secret = Secret, - name = Name, - desc = Desc, - status = Status, - expired = Expired}) - end, - case ekka_mnesia:transaction(?MANAGEMENT_SHARD, AddFun) of - {atomic, ok} -> ok; - {aborted, Reason} -> {error, Reason} - end. - --spec(generate_appsecret_if_need(binary() | undefined) -> binary()). -generate_appsecret_if_need(InSecrt) when is_binary(InSecrt), byte_size(InSecrt) > 0 -> - InSecrt; -generate_appsecret_if_need(_) -> - emqx_guid:to_base62(emqx_guid:gen()). - --spec(get_appsecret(appid()) -> {appsecret() | undefined}). -get_appsecret(AppId) when is_binary(AppId) -> - case mnesia:dirty_read(mqtt_app, AppId) of - [#mqtt_app{secret = Secret}] -> Secret; - [] -> undefined - end. - --spec(lookup_app(appid()) -> undefined | {appid(), appsecret(), binary(), binary(), boolean(), integer() | undefined}). -lookup_app(AppId) when is_binary(AppId) -> - case mnesia:dirty_read(mqtt_app, AppId) of - [#mqtt_app{id = AppId, - secret = AppSecret, - name = Name, - desc = Desc, - status = Status, - expired = Expired}] -> {AppId, AppSecret, Name, Desc, Status, Expired}; - [] -> undefined - end. - --spec(update_app(appid(), boolean()) -> ok | {error, term()}). -update_app(AppId, Status) -> - case mnesia:dirty_read(mqtt_app, AppId) of - [App = #mqtt_app{}] -> - Fun = fun() -> mnesia:write(App#mqtt_app{status = Status}) end, - case ekka_mnesia:transaction(?MANAGEMENT_SHARD, Fun) of - {atomic, ok} -> ok; - {aborted, Reason} -> {error, Reason} - end; - [] -> - {error, not_found} - end. - --spec(update_app(appid(), binary(), binary(), boolean(), integer() | undefined) -> ok | {error, term()}). -update_app(AppId, Name, Desc, Status, Expired) -> - case mnesia:dirty_read(mqtt_app, AppId) of - [App = #mqtt_app{}] -> - case ekka_mnesia:transaction( - ?MANAGEMENT_SHARD, - fun() -> mnesia:write(App#mqtt_app{name = Name, - desc = Desc, - status = Status, - expired = Expired}) end) of - {atomic, ok} -> ok; - {aborted, Reason} -> {error, Reason} - end; - [] -> - {error, not_found} - end. - --spec(del_app(appid()) -> ok | {error, term()}). -del_app(AppId) when is_binary(AppId) -> - case ekka_mnesia:transaction(?MANAGEMENT_SHARD, fun mnesia:delete/1, [{mqtt_app, AppId}]) of - {atomic, Ok} -> Ok; - {aborted, Reason} -> {error, Reason} - end. - --spec(list_apps() -> [{appid(), appsecret(), binary(), binary(), boolean(), integer() | undefined}]). -list_apps() -> - [ {AppId, AppSecret, Name, Desc, Status, Expired} || #mqtt_app{id = AppId, - secret = AppSecret, - name = Name, - desc = Desc, - status = Status, - expired = Expired} <- ets:tab2list(mqtt_app) ]. -%%-------------------------------------------------------------------- -%% Authenticate App -%%-------------------------------------------------------------------- - --spec(is_authorized(appid(), appsecret()) -> boolean()). -is_authorized(AppId, AppSecret) -> - case lookup_app(AppId) of - {_, AppSecret1, _, _, Status, Expired} -> - Status andalso is_expired(Expired) andalso AppSecret =:= AppSecret1; - _ -> - false - end. - -is_expired(undefined) -> true; -is_expired(Expired) -> Expired >= erlang:system_time(second). - -to_binary(L) when is_list(L) -> list_to_binary(L); -to_binary(B) when is_binary(B) -> B. diff --git a/apps/emqx_management/src/emqx_mgmt_cli.erl b/apps/emqx_management/src/emqx_mgmt_cli.erl index dcaac5052..3d4dea31e 100644 --- a/apps/emqx_management/src/emqx_mgmt_cli.erl +++ b/apps/emqx_management/src/emqx_mgmt_cli.erl @@ -37,7 +37,6 @@ , mnesia/1 , trace/1 , log/1 - , mgmt/1 , authz/1 ]). @@ -61,55 +60,6 @@ load() -> is_cmd(Fun) -> not lists:member(Fun, [init, load, module_info]). -mgmt(["insert", AppId, Name]) -> - case emqx_mgmt_auth:add_app(list_to_binary(AppId), list_to_binary(Name)) of - {ok, Secret} -> - emqx_ctl:print("AppSecret: ~s~n", [Secret]); - {error, already_existed} -> - emqx_ctl:print("Error: already existed~n"); - {error, Reason} -> - emqx_ctl:print("Error: ~p~n", [Reason]) - end; - -mgmt(["lookup", AppId]) -> - case emqx_mgmt_auth:lookup_app(list_to_binary(AppId)) of - {AppId1, AppSecret, Name, Desc, Status, Expired} -> - emqx_ctl:print("app_id: ~s~nsecret: ~s~nname: ~s~ndesc: ~s~nstatus: ~s~nexpired: ~p~n", - [AppId1, AppSecret, Name, Desc, Status, Expired]); - undefined -> - emqx_ctl:print("Not Found.~n") - end; - -mgmt(["update", AppId, Status]) -> - case emqx_mgmt_auth:update_app(list_to_binary(AppId), list_to_atom(Status)) of - ok -> - emqx_ctl:print("update successfully.~n"); - {error, Reason} -> - emqx_ctl:print("Error: ~p~n", [Reason]) - end; - -mgmt(["delete", AppId]) -> - case emqx_mgmt_auth:del_app(list_to_binary(AppId)) of - ok -> emqx_ctl:print("ok~n"); - {error, not_found} -> - emqx_ctl:print("Error: app not found~n"); - {error, Reason} -> - emqx_ctl:print("Error: ~p~n", [Reason]) - end; - -mgmt(["list"]) -> - lists:foreach(fun({AppId, AppSecret, Name, Desc, Status, Expired}) -> - emqx_ctl:print("app_id: ~s, secret: ~s, name: ~s, desc: ~s, status: ~s, expired: ~p~n", - [AppId, AppSecret, Name, Desc, Status, Expired]) - end, emqx_mgmt_auth:list_apps()); - -mgmt(_) -> - emqx_ctl:usage([{"mgmt list", "List Applications"}, - {"mgmt insert ", "Add Application of REST API"}, - {"mgmt update ", "Update Application of REST API"}, - {"mgmt lookup ", "Get Application of REST API"}, - {"mgmt delete ", "Delete Application of REST API"}]). - %%-------------------------------------------------------------------- %% @doc Node status diff --git a/apps/emqx_management/src/emqx_mgmt_http.erl b/apps/emqx_management/src/emqx_mgmt_http.erl deleted file mode 100644 index da509a36b..000000000 --- a/apps/emqx_management/src/emqx_mgmt_http.erl +++ /dev/null @@ -1,136 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_http). - --export([ start_listeners/0 - , stop_listeners/0 - , start_listener/1 - , stop_listener/1]). - -%% Authorization --export([authorize_appid/1]). - --include_lib("emqx/include/emqx.hrl"). --include_lib("emqx/include/logger.hrl"). - --define(APP, emqx_management). - --define(BASE_PATH, "/api/v5"). - -%%-------------------------------------------------------------------- -%% Start/Stop Listeners -%%-------------------------------------------------------------------- - -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 API", version => "5.0.0"}, - servers => [#{url => ?BASE_PATH}], - tags => [#{ - name => configs, - description => <<"The query string parameter `conf_path` is of jq format.">>, - externalDocs => #{ - description => "Find out more about the path syntax in jq", - url => "https://stedolan.github.io/jq/manual/" - } - }], - components => #{ - schemas => #{}, - securitySchemes => #{ - application => #{ - type => apiKey, - name => "authorization", - in => header}}}}, - Minirest = #{ - protocol => Proto, - base_path => ?BASE_PATH, - modules => api_modules(), - authorization => Authorization, - security => [#{application => []}], - swagger_global_spec => GlobalSpec}, - MinirestOptions = maps:merge(Minirest, RanchOptions), - {ok, _} = minirest:start(listener_name(Proto), MinirestOptions), - ?ULOG("Start ~p listener on ~p successfully.~n", [listener_name(Proto), Port]). - -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 http:management 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_management, listeners], [])]. - -listener_name(Proto) -> - list_to_atom(atom_to_list(Proto) ++ ":management"). - -authorize_appid(Req) -> - case cowboy_req:parse_header(<<"authorization">>, Req) of - {basic, AppId, AppSecret} -> - case emqx_mgmt_auth:is_authorized(AppId, AppSecret) of - true -> ok; - false -> {401, #{<<"WWW-Authenticate">> => <<"Basic Realm=\"minirest-server\"">>}, <<"UNAUTHORIZED">>} - end; - _ -> - {401, #{<<"WWW-Authenticate">> => <<"Basic Realm=\"minirest-server\"">>}, <<"UNAUTHORIZED">>} - 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]). - -apps() -> - Apps = [App || {App, _, _} <- application:loaded_applications(), App =/= emqx_dashboard], - lists:filter(fun(App) -> - case re:run(atom_to_list(App), "^emqx") of - {match,[{0,4}]} -> true; - _ -> false - end - end, Apps). - --ifdef(TEST). -api_modules() -> - minirest_api:find_api_modules(apps()). --else. -api_modules() -> - minirest_api:find_api_modules(apps()) -- [emqx_mgmt_api_apps]. --endif. - diff --git a/apps/emqx_management/test/emqx_mgmt_alarms_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_alarms_api_SUITE.erl index 2929e961d..9293d8fe0 100644 --- a/apps/emqx_management/test/emqx_mgmt_alarms_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_alarms_api_SUITE.erl @@ -25,23 +25,14 @@ -define(DE_ACT_ALARM, test_de_act_alarm). all() -> - [t_alarms_api, t_delete_alarms_api]. + emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_alarms_api(_) -> ok = emqx_alarm:activate(?ACT_ALARM), diff --git a/apps/emqx_management/test/emqx_mgmt_api_test_util.erl b/apps/emqx_management/test/emqx_mgmt_api_test_util.erl index 568ed46a6..0babef05a 100644 --- a/apps/emqx_management/test/emqx_mgmt_api_test_util.erl +++ b/apps/emqx_management/test/emqx_mgmt_api_test_util.erl @@ -17,9 +17,32 @@ -compile(export_all). -compile(nowarn_export_all). --define(SERVER, "http://127.0.0.1:8081"). +-define(SERVER, "http://127.0.0.1:18083"). -define(BASE_PATH, "/api/v5"). +init_suite() -> + ekka_mnesia:start(), + application:load(emqx_management), + emqx_ct_helpers:start_apps([emqx_dashboard], fun set_special_configs/1). + +end_suite() -> + application:unload(emqx_management), + emqx_ct_helpers:stop_apps([emqx_dashboard]). + +set_special_configs(emqx_dashboard) -> + Config = #{ + default_username => <<"admin">>, + default_password => <<"public">>, + listeners => [#{ + protocol => http, + port => 18083 + }] + }, + emqx_config:put([emqx_dashboard], Config), + ok; +set_special_configs(_App) -> + ok. + request_api(Method, Url) -> request_api(Method, Url, [], auth_header_(), []). @@ -55,13 +78,10 @@ do_request_api(Method, Request)-> end. auth_header_() -> - AppId = <<"admin">>, - AppSecret = <<"public">>, - auth_header_(binary_to_list(AppId), binary_to_list(AppSecret)). - -auth_header_(User, Pass) -> - Encoded = base64:encode_to_string(lists:append([User,":",Pass])), - {"Authorization","Basic " ++ Encoded}. + Username = <<"admin">>, + Password = <<"public">>, + {ok, Token} = emqx_dashboard_admin:sign_token(Username, Password), + {"Authorization", "Bearer " ++ binary_to_list(Token)}. api_path(Parts)-> ?SERVER ++ filename:join([?BASE_PATH | Parts]). diff --git a/apps/emqx_management/test/emqx_mgmt_apps_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_apps_api_SUITE.erl deleted file mode 100644 index a139208a5..000000000 --- a/apps/emqx_management/test/emqx_mgmt_apps_api_SUITE.erl +++ /dev/null @@ -1,110 +0,0 @@ -%%-------------------------------------------------------------------- -%% 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_mgmt_apps_api_SUITE). - --compile(export_all). --compile(nowarn_export_all). - --include_lib("eunit/include/eunit.hrl"). - -all() -> - emqx_ct:all(?MODULE). - -init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), - Config. - -end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. - -t_list_app(_) -> - Path = emqx_mgmt_api_test_util:api_path(["apps"]), - {ok, Body} = emqx_mgmt_api_test_util:request_api(get, Path), - Data = emqx_json:decode(Body, [return_maps]), - AdminApp = hd(Data), - Admin = maps:get(<<"app_id">>, AdminApp), - ?assertEqual(<<"admin">>, Admin). - -t_get_app(_) -> - Path = emqx_mgmt_api_test_util:api_path(["apps/admin"]), - {ok, Body} = emqx_mgmt_api_test_util:request_api(get, Path), - AdminApp = emqx_json:decode(Body, [return_maps]), - ?assertEqual(<<"admin">>, maps:get(<<"app_id">>, AdminApp)), - ?assertEqual(<<"public">>, maps:get(<<"secret">>, AdminApp)). - -t_add_app(_) -> - AuthHeader = emqx_mgmt_api_test_util:auth_header_(), - AppId = <<"test_app_id">>, - TestAppPath = emqx_mgmt_api_test_util:api_path(["apps", AppId]), - AppSecret = <<"test_app_secret">>, - - %% new test app - Path = emqx_mgmt_api_test_util:api_path(["apps"]), - RequestBody = #{ - app_id => AppId, - secret => AppSecret, - desc => <<"test desc">>, - name => <<"test_app_name">>, - expired => erlang:system_time(second) + 3000, - status => true - }, - {ok, Body} = emqx_mgmt_api_test_util:request_api(post, Path, "", AuthHeader, RequestBody), - TestAppSecret = emqx_json:decode(Body, [return_maps]), - ?assertEqual(AppSecret, maps:get(<<"secret">>, TestAppSecret)), - - %% get new test app - {ok, GetApp} = emqx_mgmt_api_test_util:request_api(get, TestAppPath), - TestApp = emqx_json:decode(GetApp, [return_maps]), - ?assertEqual(AppId, maps:get(<<"app_id">>, TestApp)), - ?assertEqual(AppSecret, maps:get(<<"secret">>, TestApp)), - - %% update app - Desc2 = <<"test desc 2">>, - Name2 = <<"test_app_name_2">>, - PutBody = #{ - desc => Desc2, - name => Name2, - expired => erlang:system_time(second) + 3000, - status => false - }, - {ok, PutApp} = emqx_mgmt_api_test_util:request_api(put, TestAppPath, "", AuthHeader, PutBody), - TestApp1 = emqx_json:decode(PutApp, [return_maps]), - ?assertEqual(Desc2, maps:get(<<"desc">>, TestApp1)), - ?assertEqual(Name2, maps:get(<<"name">>, TestApp1)), - ?assertEqual(false, maps:get(<<"status">>, TestApp1)), - - %% after update - {ok, GetApp2} = emqx_mgmt_api_test_util:request_api(get, TestAppPath), - TestApp2 = emqx_json:decode(GetApp2, [return_maps]), - ?assertEqual(Desc2, maps:get(<<"desc">>, TestApp2)), - ?assertEqual(Name2, maps:get(<<"name">>, TestApp2)), - ?assertEqual(false, maps:get(<<"status">>, TestApp2)), - - %% delete new app - {ok, _} = emqx_mgmt_api_test_util:request_api(delete, TestAppPath), - - %% after delete - ?assertEqual({error,{"HTTP/1.1",404,"Not Found"}}, - emqx_mgmt_api_test_util:request_api(get, TestAppPath)). diff --git a/apps/emqx_management/test/emqx_mgmt_clients_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_clients_api_SUITE.erl index 9f754b4e1..54b4f92ff 100644 --- a/apps/emqx_management/test/emqx_mgmt_clients_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_clients_api_SUITE.erl @@ -19,26 +19,15 @@ -include_lib("eunit/include/eunit.hrl"). --define(APP, emqx_management). - all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_clients(_) -> process_flag(trap_exit, true), diff --git a/apps/emqx_management/test/emqx_mgmt_listeners_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_listeners_api_SUITE.erl index 93632dda4..10e1def26 100644 --- a/apps/emqx_management/test/emqx_mgmt_listeners_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_listeners_api_SUITE.erl @@ -24,20 +24,11 @@ all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_list_listeners(_) -> Path = emqx_mgmt_api_test_util:api_path(["listeners"]), diff --git a/apps/emqx_management/test/emqx_mgmt_metrics_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_metrics_api_SUITE.erl index b54489e37..5e9464a1e 100644 --- a/apps/emqx_management/test/emqx_mgmt_metrics_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_metrics_api_SUITE.erl @@ -24,20 +24,11 @@ all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_metrics_api(_) -> MetricsPath = emqx_mgmt_api_test_util:api_path(["metrics?aggregate=true"]), diff --git a/apps/emqx_management/test/emqx_mgmt_nodes_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_nodes_api_SUITE.erl index f0829b7fb..f4c17a163 100644 --- a/apps/emqx_management/test/emqx_mgmt_nodes_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_nodes_api_SUITE.erl @@ -24,20 +24,11 @@ all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_nodes_api(_) -> NodesPath = emqx_mgmt_api_test_util:api_path(["nodes"]), diff --git a/apps/emqx_management/test/emqx_mgmt_publish_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_publish_api_SUITE.erl index 2f566e5f4..311a2cc97 100644 --- a/apps/emqx_management/test/emqx_mgmt_publish_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_publish_api_SUITE.erl @@ -26,26 +26,15 @@ -define(TOPIC1, <<"api_topic1">>). -define(TOPIC2, <<"api_topic2">>). - all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. - end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_publish_api(_) -> {ok, Client} = emqtt:start_link(#{username => <<"api_username">>, clientid => <<"api_clientid">>}), diff --git a/apps/emqx_management/test/emqx_mgmt_routes_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_routes_api_SUITE.erl index 1756f6ff5..6963e42cf 100644 --- a/apps/emqx_management/test/emqx_mgmt_routes_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_routes_api_SUITE.erl @@ -24,20 +24,11 @@ all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_nodes_api(_) -> Topic = <<"test_topic">>, @@ -62,4 +53,4 @@ t_nodes_api(_) -> {ok, RouteResponse} = emqx_mgmt_api_test_util:request_api(get, RoutePath), RouteData = emqx_json:decode(RouteResponse, [return_maps]), ?assertEqual(Topic, maps:get(<<"topic">>, RouteData)), - ?assertEqual(atom_to_binary(node(), utf8), maps:get(<<"node">>, RouteData)). \ No newline at end of file + ?assertEqual(atom_to_binary(node(), utf8), maps:get(<<"node">>, RouteData)). diff --git a/apps/emqx_management/test/emqx_mgmt_stats_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_stats_api_SUITE.erl index 395a0851e..11c66daa1 100644 --- a/apps/emqx_management/test/emqx_mgmt_stats_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_stats_api_SUITE.erl @@ -24,20 +24,11 @@ all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_stats_api(_) -> StatsPath = emqx_mgmt_api_test_util:api_path(["stats?aggregate=true"]), diff --git a/apps/emqx_management/test/emqx_mgmt_subscription_api_SUITE.erl b/apps/emqx_management/test/emqx_mgmt_subscription_api_SUITE.erl index 6d56f21c4..f2d8c6eb2 100644 --- a/apps/emqx_management/test/emqx_mgmt_subscription_api_SUITE.erl +++ b/apps/emqx_management/test/emqx_mgmt_subscription_api_SUITE.erl @@ -27,26 +27,15 @@ -define(TOPIC1, <<"0000">>). -define(TOPIC2, <<"0001">>). - all() -> emqx_ct:all(?MODULE). init_per_suite(Config) -> - ekka_mnesia:start(), - emqx_mgmt_auth:mnesia(boot), - emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1), + emqx_mgmt_api_test_util:init_suite(), Config. - end_per_suite(_) -> - emqx_ct_helpers:stop_apps([emqx_management]). - -set_special_configs(emqx_management) -> - emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}], - applications =>[#{id => "admin", secret => "public"}]}), - ok; -set_special_configs(_App) -> - ok. + emqx_mgmt_api_test_util:end_suite(). t_subscription_api(_) -> {ok, Client} = emqtt:start_link(#{username => ?USERNAME, clientid => ?CLIENTID}), diff --git a/deploy/charts/emqx/templates/StatefulSet.yaml b/deploy/charts/emqx/templates/StatefulSet.yaml index ac9a6bcdc..60cc15f58 100644 --- a/deploy/charts/emqx/templates/StatefulSet.yaml +++ b/deploy/charts/emqx/templates/StatefulSet.yaml @@ -94,8 +94,6 @@ spec: containerPort: {{ .Values.emqxConfig.EMQX_LISTENERS__TCP__DEFAULT | default 1883 }} - name: mqttssl containerPort: {{ .Values.emqxConfig.EMQX_LISTENERS__SSL__DEFAULT | default 8883 }} - - name: mgmt - containerPort: {{ .Values.emqxConfig.EMQX_MANAGEMENT__LISTENER__HTTP | default 8081 }} - name: ws containerPort: {{ .Values.emqxConfig.EMQX_LISTENERS__WS__DEFAULT | default 8083 }} - name: wss @@ -140,7 +138,7 @@ spec: readinessProbe: httpGet: path: /api/v5/status - port: {{ .Values.emqxConfig.EMQX_MANAGEMENT__LISTENER__HTTP | default 8081 }} + port: {{ .Values.emqxConfig.EMQX_DASHBOARD__LISTENER__HTTP | default 18083 }} initialDelaySeconds: 5 periodSeconds: 5 {{- with .Values.nodeSelector }} diff --git a/deploy/charts/emqx/templates/service.yaml b/deploy/charts/emqx/templates/service.yaml index 77269d31f..3e9f06b52 100644 --- a/deploy/charts/emqx/templates/service.yaml +++ b/deploy/charts/emqx/templates/service.yaml @@ -55,15 +55,6 @@ spec: {{- else if eq .Values.service.type "ClusterIP" }} nodePort: null {{- end }} - - name: mgmt - port: {{ .Values.service.mgmt | default 8081 }} - protocol: TCP - targetPort: mgmt - {{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.mgmt)) }} - nodePort: {{ .Values.service.nodePorts.mgmt }} - {{- else if eq .Values.service.type "ClusterIP" }} - nodePort: null - {{- end }} - name: ws port: {{ .Values.service.ws | default 8083 }} protocol: TCP @@ -136,10 +127,6 @@ spec: port: {{ .Values.service.mqttssl | default 8883 }} protocol: TCP targetPort: mqttssl - - name: mgmt - port: {{ .Values.service.mgmt | default 8081 }} - protocol: TCP - targetPort: mgmt - name: ws port: {{ .Values.service.ws | default 8083 }} protocol: TCP