Skip to content

Commit 64c15d3

Browse files
lukebakkenmergify[bot]
authored andcommitted
When vhost is known, limit auth to that vhost
This reduces the number of extraneous auth queries to vhosts that aren't relevant. These changes also provide friendlier formatting in `log_access_control_result` Fixes #14923 (cherry picked from commit e8d9218)
1 parent 7e43377 commit 64c15d3

File tree

3 files changed

+61
-51
lines changed

3 files changed

+61
-51
lines changed

deps/rabbitmq_management/src/rabbit_mgmt_util.erl

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ get_sort_reverse(ReqData) ->
313313
V -> list_to_atom(V)
314314
end.
315315

316-
317316
-spec is_pagination_requested(#pagination{} | undefined) -> boolean().
318317
is_pagination_requested(undefined) ->
319318
false;
@@ -981,9 +980,28 @@ all_or_one_vhost(ReqData, Fun) ->
981980
VHost -> Fun(VHost)
982981
end.
983982

984-
filter_vhost(List, ReqData, Context) ->
985-
User = #user{tags = Tags} = Context#context.user,
986-
Fn = case rabbit_web_dispatch_access_control:is_admin(Tags) of
983+
filter_vhost(List, ReqData, Context = #context{user = #user{tags = Tags}}) ->
984+
IsAdmin = rabbit_web_dispatch_access_control:is_admin(Tags),
985+
filter_vhost({vhost, vhost(ReqData)}, IsAdmin, List, ReqData, Context).
986+
987+
filter_vhost({vhost, not_found}, IsAdmin, List, ReqData, Context) ->
988+
filter_none_or_not_found_vhost(IsAdmin, List, ReqData, Context);
989+
filter_vhost({vhost, none}, IsAdmin, List, ReqData, Context) ->
990+
filter_none_or_not_found_vhost(IsAdmin, List, ReqData, Context);
991+
filter_vhost({vhost, _VHost}, _IsAdmin=true, List, _ReqData, _Context) ->
992+
[I || I <- List, lists:member(pget(vhost, I), rabbit_vhost:list())];
993+
filter_vhost({vhost, VHost}, _IsAdmin=false, List, ReqData, #context{user = User}) ->
994+
AuthzData = get_authz_data(ReqData),
995+
case catch rabbit_access_control:check_vhost_access(User, VHost, AuthzData, #{}) of
996+
ok ->
997+
[I || I <- List, pget(vhost, I) =:= VHost];
998+
NotOK ->
999+
log_access_control_result(NotOK),
1000+
[]
1001+
end.
1002+
1003+
filter_none_or_not_found_vhost(IsAdmin, List, ReqData, #context{user = User}) ->
1004+
Fn = case IsAdmin of
9871005
true -> fun list_visible_vhosts_names/2;
9881006
false -> fun list_login_vhosts_names/2
9891007
end,
@@ -1090,6 +1108,8 @@ list_login_vhosts(User, AuthzData) ->
10901108
end].
10911109

10921110
% rabbitmq/rabbitmq-auth-backend-http#100
1111+
log_access_control_result({'EXIT', #amqp_error{name = Name, explanation = Msg}}) ->
1112+
?LOG_DEBUG("rabbit_access_control:check_vhost_access result: '~tp', ~ts", [Name, Msg]);
10931113
log_access_control_result(NotOK) ->
10941114
?LOG_DEBUG("rabbit_access_control:check_vhost_access result: ~tp", [NotOK]).
10951115

deps/rabbitmq_management/test/rabbit_mgmt_http_SUITE.erl

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,33 +1709,47 @@ permissions_vhost_test(Config) ->
17091709
{tags, <<"administrator">>}], {group, '2xx'}),
17101710
http_put(Config, "/users/myuser", [{password, <<"myuser">>},
17111711
{tags, <<"management">>}], {group, '2xx'}),
1712+
http_put(Config, "/users/mymonitor", [{password, <<"mymonitor">>},
1713+
{tags, [<<"monitor">>, <<"management">>]}], {group, '2xx'}),
17121714
http_put(Config, "/vhosts/myvhost1", none, {group, '2xx'}),
17131715
http_put(Config, "/vhosts/myvhost2", none, {group, '2xx'}),
17141716
http_put(Config, "/permissions/myvhost1/myuser", PermArgs, {group, '2xx'}),
1717+
http_put(Config, "/permissions/myvhost1/mymonitor", PermArgs, {group, '2xx'}),
17151718
http_put(Config, "/permissions/myvhost1/guest", PermArgs, {group, '2xx'}),
17161719
http_put(Config, "/permissions/myvhost2/guest", PermArgs, {group, '2xx'}),
17171720
assert_list([#{name => <<"/">>},
17181721
#{name => <<"myvhost1">>},
17191722
#{name => <<"myvhost2">>}], http_get(Config, "/vhosts", ?OK)),
17201723
assert_list([#{name => <<"myvhost1">>}],
17211724
http_get(Config, "/vhosts", "myuser", "myuser", ?OK)),
1725+
assert_list([#{name => <<"myvhost1">>}],
1726+
http_get(Config, "/vhosts", "mymonitor", "mymonitor", ?OK)),
17221727
http_put(Config, "/queues/myvhost1/myqueue", QArgs, {group, '2xx'}),
17231728
http_put(Config, "/queues/myvhost2/myqueue", QArgs, {group, '2xx'}),
1729+
CheckResult = fun (Path, Result) ->
1730+
case maps:get(vhost, Result) of
1731+
<<"myvhost2">> ->
1732+
throw({got_result_from_vhost2_in, Path, Result});
1733+
_ ->
1734+
ok
1735+
end
1736+
end,
17241737
Test1 =
17251738
fun(Path) ->
1726-
Results = http_get(Config, Path, "myuser", "myuser", ?OK),
1727-
[case maps:get(vhost, Result) of
1728-
<<"myvhost2">> ->
1729-
throw({got_result_from_vhost2_in, Path, Result});
1730-
_ ->
1731-
ok
1732-
end || Result <- Results]
1739+
Results0 = http_get(Config, Path, "myuser", "myuser", ?OK),
1740+
[CheckResult(Path, Result0) || Result0 <- Results0],
1741+
Results1 = http_get(Config, Path, "mymonitor", "mymonitor", ?OK),
1742+
[CheckResult(Path, Result1) || Result1 <- Results1]
17331743
end,
17341744
Test2 =
17351745
fun(Path1, Path2) ->
17361746
http_get(Config, Path1 ++ "/myvhost1/" ++ Path2, "myuser", "myuser",
17371747
?OK),
17381748
http_get(Config, Path1 ++ "/myvhost2/" ++ Path2, "myuser", "myuser",
1749+
?NOT_AUTHORISED),
1750+
http_get(Config, Path1 ++ "/myvhost1/" ++ Path2, "mymonitor", "mymonitor",
1751+
?OK),
1752+
http_get(Config, Path1 ++ "/myvhost2/" ++ Path2, "mymonitor", "mymonitor",
17391753
?NOT_AUTHORISED)
17401754
end,
17411755
Test3 =

deps/rabbitmq_web_dispatch/src/rabbit_web_dispatch_access_control.erl

Lines changed: 16 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
is_authorized_vhost_visible_for_monitoring/3,
2121
is_authorized_global_parameters/3]).
2222

23-
-export([list_visible_vhosts/1, list_visible_vhosts_names/1, list_login_vhosts/2]).
2423
-export([id/2]).
2524
-export([not_authorised/3, halt_response/5]).
2625

@@ -255,23 +254,34 @@ user_matches_vhost(ReqData, User) ->
255254
not_found -> true;
256255
none -> true;
257256
V ->
258-
AuthzData = get_authz_data(ReqData),
259-
lists:member(V, list_login_vhosts_names(User, AuthzData))
257+
check_vhost_access(ReqData, User, V)
260258
end.
261259

262-
user_matches_vhost_visible(ReqData, User) ->
260+
user_matches_vhost_visible(ReqData, User = #user{tags = Tags}) ->
263261
case vhost(ReqData) of
264262
not_found -> true;
265263
none -> true;
266264
V ->
267-
AuthzData = get_authz_data(ReqData),
268-
lists:member(V, list_visible_vhosts_names(User, AuthzData))
265+
case is_monitor(Tags) of
266+
true ->
267+
rabbit_vhost:exists(V);
268+
false ->
269+
check_vhost_access(ReqData, User, V)
270+
end
269271
end.
270272

271273
get_authz_data(ReqData) ->
272274
{PeerAddress, _PeerPort} = cowboy_req:peer(ReqData),
273275
{ip, PeerAddress}.
274276

277+
check_vhost_access(ReqData, User, VHost) ->
278+
AuthzData = get_authz_data(ReqData),
279+
case catch rabbit_access_control:check_vhost_access(User, VHost, AuthzData, #{}) of
280+
ok -> true;
281+
NotOK ->
282+
log_access_control_result(NotOK),
283+
false
284+
end.
275285

276286
not_authorised(Reason, ReqData, Context) ->
277287
%% TODO: consider changing to 403 in 4.0
@@ -328,40 +338,6 @@ id0(Key, ReqData) ->
328338
Id -> Id
329339
end.
330340

331-
332-
list_visible_vhosts_names(User) ->
333-
list_visible_vhosts(User, undefined).
334-
335-
list_visible_vhosts_names(User, AuthzData) ->
336-
list_visible_vhosts(User, AuthzData).
337-
338-
list_visible_vhosts(User) ->
339-
list_visible_vhosts(User, undefined).
340-
341-
list_visible_vhosts(User = #user{tags = Tags}, AuthzData) ->
342-
case is_monitor(Tags) of
343-
true -> rabbit_vhost:list_names();
344-
false -> list_login_vhosts_names(User, AuthzData)
345-
end.
346-
347-
list_login_vhosts_names(User, AuthzData) ->
348-
[V || V <- rabbit_vhost:list_names(),
349-
case catch rabbit_access_control:check_vhost_access(User, V, AuthzData, #{}) of
350-
ok -> true;
351-
NotOK ->
352-
log_access_control_result(NotOK),
353-
false
354-
end].
355-
356-
list_login_vhosts(User, AuthzData) ->
357-
[V || V <- rabbit_vhost:all(),
358-
case catch rabbit_access_control:check_vhost_access(User, vhost:get_name(V), AuthzData, #{}) of
359-
ok -> true;
360-
NotOK ->
361-
log_access_control_result(NotOK),
362-
false
363-
end].
364-
365341
% rabbitmq/rabbitmq-auth-backend-http#100
366342
log_access_control_result(NotOK) ->
367343
?LOG_DEBUG("rabbit_access_control:check_vhost_access result: ~tp", [NotOK]).

0 commit comments

Comments
 (0)