From 2779bf737542a3d6a9aa1e7271394f1d554f4a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20G=C3=B6m=C3=B6ri?= Date: Tue, 4 Jun 2024 16:08:34 +0200 Subject: [PATCH] amqp10_client: allow configuring global TLS options Since OTP 26 the verify_peer TLS option is enabled by default, which requires to specify cacerts as well. This change helps with not having to specify TLS options like cacertfile at every connection. This is especially helpful for shovels using AMQP 1.0, where the TLS options would otherwise need to be specified as URI parameters. Similar env configuration already exists for amqp_client. --- deps/amqp10_client/src/amqp10_client.erl | 16 +++++++++++++++- deps/amqp10_client/test/system_SUITE.erl | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/deps/amqp10_client/src/amqp10_client.erl b/deps/amqp10_client/src/amqp10_client.erl index bf00b531cc4..68cac262226 100644 --- a/deps/amqp10_client/src/amqp10_client.erl +++ b/deps/amqp10_client/src/amqp10_client.erl @@ -107,7 +107,8 @@ open_connection(ConnectionConfig0) -> notify_when_closed => NotifyWhenClosed }, Sasl = maps:get(sasl, ConnectionConfig1), - ConnectionConfig = ConnectionConfig1#{sasl => amqp10_client_connection:encrypt_sasl(Sasl)}, + ConnectionConfig2 = ConnectionConfig1#{sasl => amqp10_client_connection:encrypt_sasl(Sasl)}, + ConnectionConfig = merge_default_tls_options(ConnectionConfig2), amqp10_client_connection:open(ConnectionConfig). %% @doc Closes a connection. @@ -513,6 +514,19 @@ try_to_existing_atom(L) when is_list(L) -> ensure_started() -> _ = application:ensure_all_started(credentials_obfuscation). + +-spec merge_default_tls_options(connection_config()) -> connection_config(). +merge_default_tls_options(#{tls_opts := {secure_port, TlsOpts0}} = Config) -> + GlobalTlsOpts = application:get_env(amqp10_client, ssl_options, []), + TlsOpts = + orddict:to_list( + orddict:merge(fun (_, _A, B) -> B end, + orddict:from_list(GlobalTlsOpts), + orddict:from_list(TlsOpts0))), + Config#{tls_opts => {secure_port, TlsOpts}}; +merge_default_tls_options(Config) -> + Config. + -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/deps/amqp10_client/test/system_SUITE.erl b/deps/amqp10_client/test/system_SUITE.erl index 314040af392..9b72dd4f6e5 100644 --- a/deps/amqp10_client/test/system_SUITE.erl +++ b/deps/amqp10_client/test/system_SUITE.erl @@ -34,6 +34,7 @@ groups() -> {activemq, [], shared()}, {rabbitmq_strict, [], [ basic_roundtrip_tls, + roundtrip_tls_global_config, open_connection_plain_sasl, open_connection_plain_sasl_failure, open_connection_plain_sasl_parse_uri @@ -269,6 +270,26 @@ basic_roundtrip_tls(Config) -> sasl => ?config(sasl, Config)}, roundtrip(OpnConf). +%% ssl option validation fails if verify_peer is enabled without cacerts. +%% Test that cacertfile option takes effect taken from the application env. +roundtrip_tls_global_config(Config) -> + Hostname = ?config(rmq_hostname, Config), + Port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_amqp_tls), + CACertFile = ?config(rmq_certsdir, Config) ++ "/testca/cacert.pem", + CertFile = ?config(rmq_certsdir, Config) ++ "/client/cert.pem", + KeyFile = ?config(rmq_certsdir, Config) ++ "/client/key.pem", + ok = application:set_env(amqp10_client, ssl_options, [{cacertfile, CACertFile}, + {certfile, CertFile}, + {keyfile, KeyFile}]), + OpnConf = #{address => Hostname, + port => Port, + tls_opts => {secure_port, [{verify, verify_peer}]}, + notify => self(), + container_id => <<"open_connection_tls_container">>, + sasl => ?config(sasl, Config)}, + roundtrip(OpnConf), + application:unset_env(amqp10_client, ssl_options). + service_bus_config(Config, ContainerId) -> Hostname = ?config(sb_endpoint, Config), Port = ?config(sb_port, Config),