diff options
| author | Michael Klishin <michael@clojurewerkz.org> | 2021-08-17 20:42:53 +0300 |
|---|---|---|
| committer | Michael Klishin <michael@clojurewerkz.org> | 2021-08-17 20:42:53 +0300 |
| commit | 6a0058fe7c09cd41b87570614e6d8f29b84a0965 (patch) | |
| tree | a83c40f53b5b76277ba16257d09a3697740bceae | |
| parent | f3a52354087c4fa3cde6879502f9876a6f5175d2 (diff) | |
| download | rabbitmq-server-git-6a0058fe7c09cd41b87570614e6d8f29b84a0965.tar.gz | |
Introduce TLS-related rabbitmq.conf settings for definition import
currently only used by the HTTPS mechanism but can be used by
any other.
| -rw-r--r-- | deps/rabbit/priv/schema/rabbit.schema | 101 | ||||
| -rw-r--r-- | deps/rabbit/src/rabbit_definitions_import_https.erl | 18 | ||||
| -rw-r--r-- | deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets | 46 | ||||
| -rw-r--r-- | deps/rabbit/test/definition_import_SUITE.erl | 45 | ||||
| -rw-r--r-- | release-notes/3.9.4.md | 3 |
5 files changed, 207 insertions, 6 deletions
diff --git a/deps/rabbit/priv/schema/rabbit.schema b/deps/rabbit/priv/schema/rabbit.schema index c4688b64a5..adb68b3927 100644 --- a/deps/rabbit/priv/schema/rabbit.schema +++ b/deps/rabbit/priv/schema/rabbit.schema @@ -159,9 +159,101 @@ end}. {mapping, "definitions.https.url", "rabbit.definitions.url", [{datatype, string}]}. +%% Client-side TLS settings used by e.g. HTTPS definition loading mechanism. +%% These can be reused by other clients. + +{mapping, "definitions.tls.verify", "rabbit.definitions.ssl_options.verify", [ + {datatype, {enum, [verify_peer, verify_none]}}]}. + +{mapping, "definitions.tls.fail_if_no_peer_cert", "rabbit.definitions.ssl_options.fail_if_no_peer_cert", [ + {datatype, {enum, [true, false]}}]}. + +{mapping, "definitions.tls.cacertfile", "rabbit.definitions.ssl_options.cacertfile", + [{datatype, string}, {validators, ["file_accessible"]}]}. + +{mapping, "definitions.tls.certfile", "rabbit.definitions.ssl_options.certfile", + [{datatype, string}, {validators, ["file_accessible"]}]}. + +{mapping, "definitions.tls.cacerts.$name", "rabbit.definitions.ssl_options.cacerts", + [{datatype, string}]}. + +{translation, "rabbit.definitions.ssl_options.cacerts", +fun(Conf) -> + Settings = cuttlefish_variable:filter_by_prefix("definitions.tls.cacerts", Conf), + [ list_to_binary(V) || {_, V} <- Settings ] +end}. + +{mapping, "definitions.tls.cert", "rabbit.definitions.ssl_options.cert", + [{datatype, string}]}. + +{translation, "rabbit.definitions.ssl_options.cert", +fun(Conf) -> + list_to_binary(cuttlefish:conf_get("definitions.tls.cert", Conf)) +end}. + +{mapping, "definitions.tls.reuse_session", "rabbit.definitions.ssl_options.reuse_session", + [{datatype, {enum, [true, false]}}]}. + +{mapping, "definitions.tls.crl_check", "rabbit.definitions.ssl_options.crl_check", + [{datatype, [{enum, [true, false, peer, best_effort]}]}]}. + +{mapping, "definitions.tls.depth", "rabbit.definitions.ssl_options.depth", + [{datatype, integer}, {validators, ["byte"]}]}. + +{mapping, "definitions.tls.dh", "rabbit.definitions.ssl_options.dh", + [{datatype, string}]}. + +{translation, "rabbit.definitions.ssl_options.dh", +fun(Conf) -> + list_to_binary(cuttlefish:conf_get("definitions.tls.dh", Conf)) +end}. + +{translation, "rabbit.definitions.ssl_options.key", +fun(Conf) -> + case cuttlefish_variable:filter_by_prefix("definitions.tls.key", Conf) of + [{[_,_,Key], Val}|_] -> {list_to_atom(Key), list_to_binary(Val)}; + _ -> cuttlefish:unset() + end +end}. + +{mapping, "definitions.tls.keyfile", "rabbit.definitions.ssl_options.keyfile", + [{datatype, string}, {validators, ["file_accessible"]}]}. + +{mapping, "definitions.tls.log_alert", "rabbit.definitions.ssl_options.log_alert", + [{datatype, {enum, [true, false]}}]}. + +{mapping, "definitions.tls.password", "rabbit.definitions.ssl_options.password", + [{datatype, string}]}. + +{mapping, "definitions.tls.secure_renegotiate", "rabbit.definitions.ssl_options.secure_renegotiate", + [{datatype, {enum, [true, false]}}]}. + +{mapping, "definitions.tls.reuse_sessions", "rabbit.definitions.ssl_options.reuse_sessions", + [{datatype, {enum, [true, false]}}]}. + +{mapping, "definitions.tls.versions.$version", "rabbit.definitions.ssl_options.versions", + [{datatype, atom}]}. + +{translation, "rabbit.definitions.ssl_options.versions", +fun(Conf) -> + Settings = cuttlefish_variable:filter_by_prefix("definitions.tls.versions", Conf), + [V || {_, V} <- Settings] +end}. + +{mapping, "definitions.tls.ciphers.$cipher", "rabbit.definitions.ssl_options.ciphers", + [{datatype, string}]}. + +{translation, "rabbit.definitions.ssl_options.ciphers", +fun(Conf) -> + Settings = cuttlefish_variable:filter_by_prefix("definitions.tls.ciphers", Conf), + lists:reverse([V || {_, V} <- Settings]) +end}. + +{mapping, "definitions.tls.log_level", "rabbit.definitions.ssl_options.log_level", + [{datatype, {enum, [emergency, alert, critical, error, warning, notice, info, debug]}}]}. + %% -%% Security / AAA -%% ============== +%% Seed User, Authentication, Access Control %% %% The default "guest" user is only permitted to access the server @@ -283,13 +375,16 @@ end}. fun(Conf) -> case cuttlefish_variable:filter_by_prefix("ssl_options.key", Conf) of [{[_,_,Key], Val}|_] -> {list_to_atom(Key), list_to_binary(Val)}; - _ -> undefined + _ -> cuttlefish:unset() end end}. {mapping, "ssl_options.keyfile", "rabbit.ssl_options.keyfile", [{datatype, string}, {validators, ["file_accessible"]}]}. +{mapping, "ssl_options.log_level", "rabbit.ssl_options.log_level", + [{datatype, {enum, [emergency, alert, critical, error, warning, notice, info, debug]}}]}. + {mapping, "ssl_options.log_alert", "rabbit.ssl_options.log_alert", [{datatype, {enum, [true, false]}}]}. diff --git a/deps/rabbit/src/rabbit_definitions_import_https.erl b/deps/rabbit/src/rabbit_definitions_import_https.erl index 7115f2d2e8..f239400edd 100644 --- a/deps/rabbit/src/rabbit_definitions_import_https.erl +++ b/deps/rabbit/src/rabbit_definitions_import_https.erl @@ -15,7 +15,7 @@ --import(rabbit_misc, [pget/2]). +-import(rabbit_misc, [pget/2, pget/3]). -import(rabbit_data_coercion, [to_binary/1]). -import(rabbit_definitions, [import_raw/1]). @@ -38,9 +38,20 @@ is_enabled() -> end. load(Proplist) -> + rabbit_log:debug("Definitions proprties: ~p", [Proplist]), URL = pget(url, Proplist), - %% TODO - HTTPOptions = [], + TLSOptions0 = [ + %% avoids a peer verification warning emitted by default if no certificate chain and peer verification + %% settings are provided: these are not essential in this particular case (client-side downloads that likely + %% will happen from a local trusted source) + {log_level, error}, + %% use TLSv1.2 by default + {versions, ['tlsv1.2']} + ], + TLSOptions = pget(ssl_options, Proplist, TLSOptions0), + HTTPOptions = [ + {ssl, TLSOptions} + ], load_from_url(URL, HTTPOptions). @@ -54,6 +65,7 @@ load_from_url(URL, HTTPOptions0) -> {body_format, binary} ], HTTPOptions = HTTPOptions0 ++ [ + {connect_timeout, 120000}, {autoredirect, true} ], rabbit_log:info("Applying definitions from remote URL"), diff --git a/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets b/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets index 93fd8d855b..08ea31ff49 100644 --- a/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets +++ b/deps/rabbit/test/config_schema_SUITE_data/rabbit.snippets @@ -683,6 +683,52 @@ credential_validator.regexp = ^abc\\d+", ]}], []}, + %% modern configuration key, HTTPS source + {definition_files, "definitions.import_backend = https + definitions.https.url = https://rabbitmq.eng.megacorp.local/env-1/case1.json + definitions.tls.versions.1 = tlsv1.2 + definitions.tls.log_level = error + + definitions.tls.secure_renegotiate = true + + definitions.tls.ciphers.1 = ECDHE-ECDSA-AES256-GCM-SHA384 + definitions.tls.ciphers.2 = ECDHE-RSA-AES256-GCM-SHA384 + definitions.tls.ciphers.3 = ECDH-ECDSA-AES256-GCM-SHA384 + definitions.tls.ciphers.4 = ECDH-RSA-AES256-GCM-SHA384 + definitions.tls.ciphers.5 = DHE-RSA-AES256-GCM-SHA384 + definitions.tls.ciphers.6 = DHE-DSS-AES256-GCM-SHA384 + definitions.tls.ciphers.7 = ECDHE-ECDSA-AES128-GCM-SHA256 + definitions.tls.ciphers.8 = ECDHE-RSA-AES128-GCM-SHA256 + definitions.tls.ciphers.9 = ECDH-ECDSA-AES128-GCM-SHA256 + definitions.tls.ciphers.10 = ECDH-RSA-AES128-GCM-SHA256 + definitions.tls.ciphers.11 = DHE-RSA-AES128-GCM-SHA256 + definitions.tls.ciphers.12 = DHE-DSS-AES128-GCM-SHA256", + [{rabbit, [ + {definitions, [ + {import_backend, rabbit_definitions_import_https}, + {url, "https://rabbitmq.eng.megacorp.local/env-1/case1.json"}, + {ssl_options, [ + {log_level, error}, + {secure_renegotiate, true}, + {versions, ['tlsv1.2']}, + {ciphers, [ + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDH-ECDSA-AES256-GCM-SHA384", + "ECDH-RSA-AES256-GCM-SHA384", + "DHE-RSA-AES256-GCM-SHA384", + "DHE-DSS-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDH-ECDSA-AES128-GCM-SHA256", + "ECDH-RSA-AES128-GCM-SHA256", + "DHE-RSA-AES128-GCM-SHA256", + "DHE-DSS-AES128-GCM-SHA256" + ]} + ]} + ]}]}], + []}, + %% %% Raft %% diff --git a/deps/rabbit/test/definition_import_SUITE.erl b/deps/rabbit/test/definition_import_SUITE.erl index f4bf62fcdb..eff4ba1707 100644 --- a/deps/rabbit/test/definition_import_SUITE.erl +++ b/deps/rabbit/test/definition_import_SUITE.erl @@ -19,6 +19,7 @@ all() -> {group, boot_time_import_using_classic_source}, %% uses rabbit.definitions with import_backend set to local_filesystem {group, boot_time_import_using_modern_local_filesystem_source}, + {group, boot_time_import_using_public_https_source}, {group, roundtrip}, {group, import_on_a_running_node} ]. @@ -55,6 +56,10 @@ groups() -> import_on_a_booting_node_using_modern_local_filesystem_source ]}, + {boot_time_import_using_public_https_source, [], [ + import_on_a_booting_node_using_public_https_source + ]}, + {roundtrip, [], [ export_import_round_trip_case1, export_import_round_trip_case2 @@ -98,6 +103,38 @@ init_per_group(boot_time_import_using_modern_local_filesystem_source = Group, Co ]} ]}), rabbit_ct_helpers:run_setup_steps(Config2, rabbit_ct_broker_helpers:setup_steps()); +init_per_group(boot_time_import_using_public_https_source = Group, Config) -> + Config1 = rabbit_ct_helpers:set_config(Config, [ + {rmq_nodename_suffix, Group}, + {rmq_nodes_count, 1} + ]), + Config2 = rabbit_ct_helpers:merge_app_env(Config1, + {rabbit, [ + {definitions, [ + {import_backend, rabbit_definitions_import_https}, + {url, "https://gist.githubusercontent.com/michaelklishin/e73b0114728d9391425d0644304f264a/raw/f15642771f099c60b6fa93f75d46a4246bb47c45/upstream.definitions.json"}, + {ssl_options, [ + {log_level, error}, + {secure_renegotiate, true}, + {versions, ['tlsv1.2']}, + {ciphers, [ + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDH-ECDSA-AES256-GCM-SHA384", + "ECDH-RSA-AES256-GCM-SHA384", + "DHE-RSA-AES256-GCM-SHA384", + "DHE-DSS-AES256-GCM-SHA384", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDH-ECDSA-AES128-GCM-SHA256", + "ECDH-RSA-AES128-GCM-SHA256", + "DHE-RSA-AES128-GCM-SHA256", + "DHE-DSS-AES128-GCM-SHA256" + ]} + ]} + ]} + ]}), + rabbit_ct_helpers:run_setup_steps(Config2, rabbit_ct_broker_helpers:setup_steps()); init_per_group(Group, Config) -> Config1 = rabbit_ct_helpers:set_config(Config, [ {rmq_nodename_suffix, Group} @@ -199,6 +236,14 @@ import_on_a_booting_node_using_modern_local_filesystem_source(Config) -> {error, timeout} -> ct:fail("virtual host ~p was not imported on boot", [VHost]) end. +import_on_a_booting_node_using_public_https_source(Config) -> + VHost = <<"bunny_testbed">>, + %% verify that virtual host eventually starts + case rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_vhost, await_running_on_all_nodes, [VHost, 3000]) of + ok -> ok; + {error, timeout} -> ct:fail("virtual host ~p was not imported on boot", [VHost]) + end. + %% %% Implementation %% diff --git a/release-notes/3.9.4.md b/release-notes/3.9.4.md index 6b445fea39..eef4d5b1e1 100644 --- a/release-notes/3.9.4.md +++ b/release-notes/3.9.4.md @@ -48,6 +48,9 @@ consistent release schedule. definitions.import_backend = https definitions.https.url = https://rabbitmq.eng.megacorp.local/env-1/definitions.json + + definitions.tls.versions.1 = tlsv1.2 + definitions.tls.log_level = error ``` GitHub issue: [#3249](https://github.com/rabbitmq/rabbitmq-server/issues/3249) |
