Skip to content

Commit bc281d5

Browse files
Merge pull request #14405 from rabbitmq/mergify/bp/v4.1.x/pr-14403
Close stream connection if unauthorized vhost after secret update (backport #14403)
2 parents ada87aa + 4dcb2e8 commit bc281d5

File tree

2 files changed

+57
-17
lines changed

2 files changed

+57
-17
lines changed

deps/rabbitmq_stream/src/rabbit_stream_reader.erl

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,6 @@ handle_frame_pre_auth(Transport,
15051505
send(Transport, S, F),
15061506
Connection#stream_connection{connection_step = failure}
15071507
end,
1508-
15091508
{Connection1, State};
15101509
handle_frame_pre_auth(_Transport, Connection, State, heartbeat) ->
15111510
rabbit_log:debug("Received heartbeat frame pre auth"),
@@ -1614,21 +1613,8 @@ handle_frame_post_auth(Transport,
16141613
Challenge}};
16151614
{ok, NewUser = #user{username = NewUsername}} ->
16161615
case NewUsername of
1617-
Username ->
1618-
rabbit_core_metrics:auth_attempt_succeeded(Host,
1619-
Username,
1620-
stream),
1621-
notify_auth_result(Username,
1622-
user_authentication_success,
1623-
[],
1624-
C1,
1625-
S1),
1626-
rabbit_log:debug("Successfully updated secret for username '~ts'", [Username]),
1627-
{C1#stream_connection{user = NewUser,
1628-
authentication_state = done,
1629-
connection_step = authenticated},
1630-
{sasl_authenticate, ?RESPONSE_CODE_OK,
1631-
<<>>}};
1616+
Username ->
1617+
complete_secret_update(NewUser, C1, S1);
16321618
_ ->
16331619
rabbit_core_metrics:auth_attempt_failed(Host,
16341620
Username,
@@ -2780,6 +2766,32 @@ handle_frame_post_auth(Transport,
27802766
increase_protocol_counter(?UNKNOWN_FRAME),
27812767
{Connection#stream_connection{connection_step = close_sent}, State}.
27822768

2769+
complete_secret_update(NewUser = #user{username = Username},
2770+
#stream_connection{host = Host,
2771+
socket = S,
2772+
virtual_host = VH} = C1, S1) ->
2773+
notify_auth_result(Username, user_authentication_success, [], C1, S1),
2774+
rabbit_core_metrics:auth_attempt_succeeded(Host, Username, stream),
2775+
rabbit_log_connection:debug("Stream connection has successfully checked updated secret (token) for username '~ts'",
2776+
[Username]),
2777+
try
2778+
rabbit_log_connection:debug("Stream connection: will verify virtual host access after secret (token) update"),
2779+
rabbit_access_control:check_vhost_access(NewUser, VH, {socket, S}, #{}),
2780+
rabbit_log_connection:debug("Stream connection: successfully re-verified virtual host access"),
2781+
2782+
{C1#stream_connection{user = NewUser,
2783+
authentication_state = done,
2784+
connection_step = authenticated},
2785+
{sasl_authenticate, ?RESPONSE_CODE_OK,
2786+
<<>>}}
2787+
catch exit:#amqp_error{explanation = Explanation} ->
2788+
rabbit_log_connection:warning("Stream connection no longer has the permissions to access its target virtual host ('~ts') after a secret (token) update: ~ts",
2789+
[VH, Explanation]),
2790+
silent_close_delay(),
2791+
{C1#stream_connection{connection_step = failure},
2792+
{sasl_authenticate, ?RESPONSE_VHOST_ACCESS_FAILURE, <<>>}}
2793+
end.
2794+
27832795
process_client_command_versions(C, []) ->
27842796
C;
27852797
process_client_command_versions(C, [H | T]) ->

deps/rabbitmq_stream/test/rabbit_stream_SUITE.erl

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ groups() ->
4949
cannot_update_username_after_authenticated,
5050
cannot_use_another_authmechanism_when_updating_secret,
5151
update_secret_should_close_connection_if_wrong_secret,
52+
update_secret_should_close_connection_if_unauthorized_vhost,
5253
unauthenticated_client_rejected_tcp_connected,
5354
timeout_tcp_connected,
5455
unauthenticated_client_rejected_peer_properties_exchanged,
@@ -166,6 +167,12 @@ init_per_testcase(cannot_update_username_after_authenticated = TestCase, Config)
166167
ok = rabbit_ct_broker_helpers:add_user(Config, <<"other">>),
167168
rabbit_ct_helpers:testcase_started(Config, TestCase);
168169

170+
init_per_testcase(update_secret_should_close_connection_if_unauthorized_vhost = TestCase,
171+
Config) ->
172+
ok = rabbit_ct_broker_helpers:add_user(Config, <<"other">>),
173+
ok = rabbit_ct_broker_helpers:set_full_permissions(Config, <<"other">>, <<"/">>),
174+
rabbit_ct_helpers:testcase_started(Config, TestCase);
175+
169176
init_per_testcase(close_connection_on_consumer_update_timeout = TestCase, Config) ->
170177
ok = rabbit_ct_broker_helpers:rpc(Config,
171178
0,
@@ -201,6 +208,11 @@ end_per_testcase(cannot_update_username_after_authenticated = TestCase, Config)
201208
ok = rabbit_ct_broker_helpers:delete_user(Config, <<"other">>),
202209
rabbit_ct_helpers:testcase_finished(Config, TestCase);
203210

211+
end_per_testcase(update_secret_should_close_connection_if_unauthorized_vhost = TestCase,
212+
Config) ->
213+
ok = rabbit_ct_broker_helpers:delete_user(Config, <<"other">>),
214+
rabbit_ct_helpers:testcase_finished(Config, TestCase);
215+
204216
end_per_testcase(close_connection_on_consumer_update_timeout = TestCase, Config) ->
205217
ok = rabbit_ct_broker_helpers:rpc(Config,
206218
0,
@@ -286,7 +298,7 @@ test_update_secret(Config) ->
286298
{S, C0} = connect_and_authenticate(Transport, Config),
287299
rabbit_ct_broker_helpers:change_password(Config, <<"guest">>, <<"password">>),
288300
C1 = expect_successful_authentication(
289-
try_authenticate(Transport, S, C0, <<"PLAIN">>, <<"guest">>, <<"password">>)),
301+
try_authenticate(Transport, S, C0, <<"PLAIN">>, <<"guest">>, <<"password">>)),
290302
_C2 = test_close(Transport, S, C1),
291303
closed = wait_for_socket_close(Transport, S, 10),
292304
ok.
@@ -317,6 +329,22 @@ update_secret_should_close_connection_if_wrong_secret(Config) ->
317329
closed = wait_for_socket_close(Transport, S, 10),
318330
ok.
319331

332+
update_secret_should_close_connection_if_unauthorized_vhost(Config) ->
333+
T = gen_tcp,
334+
Port = get_port(T, Config),
335+
Opts = get_opts(T),
336+
{ok, S} = T:connect("localhost", Port, Opts),
337+
C0 = rabbit_stream_core:init(0),
338+
C1 = test_peer_properties(T, S, C0),
339+
Username = <<"other">>,
340+
C2 = test_authenticate(T, S, C1, Username),
341+
ok = rabbit_ct_broker_helpers:clear_permissions(Config, Username, <<"/">>),
342+
_C3 = expect_unsuccessful_authentication(
343+
try_authenticate(gen_tcp, S, C2, <<"PLAIN">>, Username, Username),
344+
?RESPONSE_VHOST_ACCESS_FAILURE),
345+
closed = wait_for_socket_close(T, S, 10),
346+
ok.
347+
320348
test_stream_tls(Config) ->
321349
Stream = atom_to_binary(?FUNCTION_NAME, utf8),
322350
test_server(ssl, Stream, Config),

0 commit comments

Comments
 (0)