Skip to content

Commit b7d6bf9

Browse files
Merge pull request #14931 from amazon-mq/lukebakken/rabbitmq-server-14923
HTTP API: when virtual host is known, limit permission filtering to just that specific virtual host
2 parents 25e31b5 + e8d9218 commit b7d6bf9

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)