fix: start auth & acl mongo with availability check
This commit is contained in:
parent
16dc0d6555
commit
3c34cb3b6a
|
@ -1,6 +1,6 @@
|
|||
{application, emqx_auth_mongo,
|
||||
[{description, "EMQ X Authentication/ACL with MongoDB"},
|
||||
{vsn, "4.3.2"}, % strict semver, bump manually!
|
||||
{vsn, "4.3.3"}, % strict semver, bump manually!
|
||||
{modules, []},
|
||||
{registered, [emqx_auth_mongo_sup]},
|
||||
{applications, [kernel,stdlib,mongodb,ecpool]},
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
%% -*- mode: erlang -*-
|
||||
%% Unless you know what you are doing, DO NOT edit manually!!
|
||||
{VSN,
|
||||
[{"4.3.1",
|
||||
[{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
|
||||
[{"4.3.2",
|
||||
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
|
||||
{"4.3.1",
|
||||
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
|
||||
{"4.3.0",
|
||||
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]}]},
|
||||
{<<".*">>,[]}],
|
||||
[{"4.3.1",
|
||||
[{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
|
||||
[{"4.3.2",
|
||||
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
|
||||
{"4.3.1",
|
||||
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]}]},
|
||||
{"4.3.0",
|
||||
[{load_module,emqx_auth_mongo_app,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_auth_mongo,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_acl_mongo,brutal_purge,soft_purge,[]}]},
|
||||
{<<".*">>,[]}]
|
||||
}.
|
||||
{<<".*">>,[]}]}.
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
, query_multi/3
|
||||
]).
|
||||
|
||||
-export([ available/2
|
||||
, available/3
|
||||
]).
|
||||
|
||||
-spec(register_metrics() -> ok).
|
||||
register_metrics() ->
|
||||
lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
|
||||
|
@ -97,6 +101,56 @@ is_superuser(Pool, #superquery{collection = Coll, field = Field, selector = Sele
|
|||
end
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Availability Test
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
available(Pool, #superquery{collection = Collection, selector = Selector}) ->
|
||||
available(Pool, Collection, maps:from_list(replvars(Selector, test_client_info())));
|
||||
available(Pool, #authquery{collection = Collection, selector = Selector}) ->
|
||||
available(Pool, Collection, maps:from_list(replvars(Selector, test_client_info())));
|
||||
available(Pool, #aclquery{collection = Collection, selector = Selectors}) ->
|
||||
Fun =
|
||||
fun(Selector) ->
|
||||
maps:from_list(emqx_auth_mongo:replvars(Selector, test_client_info()))
|
||||
end,
|
||||
available(Pool, Collection, lists:map(Fun, Selectors), fun query_multi/3).
|
||||
|
||||
available(Pool, Collection, Query) ->
|
||||
available(Pool, Collection, Query, fun query/3).
|
||||
|
||||
available(Pool, Collection, Query, Fun) ->
|
||||
try Fun(Pool, Collection, Query) of
|
||||
{error, Reason} ->
|
||||
?LOG(error, "[MongoDB] ~p availability test error: ~0p", [Collection, Reason]),
|
||||
{error, Reason};
|
||||
Error = #{<<"code">> := Code} ->
|
||||
CodeName = maps:get(<<"codeName">>, Error, undefined),
|
||||
ErrorMessage = maps:get(<<"errmsg">>, Error, undefined),
|
||||
?LOG(error, "[MongoDB] ~p availability test error, code: ~p Name: ~0p Message: ~0p",
|
||||
[Collection, Code, CodeName, ErrorMessage]),
|
||||
{error, {mongo_error, Code}};
|
||||
_Return ->
|
||||
%% Any success result is fine.
|
||||
ok
|
||||
catch E:R:S ->
|
||||
?LOG(error, "[MongoDB] ~p availability test error, ~p: ~0p: ~0p", [Collection, E, R, S]),
|
||||
{error, R}
|
||||
end.
|
||||
|
||||
%% Test client info
|
||||
test_client_info() ->
|
||||
#{
|
||||
clientid => <<"EMQX_availability_test_client">>,
|
||||
username => <<"EMQX_availability_test_username">>,
|
||||
cn => <<"EMQX_availability_test_cn">>,
|
||||
dn => <<"EMQX_availability_test_dn">>
|
||||
}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal func
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
replvars(VarList, ClientInfo) ->
|
||||
lists:map(fun(Var) -> replvar(Var, ClientInfo) end, VarList).
|
||||
|
||||
|
|
|
@ -36,26 +36,65 @@
|
|||
|
||||
start(_StartType, _StartArgs) ->
|
||||
{ok, Sup} = emqx_auth_mongo_sup:start_link(),
|
||||
with_env(auth_query, fun reg_authmod/1),
|
||||
with_env(acl_query, fun reg_aclmod/1),
|
||||
ok = safe_start(),
|
||||
{ok, Sup}.
|
||||
|
||||
prep_stop(State) ->
|
||||
ok = emqx:unhook('client.authenticate', fun emqx_auth_mongo:check/3),
|
||||
ok = emqx:unhook('client.check_acl', fun emqx_acl_mongo:check_acl/5),
|
||||
ok = unload_hook(),
|
||||
_ = stop_pool(),
|
||||
State.
|
||||
|
||||
stop(_State) ->
|
||||
ok.
|
||||
|
||||
unload_hook() ->
|
||||
ok = emqx:unhook('client.authenticate', fun emqx_auth_mongo:check/3),
|
||||
ok = emqx:unhook('client.check_acl', fun emqx_acl_mongo:check_acl/5).
|
||||
|
||||
stop_pool() ->
|
||||
ecpool:stop_sup_pool(?APP).
|
||||
|
||||
safe_start() ->
|
||||
try
|
||||
ok = with_env(auth_query, fun reg_authmod/1),
|
||||
ok = with_env(acl_query, fun reg_aclmod/1),
|
||||
ok
|
||||
catch _E:R:_S ->
|
||||
unload_hook(),
|
||||
_ = stop_pool(),
|
||||
{error, R}
|
||||
end.
|
||||
|
||||
reg_authmod(AuthQuery) ->
|
||||
emqx_auth_mongo:register_metrics(),
|
||||
SuperQuery = r(super_query, application:get_env(?APP, super_query, undefined)),
|
||||
ok = emqx:hook('client.authenticate', fun emqx_auth_mongo:check/3,
|
||||
[#{authquery => AuthQuery, superquery => SuperQuery, pool => ?APP}]).
|
||||
case emqx_auth_mongo:available(?APP, AuthQuery) of
|
||||
ok ->
|
||||
emqx_auth_mongo:register_metrics(),
|
||||
HookFun = fun emqx_auth_mongo:check/3,
|
||||
HookOptions = #{authquery => AuthQuery, superquery => undefined, pool => ?APP},
|
||||
case r(super_query, application:get_env(?APP, super_query, undefined)) of
|
||||
undefined ->
|
||||
ok = emqx:hook('client.authenticate', HookFun, [HookOptions]);
|
||||
SuperQuery ->
|
||||
case emqx_auth_mongo:available(?APP, SuperQuery) of
|
||||
ok ->
|
||||
ok = emqx:hook('client.authenticate', HookFun,
|
||||
[HookOptions#{superquery => SuperQuery}]);
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end
|
||||
end;
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
reg_aclmod(AclQuery) ->
|
||||
ok = emqx:hook('client.check_acl', fun emqx_acl_mongo:check_acl/5, [#{aclquery => AclQuery, pool => ?APP}]).
|
||||
case emqx_auth_mongo:available(?APP, AclQuery) of
|
||||
ok ->
|
||||
ok = emqx:hook('client.check_acl', fun emqx_acl_mongo:check_acl/5,
|
||||
[#{aclquery => AclQuery, pool => ?APP}]);
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal functions
|
||||
|
|
Loading…
Reference in New Issue