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:
Thales Macedo Garitezi 2023-01-05 11:02:04 -03:00
parent 32922a6830
commit c6b8e614df
6 changed files with 55 additions and 3 deletions

View File

@ -1,7 +1,7 @@
%% -*- mode: erlang -*-
{application, emqx_authz, [
{description, "An OTP application"},
{vsn, "0.1.10"},
{vsn, "0.1.11"},
{registered, []},
{mod, {emqx_authz_app, []}},
{applications, [

View File

@ -20,6 +20,7 @@
-include("emqx_authz.hrl").
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx/include/emqx_hooks.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-ifdef(TEST).
-compile(export_all).
@ -358,6 +359,7 @@ authorize_non_superuser(
emqx_metrics:inc(?METRIC_DENY),
{stop, #{result => deny, from => AuthzSource}};
nomatch ->
?tp(authz_non_superuser, #{result => nomatch}),
?SLOG(info, #{
msg => "authorization_failed_nomatch",
username => Username,
@ -388,6 +390,12 @@ do_authorize(
nomatch ->
emqx_metrics_worker:inc(authz_metrics, Type, nomatch),
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, Type}
catch

View File

@ -20,6 +20,7 @@
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx/include/emqx_placeholder.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-behaviour(emqx_authz).
@ -104,6 +105,7 @@ authorize(
log_nomtach_msg(Status, Headers, Body),
nomatch;
{error, Reason} ->
?tp(authz_http_request_failure, #{error => Reason}),
?SLOG(error, #{
msg => "http_server_query_failed",
resource => ResourceID,

View File

@ -23,6 +23,7 @@
-include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("emqx/include/emqx_placeholder.hrl").
-include_lib("snabbkaffe/include/snabbkaffe.hrl").
-define(HTTP_PORT, 33333).
-define(HTTP_PATH, "/authz/[...]").
@ -64,7 +65,14 @@ init_per_testcase(_Case, Config) ->
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
@ -148,7 +156,39 @@ t_response_handling(_Config) ->
?assertEqual(
deny,
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) ->
ok = setup_handler_and_config(

View File

@ -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.

View File

@ -0,0 +1 @@
修正当请求失败HTTP资源关闭会导致`function_clause`错误时对HTTP授权结果的处理。