From b6fbc0292a0d40b60b2db5f05d9df721cccf7096 Mon Sep 17 00:00:00 2001 From: David Ansari Date: Fri, 16 Aug 2024 14:38:36 +0200 Subject: [PATCH] Maintain order of configured SASL mechanisms RabbitMQ should advertise the SASL mechanisms in the order as configured in `rabbitmq.conf`. Starting RabbitMQ with the following `rabbitmq.conf`: ``` auth_mechanisms.1 = PLAIN auth_mechanisms.2 = AMQPLAIN auth_mechanisms.3 = ANONYMOUS ``` translates prior to this commit to: ``` 1> application:get_env(rabbit, auth_mechanisms). {ok,['ANONYMOUS','AMQPLAIN','PLAIN']} ``` and after this commit to: ``` 1> application:get_env(rabbit, auth_mechanisms). {ok,['PLAIN','AMQPLAIN','ANONYMOUS']} ``` In our 4.0 docs we write: > The server mechanisms are ordered in decreasing level of preference. which complies with https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-security-v1.0-os.html#type-sasl-mechanisms --- deps/rabbit/priv/schema/rabbit.schema | 9 ++++---- .../config_schema_SUITE_data/rabbit.snippets | 14 ++++++++++++ .../src/rabbit_ct_config_schema.erl | 22 +++++++++++++------ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/deps/rabbit/priv/schema/rabbit.schema b/deps/rabbit/priv/schema/rabbit.schema index 049dbb5faf..8f805911d0 100644 --- a/deps/rabbit/priv/schema/rabbit.schema +++ b/deps/rabbit/priv/schema/rabbit.schema @@ -455,10 +455,11 @@ end}. {datatype, atom}]}. {translation, "rabbit.auth_mechanisms", -fun(Conf) -> - Settings = cuttlefish_variable:filter_by_prefix("auth_mechanisms", Conf), - [ V || {_, V} <- Settings ] -end}. + fun(Conf) -> + Settings = cuttlefish_variable:filter_by_prefix("auth_mechanisms", Conf), + Sorted = lists:keysort(1, Settings), + [V || {_, V} <- Sorted] + end}. %% Select an authentication backend to use. RabbitMQ provides an diff --git a/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets b/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets index a74b249ea0..cf6075693d 100644 --- a/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets +++ b/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets @@ -239,6 +239,20 @@ default_permissions.write = .*", [{rabbit, [{anonymous_login_user, none}]}], []}, + + {auth_mechanisms_ordered, + "auth_mechanisms.1 = PLAIN +auth_mechanisms.2 = AMQPLAIN +auth_mechanisms.3 = ANONYMOUS", + [], + [{rabbit, + %% We expect the mechanisms in the order as declared. + [{auth_mechanisms, ['PLAIN', 'AMQPLAIN', 'ANONYMOUS']}] + }], + [], + nosort + }, + {cluster_formation, "cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config cluster_formation.classic_config.nodes.peer1 = rabbit@hostname1 diff --git a/deps/rabbitmq_ct_helpers/src/rabbit_ct_config_schema.erl b/deps/rabbitmq_ct_helpers/src/rabbit_ct_config_schema.erl index 2f68bc3643..7baee0264b 100644 --- a/deps/rabbitmq_ct_helpers/src/rabbit_ct_config_schema.erl +++ b/deps/rabbitmq_ct_helpers/src/rabbit_ct_config_schema.erl @@ -25,10 +25,14 @@ run_snippets(Config) -> {ok, [Snippets]} = file:consult(?config(conf_snippets, Config)), ct:pal("Loaded config schema snippets: ~tp", [Snippets]), lists:map( - fun({N, S, C, P}) -> ok = test_snippet(Config, {snippet_id(N), S, []}, C, P); - ({N, S, A, C, P}) -> ok = test_snippet(Config, {snippet_id(N), S, A}, C, P) - end, - Snippets), + fun({N, S, C, P}) -> + ok = test_snippet(Config, {snippet_id(N), S, []}, C, P, true); + ({N, S, A, C, P}) -> + ok = test_snippet(Config, {snippet_id(N), S, A}, C, P, true); + ({N, S, A, C, P, nosort}) -> + ok = test_snippet(Config, {snippet_id(N), S, A}, C, P, false) + end, + Snippets), ok. snippet_id(N) when is_integer(N) -> @@ -40,7 +44,7 @@ snippet_id(A) when is_atom(A) -> snippet_id(L) when is_list(L) -> L. -test_snippet(Config, Snippet = {SnipID, _, _}, Expected, _Plugins) -> +test_snippet(Config, Snippet = {SnipID, _, _}, Expected, _Plugins, Sort) -> {ConfFile, AdvancedFile} = write_snippet(Config, Snippet), %% We ignore the rabbit -> log portion of the config on v3.9+, where the lager %% dependency has been dropped @@ -50,8 +54,12 @@ test_snippet(Config, Snippet = {SnipID, _, _}, Expected, _Plugins) -> _ -> generate_config(ConfFile, AdvancedFile) end, - Gen = deepsort(Generated), - Exp = deepsort(Expected), + {Exp, Gen} = case Sort of + true -> + {deepsort(Expected), deepsort(Generated)}; + false -> + {Expected, Generated} + end, case Exp of Gen -> ok; _ ->