Merge pull request #10896 from zhongwencool/api-keys-hot-conf-update
feat: api_key conf support hot conf
This commit is contained in:
commit
8d8efe449e
|
@ -115,14 +115,6 @@ end_per_testcase(_TestCase, _Config) ->
|
||||||
delete_all_bridges(),
|
delete_all_bridges(),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
set_special_configs(emqx_management) ->
|
|
||||||
Listeners = #{http => #{port => 8081}},
|
|
||||||
Config = #{
|
|
||||||
listeners => Listeners,
|
|
||||||
applications => [#{id => "admin", secret => "public"}]
|
|
||||||
},
|
|
||||||
emqx_config:put([emqx_management], Config),
|
|
||||||
ok;
|
|
||||||
set_special_configs(emqx_dashboard) ->
|
set_special_configs(emqx_dashboard) ->
|
||||||
emqx_dashboard_api_test_helpers:set_default_config(),
|
emqx_dashboard_api_test_helpers:set_default_config(),
|
||||||
ok;
|
ok;
|
||||||
|
|
|
@ -62,9 +62,8 @@ fields("dashboard") ->
|
||||||
#{
|
#{
|
||||||
desc => ?DESC(bootstrap_users_file),
|
desc => ?DESC(bootstrap_users_file),
|
||||||
required => false,
|
required => false,
|
||||||
importance => ?IMPORTANCE_HIDDEN,
|
default => <<>>,
|
||||||
default => <<>>
|
deprecated => {since, "5.1.0"}
|
||||||
%% deprecated => {since, "5.1.0"}
|
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
];
|
];
|
||||||
|
|
|
@ -31,10 +31,12 @@ start(_Type, _Args) ->
|
||||||
ok = mria_rlog:wait_for_shards([?MANAGEMENT_SHARD], infinity),
|
ok = mria_rlog:wait_for_shards([?MANAGEMENT_SHARD], infinity),
|
||||||
case emqx_mgmt_auth:init_bootstrap_file() of
|
case emqx_mgmt_auth:init_bootstrap_file() of
|
||||||
ok ->
|
ok ->
|
||||||
|
emqx_conf:add_handler([api_key], emqx_mgmt_auth),
|
||||||
emqx_mgmt_sup:start_link();
|
emqx_mgmt_sup:start_link();
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, Reason}
|
{error, Reason}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
stop(_State) ->
|
stop(_State) ->
|
||||||
|
emqx_conf:remove_handler([api_key]),
|
||||||
ok.
|
ok.
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
%% API
|
%% API
|
||||||
-export([mnesia/1]).
|
-export([mnesia/1]).
|
||||||
-boot_mnesia({mnesia, [boot]}).
|
-boot_mnesia({mnesia, [boot]}).
|
||||||
|
-behaviour(emqx_config_handler).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
create/4,
|
create/4,
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([authorize/3]).
|
-export([authorize/3]).
|
||||||
|
-export([post_config_update/5]).
|
||||||
|
|
||||||
%% Internal exports (RPC)
|
%% Internal exports (RPC)
|
||||||
-export([
|
-export([
|
||||||
|
@ -65,6 +67,17 @@ mnesia(boot) ->
|
||||||
{attributes, record_info(fields, ?APP)}
|
{attributes, record_info(fields, ?APP)}
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
post_config_update([api_key], _Req, NewConf, _OldConf, _AppEnvs) ->
|
||||||
|
#{bootstrap_file := File} = NewConf,
|
||||||
|
case init_bootstrap_file(File) of
|
||||||
|
ok ->
|
||||||
|
?SLOG(debug, #{msg => "init_bootstrap_api_keys_from_file_ok", file => File});
|
||||||
|
{error, Reason} ->
|
||||||
|
Msg = "init_bootstrap_api_keys_from_file_failed",
|
||||||
|
?SLOG(error, #{msg => Msg, reason => Reason, file => File})
|
||||||
|
end,
|
||||||
|
ok.
|
||||||
|
|
||||||
-spec init_bootstrap_file() -> ok | {error, _}.
|
-spec init_bootstrap_file() -> ok | {error, _}.
|
||||||
init_bootstrap_file() ->
|
init_bootstrap_file() ->
|
||||||
File = bootstrap_file(),
|
File = bootstrap_file(),
|
||||||
|
@ -230,13 +243,7 @@ generate_api_secret() ->
|
||||||
emqx_base62:encode(Random).
|
emqx_base62:encode(Random).
|
||||||
|
|
||||||
bootstrap_file() ->
|
bootstrap_file() ->
|
||||||
case emqx:get_config([api_key, bootstrap_file], <<>>) of
|
emqx:get_config([api_key, bootstrap_file], <<>>).
|
||||||
%% For compatible remove until 5.1.0
|
|
||||||
<<>> ->
|
|
||||||
emqx:get_config([dashboard, bootstrap_users_file], <<>>);
|
|
||||||
File ->
|
|
||||||
File
|
|
||||||
end.
|
|
||||||
|
|
||||||
init_bootstrap_file(<<>>) ->
|
init_bootstrap_file(<<>>) ->
|
||||||
ok;
|
ok;
|
||||||
|
|
|
@ -29,19 +29,18 @@ groups() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
init_per_suite(Config) ->
|
||||||
emqx_mgmt_api_test_util:init_suite([emqx_conf]),
|
emqx_mgmt_api_test_util:init_suite([emqx_conf, emqx_management]),
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
end_per_suite(_) ->
|
end_per_suite(_) ->
|
||||||
emqx_mgmt_api_test_util:end_suite([emqx_conf]).
|
emqx_mgmt_api_test_util:end_suite([emqx_conf, emqx_management]).
|
||||||
|
|
||||||
t_bootstrap_file(_) ->
|
t_bootstrap_file(_) ->
|
||||||
TestPath = <<"/api/v5/status">>,
|
TestPath = <<"/api/v5/status">>,
|
||||||
Bin = <<"test-1:secret-1\ntest-2:secret-2">>,
|
Bin = <<"test-1:secret-1\ntest-2:secret-2">>,
|
||||||
File = "./bootstrap_api_keys.txt",
|
File = "./bootstrap_api_keys.txt",
|
||||||
ok = file:write_file(File, Bin),
|
ok = file:write_file(File, Bin),
|
||||||
emqx:update_config([api_key, bootstrap_file], File),
|
update_file(File),
|
||||||
ok = emqx_mgmt_auth:init_bootstrap_file(),
|
|
||||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
|
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
|
||||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
|
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
|
||||||
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-1">>)),
|
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-1">>)),
|
||||||
|
@ -49,39 +48,33 @@ t_bootstrap_file(_) ->
|
||||||
%% relaunch to check if the table is changed.
|
%% relaunch to check if the table is changed.
|
||||||
Bin1 = <<"test-1:new-secret-1\ntest-2:new-secret-2">>,
|
Bin1 = <<"test-1:new-secret-1\ntest-2:new-secret-2">>,
|
||||||
ok = file:write_file(File, Bin1),
|
ok = file:write_file(File, Bin1),
|
||||||
ok = emqx_mgmt_auth:init_bootstrap_file(),
|
update_file(File),
|
||||||
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
|
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
|
||||||
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
|
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
|
||||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
|
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
|
||||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"new-secret-2">>)),
|
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"new-secret-2">>)),
|
||||||
|
|
||||||
%% Compatibility
|
%% not error when bootstrap_file is empty
|
||||||
Bin2 = <<"test-3:new-secret-3\ntest-4:new-secret-4">>,
|
update_file(<<>>),
|
||||||
ok = file:write_file(File, Bin2),
|
update_file("./bootstrap_apps_not_exist.txt"),
|
||||||
emqx:update_config([api_key, bootstrap_file], <<>>),
|
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
|
||||||
emqx:update_config([dashboard, bootstrap_users_file], File),
|
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
|
||||||
ok = emqx_mgmt_auth:init_bootstrap_file(),
|
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
|
||||||
?assertMatch(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
|
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"new-secret-2">>)),
|
||||||
?assertMatch(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"new-secret-2">>)),
|
|
||||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-3">>, <<"new-secret-3">>)),
|
|
||||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-4">>, <<"new-secret-4">>)),
|
|
||||||
|
|
||||||
%% not found
|
|
||||||
NotFoundFile = "./bootstrap_apps_not_exist.txt",
|
|
||||||
emqx:update_config([api_key, bootstrap_file], NotFoundFile),
|
|
||||||
?assertMatch({error, "No such file or directory"}, emqx_mgmt_auth:init_bootstrap_file()),
|
|
||||||
|
|
||||||
%% bad format
|
%% bad format
|
||||||
BadBin = <<"test-1:secret-11\ntest-2 secret-12">>,
|
BadBin = <<"test-1:secret-11\ntest-2 secret-12">>,
|
||||||
ok = file:write_file(File, BadBin),
|
ok = file:write_file(File, BadBin),
|
||||||
emqx:update_config([api_key, bootstrap_file], File),
|
update_file(File),
|
||||||
?assertMatch({error, #{reason := "invalid_format"}}, emqx_mgmt_auth:init_bootstrap_file()),
|
?assertMatch({error, #{reason := "invalid_format"}}, emqx_mgmt_auth:init_bootstrap_file()),
|
||||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-11">>)),
|
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-11">>)),
|
||||||
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-12">>)),
|
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-12">>)),
|
||||||
emqx:update_config([api_key, bootstrap_file], <<>>),
|
update_file(<<>>),
|
||||||
emqx:update_config([dashboard, bootstrap_users_file], <<>>),
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
update_file(File) ->
|
||||||
|
?assertMatch({ok, _}, emqx:update_config([<<"api_key">>], #{<<"bootstrap_file">> => File})).
|
||||||
|
|
||||||
t_create(_Config) ->
|
t_create(_Config) ->
|
||||||
Name = <<"EMQX-API-KEY-1">>,
|
Name = <<"EMQX-API-KEY-1">>,
|
||||||
{ok, Create} = create_app(Name),
|
{ok, Create} = create_app(Name),
|
||||||
|
|
|
@ -24,20 +24,11 @@ all() ->
|
||||||
emqx_common_test_helpers:all(?MODULE).
|
emqx_common_test_helpers:all(?MODULE).
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
init_per_suite(Config) ->
|
||||||
mria:start(),
|
emqx_mgmt_api_test_util:init_suite([emqx_conf, emqx_management]),
|
||||||
ok = emqx_common_test_helpers:start_apps([emqx_management]),
|
|
||||||
emqx_common_test_helpers:start_apps([] ++ [emqx_dashboard], fun set_special_configs/1),
|
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
end_per_suite(_) ->
|
end_per_suite(_) ->
|
||||||
emqx_common_test_helpers:stop_apps([emqx_management] ++ [emqx_dashboard]),
|
emqx_mgmt_api_test_util:end_suite([emqx_management, emqx_conf]).
|
||||||
emqx_config:delete_override_conf_files(),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
set_special_configs(emqx_dashboard) ->
|
|
||||||
emqx_dashboard_api_test_helpers:set_default_config();
|
|
||||||
set_special_configs(_App) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
t_status(_Config) ->
|
t_status(_Config) ->
|
||||||
emqx_ctl:run_command([]),
|
emqx_ctl:run_command([]),
|
||||||
|
|
Loading…
Reference in New Issue