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(),
|
||||
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) ->
|
||||
emqx_dashboard_api_test_helpers:set_default_config(),
|
||||
ok;
|
||||
|
|
|
@ -62,9 +62,8 @@ fields("dashboard") ->
|
|||
#{
|
||||
desc => ?DESC(bootstrap_users_file),
|
||||
required => false,
|
||||
importance => ?IMPORTANCE_HIDDEN,
|
||||
default => <<>>
|
||||
%% deprecated => {since, "5.1.0"}
|
||||
default => <<>>,
|
||||
deprecated => {since, "5.1.0"}
|
||||
}
|
||||
)}
|
||||
];
|
||||
|
|
|
@ -31,10 +31,12 @@ start(_Type, _Args) ->
|
|||
ok = mria_rlog:wait_for_shards([?MANAGEMENT_SHARD], infinity),
|
||||
case emqx_mgmt_auth:init_bootstrap_file() of
|
||||
ok ->
|
||||
emqx_conf:add_handler([api_key], emqx_mgmt_auth),
|
||||
emqx_mgmt_sup:start_link();
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
stop(_State) ->
|
||||
emqx_conf:remove_handler([api_key]),
|
||||
ok.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
%% API
|
||||
-export([mnesia/1]).
|
||||
-boot_mnesia({mnesia, [boot]}).
|
||||
-behaviour(emqx_config_handler).
|
||||
|
||||
-export([
|
||||
create/4,
|
||||
|
@ -31,6 +32,7 @@
|
|||
]).
|
||||
|
||||
-export([authorize/3]).
|
||||
-export([post_config_update/5]).
|
||||
|
||||
%% Internal exports (RPC)
|
||||
-export([
|
||||
|
@ -65,6 +67,17 @@ mnesia(boot) ->
|
|||
{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, _}.
|
||||
init_bootstrap_file() ->
|
||||
File = bootstrap_file(),
|
||||
|
@ -230,13 +243,7 @@ generate_api_secret() ->
|
|||
emqx_base62:encode(Random).
|
||||
|
||||
bootstrap_file() ->
|
||||
case emqx:get_config([api_key, bootstrap_file], <<>>) of
|
||||
%% For compatible remove until 5.1.0
|
||||
<<>> ->
|
||||
emqx:get_config([dashboard, bootstrap_users_file], <<>>);
|
||||
File ->
|
||||
File
|
||||
end.
|
||||
emqx:get_config([api_key, bootstrap_file], <<>>).
|
||||
|
||||
init_bootstrap_file(<<>>) ->
|
||||
ok;
|
||||
|
|
|
@ -29,19 +29,18 @@ groups() ->
|
|||
].
|
||||
|
||||
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.
|
||||
|
||||
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(_) ->
|
||||
TestPath = <<"/api/v5/status">>,
|
||||
Bin = <<"test-1:secret-1\ntest-2:secret-2">>,
|
||||
File = "./bootstrap_api_keys.txt",
|
||||
ok = file:write_file(File, Bin),
|
||||
emqx:update_config([api_key, bootstrap_file], File),
|
||||
ok = emqx_mgmt_auth:init_bootstrap_file(),
|
||||
update_file(File),
|
||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
|
||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-2">>)),
|
||||
?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.
|
||||
Bin1 = <<"test-1:new-secret-1\ntest-2:new-secret-2">>,
|
||||
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-2">>, <<"secret-2">>)),
|
||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
|
||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"new-secret-2">>)),
|
||||
|
||||
%% Compatibility
|
||||
Bin2 = <<"test-3:new-secret-3\ntest-4:new-secret-4">>,
|
||||
ok = file:write_file(File, Bin2),
|
||||
emqx:update_config([api_key, bootstrap_file], <<>>),
|
||||
emqx:update_config([dashboard, bootstrap_users_file], File),
|
||||
ok = emqx_mgmt_auth:init_bootstrap_file(),
|
||||
?assertMatch(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"new-secret-1">>)),
|
||||
?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()),
|
||||
%% not error when bootstrap_file is empty
|
||||
update_file(<<>>),
|
||||
update_file("./bootstrap_apps_not_exist.txt"),
|
||||
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-1">>)),
|
||||
?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-2">>, <<"new-secret-2">>)),
|
||||
|
||||
%% bad format
|
||||
BadBin = <<"test-1:secret-11\ntest-2 secret-12">>,
|
||||
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()),
|
||||
?assertEqual(ok, emqx_mgmt_auth:authorize(TestPath, <<"test-1">>, <<"secret-11">>)),
|
||||
?assertMatch({error, _}, emqx_mgmt_auth:authorize(TestPath, <<"test-2">>, <<"secret-12">>)),
|
||||
emqx:update_config([api_key, bootstrap_file], <<>>),
|
||||
emqx:update_config([dashboard, bootstrap_users_file], <<>>),
|
||||
update_file(<<>>),
|
||||
ok.
|
||||
|
||||
update_file(File) ->
|
||||
?assertMatch({ok, _}, emqx:update_config([<<"api_key">>], #{<<"bootstrap_file">> => File})).
|
||||
|
||||
t_create(_Config) ->
|
||||
Name = <<"EMQX-API-KEY-1">>,
|
||||
{ok, Create} = create_app(Name),
|
||||
|
|
|
@ -24,20 +24,11 @@ all() ->
|
|||
emqx_common_test_helpers:all(?MODULE).
|
||||
|
||||
init_per_suite(Config) ->
|
||||
mria:start(),
|
||||
ok = emqx_common_test_helpers:start_apps([emqx_management]),
|
||||
emqx_common_test_helpers:start_apps([] ++ [emqx_dashboard], fun set_special_configs/1),
|
||||
emqx_mgmt_api_test_util:init_suite([emqx_conf, emqx_management]),
|
||||
Config.
|
||||
|
||||
end_per_suite(_) ->
|
||||
emqx_common_test_helpers:stop_apps([emqx_management] ++ [emqx_dashboard]),
|
||||
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.
|
||||
emqx_mgmt_api_test_util:end_suite([emqx_management, emqx_conf]).
|
||||
|
||||
t_status(_Config) ->
|
||||
emqx_ctl:run_command([]),
|
||||
|
|
Loading…
Reference in New Issue