fix(authz_http): handle `ignore` results (request failures)
Related issue: https://github.com/emqx/emqx/issues/9683 When the HTTP request for authz fails (e.g.: resource is down or server is down), then the HTTP authorizer returns `ignore`, which was not handled correctly by the authorization callback.
This commit is contained in:
parent
32922a6830
commit
c6b8e614df
|
@ -1,7 +1,7 @@
|
||||||
%% -*- mode: erlang -*-
|
%% -*- mode: erlang -*-
|
||||||
{application, emqx_authz, [
|
{application, emqx_authz, [
|
||||||
{description, "An OTP application"},
|
{description, "An OTP application"},
|
||||||
{vsn, "0.1.10"},
|
{vsn, "0.1.11"},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{mod, {emqx_authz_app, []}},
|
{mod, {emqx_authz_app, []}},
|
||||||
{applications, [
|
{applications, [
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
-include("emqx_authz.hrl").
|
-include("emqx_authz.hrl").
|
||||||
-include_lib("emqx/include/logger.hrl").
|
-include_lib("emqx/include/logger.hrl").
|
||||||
-include_lib("emqx/include/emqx_hooks.hrl").
|
-include_lib("emqx/include/emqx_hooks.hrl").
|
||||||
|
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
-compile(export_all).
|
-compile(export_all).
|
||||||
|
@ -358,6 +359,7 @@ authorize_non_superuser(
|
||||||
emqx_metrics:inc(?METRIC_DENY),
|
emqx_metrics:inc(?METRIC_DENY),
|
||||||
{stop, #{result => deny, from => AuthzSource}};
|
{stop, #{result => deny, from => AuthzSource}};
|
||||||
nomatch ->
|
nomatch ->
|
||||||
|
?tp(authz_non_superuser, #{result => nomatch}),
|
||||||
?SLOG(info, #{
|
?SLOG(info, #{
|
||||||
msg => "authorization_failed_nomatch",
|
msg => "authorization_failed_nomatch",
|
||||||
username => Username,
|
username => Username,
|
||||||
|
@ -388,6 +390,12 @@ do_authorize(
|
||||||
nomatch ->
|
nomatch ->
|
||||||
emqx_metrics_worker:inc(authz_metrics, Type, nomatch),
|
emqx_metrics_worker:inc(authz_metrics, Type, nomatch),
|
||||||
do_authorize(Client, PubSub, Topic, Tail);
|
do_authorize(Client, PubSub, Topic, Tail);
|
||||||
|
%% {matched, allow | deny | ignore}
|
||||||
|
{matched, ignore} ->
|
||||||
|
do_authorize(Client, PubSub, Topic, Tail);
|
||||||
|
ignore ->
|
||||||
|
do_authorize(Client, PubSub, Topic, Tail);
|
||||||
|
%% {matched, allow | deny}
|
||||||
Matched ->
|
Matched ->
|
||||||
{Matched, Type}
|
{Matched, Type}
|
||||||
catch
|
catch
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
-include_lib("emqx/include/emqx.hrl").
|
-include_lib("emqx/include/emqx.hrl").
|
||||||
-include_lib("emqx/include/logger.hrl").
|
-include_lib("emqx/include/logger.hrl").
|
||||||
-include_lib("emqx/include/emqx_placeholder.hrl").
|
-include_lib("emqx/include/emqx_placeholder.hrl").
|
||||||
|
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
|
||||||
|
|
||||||
-behaviour(emqx_authz).
|
-behaviour(emqx_authz).
|
||||||
|
|
||||||
|
@ -104,6 +105,7 @@ authorize(
|
||||||
log_nomtach_msg(Status, Headers, Body),
|
log_nomtach_msg(Status, Headers, Body),
|
||||||
nomatch;
|
nomatch;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
|
?tp(authz_http_request_failure, #{error => Reason}),
|
||||||
?SLOG(error, #{
|
?SLOG(error, #{
|
||||||
msg => "http_server_query_failed",
|
msg => "http_server_query_failed",
|
||||||
resource => ResourceID,
|
resource => ResourceID,
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
-include_lib("common_test/include/ct.hrl").
|
-include_lib("common_test/include/ct.hrl").
|
||||||
-include_lib("emqx/include/emqx_placeholder.hrl").
|
-include_lib("emqx/include/emqx_placeholder.hrl").
|
||||||
|
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
|
||||||
|
|
||||||
-define(HTTP_PORT, 33333).
|
-define(HTTP_PORT, 33333).
|
||||||
-define(HTTP_PATH, "/authz/[...]").
|
-define(HTTP_PATH, "/authz/[...]").
|
||||||
|
@ -64,7 +65,14 @@ init_per_testcase(_Case, Config) ->
|
||||||
Config.
|
Config.
|
||||||
|
|
||||||
end_per_testcase(_Case, _Config) ->
|
end_per_testcase(_Case, _Config) ->
|
||||||
ok = emqx_authz_http_test_server:stop().
|
try
|
||||||
|
ok = emqx_authz_http_test_server:stop()
|
||||||
|
catch
|
||||||
|
exit:noproc ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
snabbkaffe:stop(),
|
||||||
|
ok.
|
||||||
|
|
||||||
%%------------------------------------------------------------------------------
|
%%------------------------------------------------------------------------------
|
||||||
%% Tests
|
%% Tests
|
||||||
|
@ -148,7 +156,39 @@ t_response_handling(_Config) ->
|
||||||
?assertEqual(
|
?assertEqual(
|
||||||
deny,
|
deny,
|
||||||
emqx_access_control:authorize(ClientInfo, publish, <<"t">>)
|
emqx_access_control:authorize(ClientInfo, publish, <<"t">>)
|
||||||
).
|
),
|
||||||
|
|
||||||
|
%% the server cannot be reached; should skip to the next
|
||||||
|
%% authorizer in the chain.
|
||||||
|
ok = emqx_authz_http_test_server:stop(),
|
||||||
|
|
||||||
|
?check_trace(
|
||||||
|
?assertEqual(
|
||||||
|
deny,
|
||||||
|
emqx_access_control:authorize(ClientInfo, publish, <<"t">>)
|
||||||
|
),
|
||||||
|
fun(Trace) ->
|
||||||
|
?assertMatch(
|
||||||
|
[
|
||||||
|
#{
|
||||||
|
?snk_kind := authz_http_request_failure,
|
||||||
|
error := {recoverable_error, econnrefused}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
?of_kind(authz_http_request_failure, Trace)
|
||||||
|
),
|
||||||
|
?assert(
|
||||||
|
?strict_causality(
|
||||||
|
#{?snk_kind := authz_http_request_failure},
|
||||||
|
#{?snk_kind := authz_non_superuser, result := nomatch},
|
||||||
|
Trace
|
||||||
|
)
|
||||||
|
),
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
t_query_params(_Config) ->
|
t_query_params(_Config) ->
|
||||||
ok = setup_handler_and_config(
|
ok = setup_handler_and_config(
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix handling of HTTP authorization result when a request failure (e.g.: HTTP resource is down) would cause a `function_clause` error.
|
|
@ -0,0 +1 @@
|
||||||
|
修正当请求失败(如:HTTP资源关闭)会导致`function_clause`错误时对HTTP授权结果的处理。
|
Loading…
Reference in New Issue