feat: authz support merge sources

This commit is contained in:
zhongwencool 2023-06-09 11:16:40 +08:00
parent 994db58cbf
commit aac5b85d26
2 changed files with 87 additions and 5 deletions

View File

@ -37,6 +37,7 @@
-define(CMD_PREPEND, prepend). -define(CMD_PREPEND, prepend).
-define(CMD_APPEND, append). -define(CMD_APPEND, append).
-define(CMD_MOVE, move). -define(CMD_MOVE, move).
-define(CMD_MERGE, merge).
-define(CMD_MOVE_FRONT, front). -define(CMD_MOVE_FRONT, front).
-define(CMD_MOVE_REAR, rear). -define(CMD_MOVE_REAR, rear).

View File

@ -24,11 +24,6 @@
-include_lib("emqx/include/emqx_hooks.hrl"). -include_lib("emqx/include/emqx_hooks.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl"). -include_lib("snabbkaffe/include/snabbkaffe.hrl").
-ifdef(TEST).
-compile(export_all).
-compile(nowarn_export_all).
-endif.
-export([ -export([
register_metrics/0, register_metrics/0,
init/0, init/0,
@ -37,6 +32,7 @@
lookup/1, lookup/1,
move/2, move/2,
update/2, update/2,
merge/1,
authorize/5, authorize/5,
%% for telemetry information %% for telemetry information
get_enabled_authzs/0 get_enabled_authzs/0
@ -45,6 +41,7 @@
-export([post_config_update/5, pre_config_update/3]). -export([post_config_update/5, pre_config_update/3]).
-export([acl_conf_file/0]). -export([acl_conf_file/0]).
-export([merge_sources/2, search/2]).
%% Data backup %% Data backup
-export([ -export([
@ -128,6 +125,9 @@ lookup(Type) ->
{Source, _Front, _Rear} = take(Type), {Source, _Front, _Rear} = take(Type),
Source. Source.
merge(NewConf) ->
emqx_authz_utils:update_config(?ROOT_KEY, {?CMD_MERGE, NewConf}).
move(Type, ?CMD_MOVE_BEFORE(Before)) -> move(Type, ?CMD_MOVE_BEFORE(Before)) ->
emqx_authz_utils:update_config( emqx_authz_utils:update_config(
?CONF_KEY_PATH, {?CMD_MOVE, type(Type), ?CMD_MOVE_BEFORE(type(Before))} ?CONF_KEY_PATH, {?CMD_MOVE, type(Type), ?CMD_MOVE_BEFORE(type(Before))}
@ -158,9 +158,16 @@ pre_config_update(Path, Cmd, Sources) ->
do_pre_config_update(?CONF_KEY_PATH, Cmd, Sources) -> do_pre_config_update(?CONF_KEY_PATH, Cmd, Sources) ->
do_pre_config_update(Cmd, Sources); do_pre_config_update(Cmd, Sources);
do_pre_config_update(?ROOT_KEY, {?CMD_MERGE, NewConf}, OldConf) ->
do_pre_config_merge(NewConf, OldConf);
do_pre_config_update(?ROOT_KEY, NewConf, OldConf) -> do_pre_config_update(?ROOT_KEY, NewConf, OldConf) ->
do_pre_config_replace(NewConf, OldConf). do_pre_config_replace(NewConf, OldConf).
do_pre_config_merge(NewConf, OldConf) ->
MergeConf0 = emqx_utils_maps:deep_merge(OldConf, NewConf),
NewSources = merge_sources(NewConf, OldConf),
do_pre_config_replace(MergeConf0#{<<"sources">> := NewSources}, OldConf).
%% override the entire config when updating the root key %% override the entire config when updating the root key
%% emqx_conf:update(?ROOT_KEY, Conf); %% emqx_conf:update(?ROOT_KEY, Conf);
do_pre_config_replace(Conf, Conf) -> do_pre_config_replace(Conf, Conf) ->
@ -629,3 +636,77 @@ check_acl_file_rules(Path, Rules) ->
after after
_ = file:delete(TmpPath) _ = file:delete(TmpPath)
end. end.
merge_sources(OldConf, NewConf) ->
Default = [emqx_authz_schema:default_authz()],
NewSources0 = maps:get(<<"sources">>, NewConf, Default),
OriginSources0 = maps:get(<<"sources">>, OldConf, Default),
{OriginSource, NewSources} =
lists:foldl(
fun(Old = #{<<"type">> := Type}, {OriginAcc, NewAcc}) ->
case search(Type, NewAcc) of
not_found ->
{[Old | OriginAcc], NewAcc};
{New, NewAcc1} ->
MergeSource = emqx_utils_maps:deep_merge(Old, New),
{[MergeSource | OriginAcc], NewAcc1}
end
end,
{[], NewSources0},
OriginSources0
),
lists:reverse(OriginSource) ++ NewSources.
search(Type, Sources) ->
case lists:splitwith(fun(T) -> type(T) =/= type(Type) end, Sources) of
{_Front, []} -> not_found;
{Front, [Target | Rear]} -> {Target, Front ++ Rear}
end.
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-compile(nowarn_export_all).
-compile(export_all).
merge_sources_test() ->
Default = [emqx_authz_schema:default_authz()],
Http = #{<<"type">> => <<"http">>, <<"enable">> => true},
Mysql = #{<<"type">> => <<"mysql">>, <<"enable">> => true},
Mongo = #{<<"type">> => <<"mongodb">>, <<"enable">> => true},
Redis = #{<<"type">> => <<"redis">>, <<"enable">> => true},
HttpDisable = Http#{<<"enable">> => false},
MysqlDisable = Mysql#{<<"enable">> => false},
MongoDisable = Mongo#{<<"enable">> => false},
%% has default source
?assertEqual(Default, merge_sources(#{}, #{})),
?assertEqual([], merge_sources(#{<<"sources">> => []}, #{<<"sources">> => []})),
?assertEqual(Default, merge_sources(#{}, #{<<"sources">> => []})),
%% add
?assertEqual(
[Http, Mysql, Mongo, Redis],
merge_sources(
#{<<"sources">> => [Http, Mysql]},
#{<<"sources">> => [Mongo, Redis]}
)
),
%% replace
?assertEqual(
[HttpDisable, MysqlDisable],
merge_sources(
#{<<"sources">> => [Http, Mysql]},
#{<<"sources">> => [HttpDisable, MysqlDisable]}
)
),
%% add + replace + change position
?assertEqual(
[HttpDisable, Mysql, MongoDisable, Redis],
merge_sources(
#{<<"sources">> => [Http, Mysql, Mongo]},
#{<<"sources">> => [MongoDisable, HttpDisable, Redis]}
)
),
ok.
-endif.