Skip to content

Commit e8d9218

Browse files
committed
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
1 parent f322fb8 commit e8d9218

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
@@ -1699,33 +1699,47 @@ permissions_vhost_test(Config) ->
16991699
{tags, <<"administrator">>}], {group, '2xx'}),
17001700
http_put(Config, "/users/myuser", [{password, <<"myuser">>},
17011701
{tags, <<"management">>}], {group, '2xx'}),
1702+
http_put(Config, "/users/mymonitor", [{password, <<"mymonitor">>},
1703+
{tags, [<<"monitor">>, <<"management">>]}], {group, '2xx'}),
17021704
http_put(Config, "/vhosts/myvhost1", none, {group, '2xx'}),
17031705
http_put(Config, "/vhosts/myvhost2", none, {group, '2xx'}),
17041706
http_put(Config, "/permissions/myvhost1/myuser", PermArgs, {group, '2xx'}),
1707+
http_put(Config, "/permissions/myvhost1/mymonitor", PermArgs, {group, '2xx'}),
17051708
http_put(Config, "/permissions/myvhost1/guest", PermArgs, {group, '2xx'}),
17061709
http_put(Config, "/permissions/myvhost2/guest", PermArgs, {group, '2xx'}),
17071710
assert_list([#{name => <<"/">>},
17081711
#{name => <<"myvhost1">>},
17091712
#{name => <<"myvhost2">>}], http_get(Config, "/vhosts", ?OK)),
17101713
assert_list([#{name => <<"myvhost1">>}],
17111714
http_get(Config, "/vhosts", "myuser", "myuser", ?OK)),
1715+
assert_list([#{name => <<"myvhost1">>}],
1716+
http_get(Config, "/vhosts", "mymonitor", "mymonitor", ?OK)),
17121717
http_put(Config, "/queues/myvhost1/myqueue", QArgs, {group, '2xx'}),
17131718
http_put(Config, "/queues/myvhost2/myqueue", QArgs, {group, '2xx'}),
1719+
CheckResult = fun (Path, Result) ->
1720+
case maps:get(vhost, Result) of
1721+
<<"myvhost2">> ->
1722+
throw({got_result_from_vhost2_in, Path, Result});
1723+
_ ->
1724+
ok
1725+
end
1726+
end,
17141727
Test1 =
17151728
fun(Path) ->
1716-
Results = http_get(Config, Path, "myuser", "myuser", ?OK),
1717-
[case maps:get(vhost, Result) of
1718-
<<"myvhost2">> ->
1719-
throw({got_result_from_vhost2_in, Path, Result});
1720-
_ ->
1721-
ok
1722-
end || Result <- Results]
1729+
Results0 = http_get(Config, Path, "myuser", "myuser", ?OK),
1730+
[CheckResult(Path, Result0) || Result0 <- Results0],
1731+
Results1 = http_get(Config, Path, "mymonitor", "mymonitor", ?OK),
1732+
[CheckResult(Path, Result1) || Result1 <- Results1]
17231733
end,
17241734
Test2 =
17251735
fun(Path1, Path2) ->
17261736
http_get(Config, Path1 ++ "/myvhost1/" ++ Path2, "myuser", "myuser",
17271737
?OK),
17281738
http_get(Config, Path1 ++ "/myvhost2/" ++ Path2, "myuser", "myuser",
1739+
?NOT_AUTHORISED),
1740+
http_get(Config, Path1 ++ "/myvhost1/" ++ Path2, "mymonitor", "mymonitor",
1741+
?OK),
1742+
http_get(Config, Path1 ++ "/myvhost2/" ++ Path2, "mymonitor", "mymonitor",
17291743
?NOT_AUTHORISED)
17301744
end,
17311745
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)