diff --git a/deps/rabbit/Makefile b/deps/rabbit/Makefile index 6b4a41fa8a31..8810affa3ea5 100644 --- a/deps/rabbit/Makefile +++ b/deps/rabbit/Makefile @@ -257,7 +257,7 @@ define ct_master.erl halt(0) endef -PARALLEL_CT_SET_1_A = unit_cluster_formation_locking_mocks unit_cluster_formation_sort_nodes unit_collections unit_config_value_encryption unit_connection_tracking +PARALLEL_CT_SET_1_A = unit_rabbit_ssl unit_cluster_formation_locking_mocks unit_cluster_formation_sort_nodes unit_collections unit_config_value_encryption unit_connection_tracking PARALLEL_CT_SET_1_B = amqp_address amqp_auth amqp_credit_api_v2 amqp_filtex amqp_dotnet amqp_jms signal_handling single_active_consumer unit_access_control_authn_authz_context_propagation unit_access_control_credential_validation unit_amqp091_content_framing unit_amqp091_server_properties unit_app_management PARALLEL_CT_SET_1_C = amqp_proxy_protocol amqpl_consumer_ack amqpl_direct_reply_to backing_queue bindings rabbit_db_maintenance rabbit_db_msup rabbit_db_policy rabbit_db_queue rabbit_db_topic_exchange rabbit_direct_reply_to_prop cluster_limit cluster_minority term_to_binary_compat_prop topic_permission transactions unicode unit_access_control PARALLEL_CT_SET_1_D = amqqueue_backward_compatibility channel_interceptor channel_operation_timeout classic_queue classic_queue_prop config_schema peer_discovery_dns peer_discovery_tmp_hidden_node per_node_limit per_user_connection_channel_limit diff --git a/deps/rabbit/src/rabbit_definitions_import_https.erl b/deps/rabbit/src/rabbit_definitions_import_https.erl index 49d9d91f819f..4ec643c84883 100644 --- a/deps/rabbit/src/rabbit_definitions_import_https.erl +++ b/deps/rabbit/src/rabbit_definitions_import_https.erl @@ -49,7 +49,8 @@ load(Proplist) -> URL = pget(url, Proplist), rabbit_log:info("Applying definitions from a remote URL"), rabbit_log:debug("HTTPS URL: ~ts", [URL]), - TLSOptions = tls_options_or_default(Proplist), + TLSOptions0 = tls_options_or_default(Proplist), + TLSOptions = rabbit_ssl:wrap_password_opt(TLSOptions0), HTTPOptions = http_options(TLSOptions), load_from_url(URL, HTTPOptions). diff --git a/deps/rabbit/src/rabbit_networking.erl b/deps/rabbit/src/rabbit_networking.erl index a2a01ab822e2..e8244bab6561 100644 --- a/deps/rabbit/src/rabbit_networking.erl +++ b/deps/rabbit/src/rabbit_networking.erl @@ -282,7 +282,8 @@ start_ssl_listener(Listener, SslOpts, NumAcceptors) -> -spec start_ssl_listener( listener_config(), rabbit_types:infos(), integer(), integer()) -> 'ok' | {'error', term()}. -start_ssl_listener(Listener, SslOpts, NumAcceptors, ConcurrentConnsSupsCount) -> +start_ssl_listener(Listener, SslOpts0, NumAcceptors, ConcurrentConnsSupsCount) -> + SslOpts = rabbit_ssl:wrap_password_opt(SslOpts0), start_listener(Listener, NumAcceptors, ConcurrentConnsSupsCount, 'amqp/ssl', "TLS (SSL) listener", tcp_opts() ++ SslOpts). diff --git a/deps/rabbit/src/rabbit_ssl.erl b/deps/rabbit/src/rabbit_ssl.erl index e433af9398cc..ebc133b0d5d3 100644 --- a/deps/rabbit/src/rabbit_ssl.erl +++ b/deps/rabbit/src/rabbit_ssl.erl @@ -15,6 +15,7 @@ cipher_suites_openssl/2, cipher_suites_openssl/1, cipher_suites/1]). -export([info/2, cert_info/2]). +-export([wrap_password_opt/1]). %%-------------------------------------------------------------------------- @@ -34,6 +35,22 @@ -type certificate() :: rabbit_cert_info:certificate(). -type cipher_suites_mode() :: default | all | anonymous. +-type tls_opts() :: [ssl:tls_server_option()] | [ssl:tls_client_option()]. + +-spec wrap_password_opt(tls_opts()) -> tls_opts(). +wrap_password_opt(Opts0) -> + case proplists:get_value(password, Opts0) of + undefined -> + Opts0; + Fun when is_function(Fun) -> + Opts0; + Password -> + %% A password can be a value or a function returning that value. + %% See the key_pem_password/0 type in https://github.com/erlang/otp/pull/5843/files. + NewOpts = proplists:delete(password, Opts0), + Fun = fun() -> Password end, + [{password, Fun} | NewOpts] + end. -spec cipher_suites(cipher_suites_mode()) -> ssl:ciphers(). cipher_suites(Mode) -> diff --git a/deps/rabbit/test/unit_rabbit_ssl_SUITE.erl b/deps/rabbit/test/unit_rabbit_ssl_SUITE.erl new file mode 100644 index 000000000000..1c7bd90d20ea --- /dev/null +++ b/deps/rabbit/test/unit_rabbit_ssl_SUITE.erl @@ -0,0 +1,66 @@ +%% This Source Code Form is subject to the terms of the Mozilla Public +%% License, v. 2.0. If a copy of the MPL was not distributed with this +%% file, You can obtain one at https://mozilla.org/MPL/2.0/. +%% +%% Copyright (c) 2007-2025 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved. +%% + +-module(unit_rabbit_ssl_SUITE). + +-include_lib("eunit/include/eunit.hrl"). + +-compile(export_all). + +all() -> + [ + {group, parallel_tests} + ]. + +groups() -> + [ + {parallel_tests, [], [ + wrap_tls_opts_with_binary_password, + wrap_tls_opts_with_function_password + ]} + ]. + + +wrap_tls_opts_with_binary_password(_Config) -> + Path = "/tmp/path/to/private_key.pem", + Bin = <<"s3krE7">>, + Opts0 = [ + {keyfile, Path}, + {password, Bin} + ], + + Opts = rabbit_ssl:wrap_password_opt(Opts0), + M = maps:from_list(Opts), + + ?assertEqual(Path, maps:get(keyfile, M)), + ?assert(is_function(maps:get(password, M))), + + F = maps:get(password, M), + ?assertEqual(Bin, F()), + + passed. + +wrap_tls_opts_with_function_password(_Config) -> + Path = "/tmp/path/to/private_key.pem", + Bin = <<"s3krE7">>, + Fun = fun() -> Bin end, + Opts0 = [ + {keyfile, Path}, + {password, Fun} + ], + + Opts = rabbit_ssl:wrap_password_opt(Opts0), + M = maps:from_list(Opts), + + ?assertEqual(Path, maps:get(keyfile, M)), + ?assert(is_function(maps:get(password, M))), + ?assertEqual(Fun, maps:get(password, M)), + + F = maps:get(password, M), + ?assertEqual(Bin, F()), + + passed. \ No newline at end of file