Introduce TLS-related rabbitmq.conf settings for definition import
currently only used by the HTTPS mechanism but can be used by any other.
This commit is contained in:
parent
f3a5235408
commit
6a0058fe7c
|
@ -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]}}]}.
|
||||
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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
|
||||
%%
|
||||
|
|
|
@ -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
|
||||
%%
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue