summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Klishin <mklishin@pivotal.io>2016-10-14 07:32:40 +0800
committerMichael Klishin <mklishin@pivotal.io>2016-10-14 07:32:40 +0800
commit0454457f4ef429d6b9d0337aa43fa738da3b5d72 (patch)
treec6c8acb02f6e9b1dfc017ad90782f4b56f948ab6
parent45c728a4a5b637521a17f0472ed29a2a4187763a (diff)
parentfdd9f295d8b33a0774b3fa1f9753ff044fcfee15 (diff)
downloadrabbitmq-server-git-0454457f4ef429d6b9d0337aa43fa738da3b5d72.tar.gz
Merge branch 'master' into rabbitmq-server-486
Conflicts: src/rabbit.app.src
-rw-r--r--.gitignore1
-rw-r--r--docs/rabbitmq.conf.example16
-rw-r--r--include/rabbit_cli.hrl14
-rw-r--r--priv/schema/rabbitmq.schema25
-rw-r--r--src/rabbit.app.src7
-rw-r--r--src/rabbit.erl106
-rw-r--r--src/rabbit_control_main.erl16
-rw-r--r--src/rabbit_control_pbe.erl79
-rw-r--r--src/rabbit_mirror_queue_mode_nodes.erl36
-rw-r--r--src/rabbit_pbe.erl194
-rw-r--r--src/rabbit_vhost_limit.erl37
-rw-r--r--test/config_schema_SUITE.erl29
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq.schema980
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_amqp1_0.schema31
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_amqp.schema27
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_http.schema15
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_ldap.schema183
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_clusterer.schema58
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_management.schema203
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_metronome.schema9
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_mqtt.schema248
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_stomp.schema110
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_web_mqtt.schema44
-rw-r--r--test/config_schema_SUITE_data/schema/rabbitmq_web_stomp.schema64
-rw-r--r--test/config_schema_SUITE_data/snippets.config17
-rw-r--r--test/dynamic_ha_SUITE.erl55
-rw-r--r--test/unit_SUITE.erl279
-rw-r--r--test/unit_SUITE_data/lib/rabbit_shovel_test/ebin/rabbit_shovel_test.app46
-rw-r--r--test/unit_SUITE_data/rabbit_shovel_test.passphrase1
29 files changed, 910 insertions, 2020 deletions
diff --git a/.gitignore b/.gitignore
index c3358da939..7af1ad4260 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@
/logs/
/plugins/
/test/ct.cover.spec
+/test/config_schema_SUITE_data/schema/**
/xrefr
rabbit.d
diff --git a/docs/rabbitmq.conf.example b/docs/rabbitmq.conf.example
index 7e60c53da4..f03145b447 100644
--- a/docs/rabbitmq.conf.example
+++ b/docs/rabbitmq.conf.example
@@ -307,14 +307,14 @@
## See http://www.rabbitmq.com/clustering.html#auto-config for
## further details.
##
-# cluster_nodes.disc.rabbit = rabbit@my.host.com
-
-## You can define multiple nodes
-# cluster_nodes.disc.hare = hare@my.host.com
-
-## There can be also ram nodes.
-## Ram nodes should not be defined together with disk nodes
-# cluster_nodes.ram.rabbit = rabbit@my.host.com
+# autocluster.classic_config.nodes.node1 = rabbit1@hostname
+# autocluster.classic_config.nodes.node2 = rabbit2@hostname
+# autocluster.classic_config.nodes.node3 = rabbit3@hostname
+# autocluster.classic_config.nodes.node4 = rabbit4@hostname
+
+## This node's type can be configured. If you are not sure
+## what node type to use, always use 'disc'.
+# autocluster.classic_config.node_type = disc
## Interval (in milliseconds) at which we send keepalive messages
## to other cluster members. Note that this is not the same thing
diff --git a/include/rabbit_cli.hrl b/include/rabbit_cli.hrl
index 19cae2fc0a..53be9fcda0 100644
--- a/include/rabbit_cli.hrl
+++ b/include/rabbit_cli.hrl
@@ -31,6 +31,13 @@
-define(ONLINE_OPT, "--online").
-define(LOCAL_OPT, "--local").
+-define(DECODE_OPT, "--decode").
+-define(CIPHER_OPT, "--cipher").
+-define(HASH_OPT, "--hash").
+-define(ITERATIONS_OPT, "--iterations").
+-define(LIST_CIPHERS_OPT, "--list-ciphers").
+-define(LIST_HASHES_OPT, "--list-hashes").
+
-define(NODE_DEF(Node), {?NODE_OPT, {option, Node}}).
-define(QUIET_DEF, {?QUIET_OPT, flag}).
-define(VHOST_DEF, {?VHOST_OPT, {option, "/"}}).
@@ -47,6 +54,13 @@
-define(OFFLINE_DEF, {?OFFLINE_OPT, flag}).
-define(ONLINE_DEF, {?ONLINE_OPT, flag}).
-define(LOCAL_DEF, {?LOCAL_OPT, flag}).
+-define(DECODE_DEF, {?DECODE_OPT, flag}).
+-define(CIPHER_DEF, {?CIPHER_OPT, {option, atom_to_list(rabbit_pbe:default_cipher())}}).
+-define(HASH_DEF, {?HASH_OPT, {option, atom_to_list(rabbit_pbe:default_hash())}}).
+-define(ITERATIONS_DEF, {?ITERATIONS_OPT, {option, integer_to_list(rabbit_pbe:default_iterations())}}).
+-define(LIST_CIPHERS_DEF, {?LIST_CIPHERS_OPT, flag}).
+-define(LIST_HASHES_DEF, {?LIST_HASHES_OPT, flag}).
+
%% Subset of standartized exit codes from sysexits.h, see
%% https://github.com/rabbitmq/rabbitmq-server/issues/396 for discussion.
diff --git a/priv/schema/rabbitmq.schema b/priv/schema/rabbitmq.schema
index bf9cccbcb8..687101dd74 100644
--- a/priv/schema/rabbitmq.schema
+++ b/priv/schema/rabbitmq.schema
@@ -764,20 +764,27 @@ end}.
%%
%% {cluster_nodes, {['rabbit@my.host.com'], disc}},
-{mapping, "cluster_nodes.disc.$node", "rabbit.cluster_nodes",
+{mapping, "autocluster.classic_config.nodes.$node", "rabbit.cluster_nodes",
[{datatype, atom}]}.
-{mapping, "cluster_nodes.ram.$node", "rabbit.cluster_nodes",
- [{datatype, atom}]}.
+{mapping, "autocluster.classic_config.node_type", "rabbit.cluster_nodes", [
+ {datatype, {enum, [disc, disk, ram]}},
+ {default, disc}
+]}.
{translation, "rabbit.cluster_nodes",
fun(Conf) ->
- DiskNodes = [ V || {_, V} <- cuttlefish_variable:filter_by_prefix("cluster_nodes.disc", Conf)],
- RamNodes = [ V || {_, V} <- cuttlefish_variable:filter_by_prefix("cluster_nodes.ram", Conf)],
-
- case {DiskNodes, RamNodes} of
- {_, []} -> {DiskNodes, disc};
- {[], _} -> {RamNodes, ram}
+ Nodes = [V || {_, V} <- cuttlefish_variable:filter_by_prefix("autocluster.classic_config.nodes", Conf)],
+
+ case Nodes of
+ [] -> cuttlefish:unset();
+ Other ->
+ case cuttlefish:conf_get("autocluster.classic_config.node_type", Conf, disc) of
+ disc -> {Other, disc};
+ % Always cast to `disc`
+ disk -> {Other, disc};
+ ram -> {Other, ram}
+ end
end
end}.
diff --git a/src/rabbit.app.src b/src/rabbit.app.src
index 87401662c8..b22ef7ae5b 100644
--- a/src/rabbit.app.src
+++ b/src/rabbit.app.src
@@ -108,6 +108,13 @@
%% used by rabbit_peer_discovery_classic_config
{cluster_nodes, {[], disc}},
+ {decoder_config, [
+ {cipher, aes_cbc256},
+ {hash, sha512},
+ {iterations, 1000},
+ {passphrase, undefined}
+ ]},
+
%% rabbitmq-server-973
{lazy_queue_explicit_gc_run_operation_threshold, 250}
]}]}.
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 5db2c40b66..089fc0dd1c 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -24,7 +24,7 @@
start_fhc/0]).
-export([start/2, stop/1, prep_stop/1]).
-export([start_apps/1, stop_apps/1]).
--export([log_locations/0, config_files/0]). %% for testing and mgmt-agent
+-export([log_locations/0, config_files/0, decrypt_config/2]). %% for testing and mgmt-agent
-ifdef(TEST).
@@ -465,6 +465,38 @@ stop_and_halt() ->
start_apps(Apps) ->
app_utils:load_applications(Apps),
+
+ DecoderConfig = case application:get_env(rabbit, decoder_config) of
+ undefined ->
+ [];
+ {ok, Val} ->
+ Val
+ end,
+ PassPhrase = case proplists:get_value(passphrase, DecoderConfig) of
+ prompt ->
+ IoDevice = get_input_iodevice(),
+ io:setopts(IoDevice, [{echo, false}]),
+ PP = lists:droplast(io:get_line(IoDevice,
+ "\nPlease enter the passphrase to unlock encrypted "
+ "configuration entries.\n\nPassphrase: ")),
+ io:setopts(IoDevice, [{echo, true}]),
+ io:format(IoDevice, "~n", []),
+ PP;
+ {file, Filename} ->
+ {ok, File} = file:read_file(Filename),
+ [PP|_] = binary:split(File, [<<"\r\n">>, <<"\n">>]),
+ PP;
+ PP ->
+ PP
+ end,
+ Algo = {
+ proplists:get_value(cipher, DecoderConfig, rabbit_pbe:default_cipher()),
+ proplists:get_value(hash, DecoderConfig, rabbit_pbe:default_hash()),
+ proplists:get_value(iterations, DecoderConfig, rabbit_pbe:default_iterations()),
+ PassPhrase
+ },
+ decrypt_config(Apps, Algo),
+
OrderedApps = app_utils:app_dependency_order(Apps, false),
case lists:member(rabbit, Apps) of
false -> rabbit_boot_steps:run_boot_steps(Apps); %% plugin activation
@@ -473,6 +505,78 @@ start_apps(Apps) ->
ok = app_utils:start_applications(OrderedApps,
handle_app_error(could_not_start)).
+%% This function retrieves the correct IoDevice for requesting
+%% input. The problem with using the default IoDevice is that
+%% the Erlang shell prevents us from getting the input.
+%%
+%% Instead we therefore look for the io process used by the
+%% shell and if it can't be found (because the shell is not
+%% started e.g with -noshell) we use the 'user' process.
+%%
+%% This function will not work when either -oldshell or -noinput
+%% options are passed to erl.
+get_input_iodevice() ->
+ case whereis(user) of
+ undefined -> user;
+ User ->
+ case group:interfaces(User) of
+ [] ->
+ user;
+ [{user_drv, Drv}] ->
+ case user_drv:interfaces(Drv) of
+ [] ->
+ user;
+ [{current_group, IoDevice}] ->
+ IoDevice
+ end
+ end
+ end.
+
+decrypt_config([], _) ->
+ ok;
+decrypt_config([App|Apps], Algo) ->
+ decrypt_app(App, application:get_all_env(App), Algo),
+ decrypt_config(Apps, Algo).
+
+decrypt_app(_, [], _) ->
+ ok;
+decrypt_app(App, [{Key, Value}|Tail], Algo) ->
+ try begin
+ case decrypt(Value, Algo) of
+ Value ->
+ ok;
+ NewValue ->
+ application:set_env(App, Key, NewValue)
+ end
+ end
+ catch
+ exit:{bad_configuration, decoder_config} ->
+ exit({bad_configuration, decoder_config});
+ _:Msg ->
+ rabbit_log:info("Error while decrypting key '~p'. Please check encrypted value, passphrase, and encryption configuration~n", [Key]),
+ exit({decryption_error, {key, Key}, Msg})
+ end,
+ decrypt_app(App, Tail, Algo).
+
+decrypt({encrypted, _}, {_, _, _, undefined}) ->
+ exit({bad_configuration, decoder_config});
+decrypt({encrypted, EncValue}, {Cipher, Hash, Iterations, Password}) ->
+ rabbit_pbe:decrypt_term(Cipher, Hash, Iterations, Password, EncValue);
+decrypt(List, Algo) when is_list(List) ->
+ decrypt_list(List, Algo, []);
+decrypt(Value, _) ->
+ Value.
+
+%% We make no distinction between strings and other lists.
+%% When we receive a string, we loop through each element
+%% and ultimately return the string unmodified, as intended.
+decrypt_list([], _, Acc) ->
+ lists:reverse(Acc);
+decrypt_list([{Key, Value}|Tail], Algo, Acc) when Key =/= encrypted ->
+ decrypt_list(Tail, Algo, [{Key, decrypt(Value, Algo)}|Acc]);
+decrypt_list([Value|Tail], Algo, Acc) ->
+ decrypt_list(Tail, Algo, [decrypt(Value, Algo)|Acc]).
+
stop_apps(Apps) ->
ok = app_utils:stop_applications(
Apps, handle_app_error(error_during_shutdown)),
diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl
index f48f0349aa..1619f25494 100644
--- a/src/rabbit_control_main.erl
+++ b/src/rabbit_control_main.erl
@@ -97,7 +97,8 @@
{trace_off, [?VHOST_DEF]},
set_vm_memory_high_watermark,
set_disk_free_limit,
- help
+ help,
+ {encode, [?DECODE_DEF, ?CIPHER_DEF, ?HASH_DEF, ?ITERATIONS_DEF, ?LIST_CIPHERS_DEF, ?LIST_HASHES_DEF]}
]).
-define(GLOBAL_QUERIES,
@@ -119,7 +120,7 @@
[stop, stop_app, start_app, wait, reset, force_reset, rotate_logs,
join_cluster, change_cluster_node_type, update_cluster_nodes,
forget_cluster_node, rename_cluster_node, cluster_status, status,
- environment, eval, force_boot, help, hipe_compile]).
+ environment, eval, force_boot, help, hipe_compile, encode]).
%% [Command | {Command, DefaultTimeoutInMilliSeconds}]
-define(COMMANDS_WITH_TIMEOUT,
@@ -613,6 +614,17 @@ action(eval, Node, [Expr], _Opts, _Inform) ->
action(help, _Node, _Args, _Opts, _Inform) ->
io:format("~s", [rabbit_ctl_usage:usage()]);
+action(encode, _Node, Args, Opts, _Inform) ->
+ ListCiphers = lists:member({?LIST_CIPHERS_OPT, true}, Opts),
+ ListHashes = lists:member({?LIST_HASHES_OPT, true}, Opts),
+ Decode = lists:member({?DECODE_OPT, true}, Opts),
+ Cipher = list_to_atom(proplists:get_value(?CIPHER_OPT, Opts)),
+ Hash = list_to_atom(proplists:get_value(?HASH_OPT, Opts)),
+ Iterations = list_to_integer(proplists:get_value(?ITERATIONS_OPT, Opts)),
+
+ {_, Msg} = rabbit_control_pbe:encode(ListCiphers, ListHashes, Decode, Cipher, Hash, Iterations, Args),
+ io:format(Msg ++ "~n");
+
action(Command, Node, Args, Opts, Inform) ->
%% For backward compatibility, run commands accepting a timeout with
%% the default timeout.
diff --git a/src/rabbit_control_pbe.erl b/src/rabbit_control_pbe.erl
new file mode 100644
index 0000000000..2fa2c90a6e
--- /dev/null
+++ b/src/rabbit_control_pbe.erl
@@ -0,0 +1,79 @@
+% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License
+%% at http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and
+%% limitations under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(rabbit_control_pbe).
+
+-export([encode/7]).
+
+% for testing purposes
+-export([evaluate_input_as_term/1]).
+
+encode(ListCiphers, _ListHashes, _Decode, _Cipher, _Hash, _Iterations, _Args) when ListCiphers ->
+ {ok, io_lib:format("~p", [rabbit_pbe:supported_ciphers()])};
+
+encode(_ListCiphers, ListHashes, _Decode, _Cipher, _Hash, _Iterations, _Args) when ListHashes ->
+ {ok, io_lib:format("~p", [rabbit_pbe:supported_hashes()])};
+
+encode(_ListCiphers, _ListHashes, Decode, Cipher, Hash, Iterations, Args) ->
+ CipherExists = lists:member(Cipher, rabbit_pbe:supported_ciphers()),
+ HashExists = lists:member(Hash, rabbit_pbe:supported_hashes()),
+ encode_encrypt_decrypt(CipherExists, HashExists, Decode, Cipher, Hash, Iterations, Args).
+
+encode_encrypt_decrypt(CipherExists, _HashExists, _Decode, _Cipher, _Hash, _Iterations, _Args) when CipherExists =:= false ->
+ {error, io_lib:format("The requested cipher is not supported", [])};
+
+encode_encrypt_decrypt(_CipherExists, HashExists, _Decode, _Cipher, _Hash, _Iterations, _Args) when HashExists =:= false ->
+ {error, io_lib:format("The requested hash is not supported", [])};
+
+encode_encrypt_decrypt(_CipherExists, _HashExists, _Decode, _Cipher, _Hash, Iterations, _Args) when Iterations =< 0 ->
+ {error, io_lib:format("The requested number of iterations is incorrect", [])};
+
+encode_encrypt_decrypt(_CipherExists, _HashExists, Decode, Cipher, Hash, Iterations, Args) when length(Args) == 2, Decode =:= false ->
+ [Value, PassPhrase] = Args,
+ try begin
+ TermValue = evaluate_input_as_term(Value),
+ Result = rabbit_pbe:encrypt_term(Cipher, Hash, Iterations, list_to_binary(PassPhrase), TermValue),
+ {ok, io_lib:format("~p", [{encrypted, Result}])}
+ end
+ catch
+ _:Msg -> {error, io_lib:format("Error during cipher operation: ~p", [Msg])}
+ end;
+
+encode_encrypt_decrypt(_CipherExists, _HashExists, Decode, Cipher, Hash, Iterations, Args) when length(Args) == 2, Decode ->
+ [Value, PassPhrase] = Args,
+ try begin
+ TermValue = evaluate_input_as_term(Value),
+ TermToDecrypt = case TermValue of
+ {encrypted, EncryptedTerm} ->
+ EncryptedTerm;
+ _ ->
+ TermValue
+ end,
+ Result = rabbit_pbe:decrypt_term(Cipher, Hash, Iterations, list_to_binary(PassPhrase), TermToDecrypt),
+ {ok, io_lib:format("~p", [Result])}
+ end
+ catch
+ _:Msg -> {error, io_lib:format("Error during cipher operation: ~p", [Msg])}
+ end;
+
+encode_encrypt_decrypt(_CipherExists, _HashExists, _Decode, _Cipher, _Hash, _Iterations, _Args) ->
+ {error, io_lib:format("Please provide a value to encode/decode and a passphrase", [])}.
+
+evaluate_input_as_term(Input) ->
+ {ok,Tokens,_EndLine} = erl_scan:string(Input ++ "."),
+ {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
+ {value,TermValue,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
+ TermValue.
diff --git a/src/rabbit_mirror_queue_mode_nodes.erl b/src/rabbit_mirror_queue_mode_nodes.erl
index e63f340373..31c55722a5 100644
--- a/src/rabbit_mirror_queue_mode_nodes.erl
+++ b/src/rabbit_mirror_queue_mode_nodes.erl
@@ -32,29 +32,37 @@
description() ->
[{description, <<"Mirror queue to specified nodes">>}].
-suggested_queue_nodes(Nodes0, MNode, _SNodes, SSNodes, Poss) ->
- Nodes1 = [list_to_atom(binary_to_list(Node)) || Node <- Nodes0],
+suggested_queue_nodes(PolicyNodes0, CurrentMaster, _SNodes, SSNodes, NodesRunningRabbitMQ) ->
+ PolicyNodes1 = [list_to_atom(binary_to_list(Node)) || Node <- PolicyNodes0],
%% If the current master is not in the nodes specified, then what we want
%% to do depends on whether there are any synchronised slaves. If there
%% are then we can just kill the current master - the admin has asked for
%% a migration and we should give it to them. If there are not however
%% then we must keep the master around so as not to lose messages.
- Nodes = case SSNodes of
- [] -> lists:usort([MNode | Nodes1]);
- _ -> Nodes1
- end,
- Unavailable = Nodes -- Poss,
- Available = Nodes -- Unavailable,
- case Available of
+
+ PolicyNodes = case SSNodes of
+ [] -> lists:usort([CurrentMaster | PolicyNodes1]);
+ _ -> PolicyNodes1
+ end,
+ Unavailable = PolicyNodes -- NodesRunningRabbitMQ,
+ AvailablePolicyNodes = PolicyNodes -- Unavailable,
+ case AvailablePolicyNodes of
[] -> %% We have never heard of anything? Not much we can do but
%% keep the master alive.
- {MNode, []};
- _ -> case lists:member(MNode, Available) of
- true -> {MNode, Available -- [MNode]};
+ {CurrentMaster, []};
+ _ -> case lists:member(CurrentMaster, AvailablePolicyNodes) of
+ true -> {CurrentMaster,
+ AvailablePolicyNodes -- [CurrentMaster]};
false -> %% Make sure the new master is synced! In order to
%% get here SSNodes must not be empty.
- [NewMNode | _] = SSNodes,
- {NewMNode, Available -- [NewMNode]}
+ SyncPolicyNodes = [Node ||
+ Node <- AvailablePolicyNodes,
+ lists:member(Node, SSNodes)],
+ NewMaster = case SyncPolicyNodes of
+ [Node | _] -> Node;
+ [] -> erlang:hd(SSNodes)
+ end,
+ {NewMaster, AvailablePolicyNodes -- [NewMaster]}
end
end.
diff --git a/src/rabbit_pbe.erl b/src/rabbit_pbe.erl
new file mode 100644
index 0000000000..f4998d4a13
--- /dev/null
+++ b/src/rabbit_pbe.erl
@@ -0,0 +1,194 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License
+%% at http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and
+%% limitations under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(rabbit_pbe).
+
+-export([supported_ciphers/0, supported_hashes/0, default_cipher/0, default_hash/0, default_iterations/0]).
+-export([encrypt_term/5, decrypt_term/5]).
+-export([encrypt/5, decrypt/5]).
+
+%% Supported ciphers and hashes
+
+supported_ciphers() ->
+ proplists:get_value(ciphers, crypto:supports())
+ -- [aes_ctr, aes_ecb, des_ecb, blowfish_ecb, rc4, aes_gcm].
+
+supported_hashes() ->
+ proplists:get_value(hashs, crypto:supports())
+ -- [md4, ripemd160].
+
+%% Default encryption parameters (keep those in sync with rabbit.app.src)
+default_cipher() ->
+ aes_cbc256.
+
+default_hash() ->
+ sha512.
+
+default_iterations() ->
+ 1000.
+
+%% Encryption/decryption of arbitrary Erlang terms.
+
+encrypt_term(Cipher, Hash, Iterations, PassPhrase, Term) ->
+ encrypt(Cipher, Hash, Iterations, PassPhrase, term_to_binary(Term)).
+
+decrypt_term(Cipher, Hash, Iterations, PassPhrase, Base64Binary) ->
+ binary_to_term(decrypt(Cipher, Hash, Iterations, PassPhrase, Base64Binary)).
+
+%% The cipher for encryption is from the list of supported ciphers.
+%% The hash for generating the key from the passphrase is from the list
+%% of supported hashes. See crypto:supports/0 to obtain both lists.
+%% The key is generated by applying the hash N times with N >= 1.
+%%
+%% The encrypt/5 function returns a base64 binary and the decrypt/5
+%% function accepts that same base64 binary.
+
+-spec encrypt(crypto:block_cipher(), crypto:hash_algorithms(),
+ pos_integer(), iodata(), binary()) -> binary().
+encrypt(Cipher, Hash, Iterations, PassPhrase, ClearText) ->
+ Salt = crypto:strong_rand_bytes(16),
+ Ivec = crypto:strong_rand_bytes(iv_length(Cipher)),
+ Key = make_key(Cipher, Hash, Iterations, PassPhrase, Salt),
+ Binary = crypto:block_encrypt(Cipher, Key, Ivec, pad(Cipher, ClearText)),
+ base64:encode(<< Salt/binary, Ivec/binary, Binary/binary >>).
+
+-spec decrypt(crypto:block_cipher(), crypto:hash_algorithms(),
+ pos_integer(), iodata(), binary()) -> binary().
+decrypt(Cipher, Hash, Iterations, PassPhrase, Base64Binary) ->
+ IvLength = iv_length(Cipher),
+ << Salt:16/binary, Ivec:IvLength/binary, Binary/bits >> = base64:decode(Base64Binary),
+ Key = make_key(Cipher, Hash, Iterations, PassPhrase, Salt),
+ unpad(crypto:block_decrypt(Cipher, Key, Ivec, Binary)).
+
+%% Generate a key from a passphrase.
+
+make_key(Cipher, Hash, Iterations, PassPhrase, Salt) ->
+ Key = pbdkdf2(PassPhrase, Salt, Iterations, key_length(Cipher),
+ fun crypto:hmac/4, Hash, hash_length(Hash)),
+ if
+ Cipher =:= des3_cbc; Cipher =:= des3_cbf; Cipher =:= des3_cfb; Cipher =:= des_ede3 ->
+ << A:8/binary, B:8/binary, C:8/binary >> = Key,
+ [A, B, C];
+ true ->
+ Key
+ end.
+
+%% Functions to pad/unpad input to a multiplier of block size.
+
+pad(Cipher, Data) ->
+ BlockSize = block_size(Cipher),
+ N = BlockSize - (byte_size(Data) rem BlockSize),
+ Pad = list_to_binary(lists:duplicate(N, N)),
+ <<Data/binary, Pad/binary>>.
+
+unpad(Data) ->
+ N = binary:last(Data),
+ binary:part(Data, 0, byte_size(Data) - N).
+
+%% These functions are necessary because the current Erlang crypto interface
+%% is lacking interfaces to the following OpenSSL functions:
+%%
+%% * int EVP_MD_size(const EVP_MD *md);
+%% * int EVP_CIPHER_iv_length(const EVP_CIPHER *e);
+%% * int EVP_CIPHER_key_length(const EVP_CIPHER *e);
+%% * int EVP_CIPHER_block_size(const EVP_CIPHER *e);
+
+hash_length(md4) -> 16;
+hash_length(md5) -> 16;
+hash_length(sha) -> 20;
+hash_length(sha224) -> 28;
+hash_length(sha256) -> 32;
+hash_length(sha384) -> 48;
+hash_length(sha512) -> 64.
+
+iv_length(des_cbc) -> 8;
+iv_length(des_cfb) -> 8;
+iv_length(des3_cbc) -> 8;
+iv_length(des3_cbf) -> 8;
+iv_length(des3_cfb) -> 8;
+iv_length(des_ede3) -> 8;
+iv_length(blowfish_cbc) -> 8;
+iv_length(blowfish_cfb64) -> 8;
+iv_length(blowfish_ofb64) -> 8;
+iv_length(rc2_cbc) -> 8;
+iv_length(aes_cbc) -> 16;
+iv_length(aes_cbc128) -> 16;
+iv_length(aes_cfb8) -> 16;
+iv_length(aes_cfb128) -> 16;
+iv_length(aes_cbc256) -> 16;
+iv_length(aes_ige256) -> 32.
+
+key_length(des_cbc) -> 8;
+key_length(des_cfb) -> 8;
+key_length(des3_cbc) -> 24;
+key_length(des3_cbf) -> 24;
+key_length(des3_cfb) -> 24;
+key_length(des_ede3) -> 24;
+key_length(blowfish_cbc) -> 16;
+key_length(blowfish_cfb64) -> 16;
+key_length(blowfish_ofb64) -> 16;
+key_length(rc2_cbc) -> 16;
+key_length(aes_cbc) -> 16;
+key_length(aes_cbc128) -> 16;
+key_length(aes_cfb8) -> 16;
+key_length(aes_cfb128) -> 16;
+key_length(aes_cbc256) -> 32;
+key_length(aes_ige256) -> 16.
+
+block_size(aes_cbc256) -> 32;
+block_size(aes_cbc128) -> 32;
+block_size(aes_ige256) -> 32;
+block_size(aes_cbc) -> 32;
+block_size(_) -> 8.
+
+%% The following was taken from OTP's lib/public_key/src/pubkey_pbe.erl
+%%
+%% This is an undocumented interface to password-based encryption algorithms.
+%% These functions have been copied here to stay compatible with R16B03.
+
+%%--------------------------------------------------------------------
+-spec pbdkdf2(string(), iodata(), integer(), integer(), fun(), atom(), integer())
+ -> binary().
+%%
+%% Description: Implements password based decryption key derive function 2.
+%% Exported mainly for testing purposes.
+%%--------------------------------------------------------------------
+pbdkdf2(Password, Salt, Count, DerivedKeyLen, Prf, PrfHash, PrfOutputLen)->
+ NumBlocks = ceiling(DerivedKeyLen / PrfOutputLen),
+ NumLastBlockOctets = DerivedKeyLen - (NumBlocks - 1) * PrfOutputLen ,
+ blocks(NumBlocks, NumLastBlockOctets, 1, Password, Salt,
+ Count, Prf, PrfHash, PrfOutputLen, <<>>).
+
+blocks(1, N, Index, Password, Salt, Count, Prf, PrfHash, PrfLen, Acc) ->
+ <<XorSum:N/binary, _/binary>> = xor_sum(Password, Salt, Count, Index, Prf, PrfHash, PrfLen),
+ <<Acc/binary, XorSum/binary>>;
+blocks(NumBlocks, N, Index, Password, Salt, Count, Prf, PrfHash, PrfLen, Acc) ->
+ XorSum = xor_sum(Password, Salt, Count, Index, Prf, PrfHash, PrfLen),
+ blocks(NumBlocks -1, N, Index +1, Password, Salt, Count, Prf, PrfHash,
+ PrfLen, <<Acc/binary, XorSum/binary>>).
+
+xor_sum(Password, Salt, Count, Index, Prf, PrfHash, PrfLen) ->
+ Result = Prf(PrfHash, Password, [Salt,<<Index:32/unsigned-big-integer>>], PrfLen),
+ do_xor_sum(Prf, PrfHash, PrfLen, Result, Password, Count-1, Result).
+
+do_xor_sum(_, _, _, _, _, 0, Acc) ->
+ Acc;
+do_xor_sum(Prf, PrfHash, PrfLen, Prev, Password, Count, Acc) ->
+ Result = Prf(PrfHash, Password, Prev, PrfLen),
+ do_xor_sum(Prf, PrfHash, PrfLen, Result, Password, Count-1, crypto:exor(Acc, Result)).
+
+ceiling(Float) ->
+ erlang:round(Float + 0.5).
diff --git a/src/rabbit_vhost_limit.erl b/src/rabbit_vhost_limit.erl
index bd79f4dd45..b933c31402 100644
--- a/src/rabbit_vhost_limit.erl
+++ b/src/rabbit_vhost_limit.erl
@@ -21,12 +21,14 @@
-include("rabbit.hrl").
-export([register/0]).
--export([parse_set/2, clear/1]).
+-export([parse_set/2, set/2, clear/1]).
+-export([list/0, list/1]).
+-export([update_limit/3, clear_limit/2, get_limit/2]).
-export([validate/5, notify/4, notify_clear/3]).
-export([connection_limit/1, queue_limit/1,
is_over_queue_limit/1, is_over_connection_limit/1]).
--import(rabbit_misc, [pget/2]).
+-import(rabbit_misc, [pget/2, pget/3]).
-rabbit_boot_step({?MODULE,
[{description, "vhost limit parameters"},
@@ -57,6 +59,21 @@ connection_limit(VirtualHost) ->
queue_limit(VirtualHost) ->
get_limit(VirtualHost, <<"max-queues">>).
+-spec list() -> [{rabbit_types:vhost(), rabbit_types:infos()}].
+
+list() ->
+ case rabbit_runtime_parameters:list_component(<<"vhost-limits">>) of
+ [] -> [];
+ Params -> [ {pget(vhost, Param), pget(value, Param)}
+ || Param <- Params,
+ pget(value, Param) =/= undefined,
+ pget(name, Param) == <<"limits">> ]
+ end.
+
+-spec list(rabbit_types:vhost()) -> rabbit_types:infos().
+
+list(VHost) ->
+ rabbit_runtime_parameters:value(VHost, <<"vhost-limits">>, <<"limits">>, []).
-spec is_over_connection_limit(rabbit_types:vhost()) -> {true, non_neg_integer()} | false.
@@ -122,6 +139,22 @@ clear(VHost) ->
rabbit_runtime_parameters:clear_any(VHost, <<"vhost-limits">>,
<<"limits">>).
+update_limit(VHost, Name, Value) ->
+ OldDef = case rabbit_runtime_parameters:list(VHost, <<"vhost-limits">>) of
+ [] -> [];
+ [Param] -> pget(value, Param, [])
+ end,
+ NewDef = [{Name, Value} | lists:keydelete(Name, 1, OldDef)],
+ set(VHost, NewDef).
+
+clear_limit(VHost, Name) ->
+ OldDef = case rabbit_runtime_parameters:list(VHost, <<"vhost-limits">>) of
+ [] -> [];
+ [Param] -> pget(value, Param, [])
+ end,
+ NewDef = lists:keydelete(Name, 1, OldDef),
+ set(VHost, NewDef).
+
vhost_limit_validation() ->
[{<<"max-connections">>, fun rabbit_parameter_validation:integer/2, optional},
{<<"max-queues">>, fun rabbit_parameter_validation:integer/2, optional}].
diff --git a/test/config_schema_SUITE.erl b/test/config_schema_SUITE.erl
index 79e7220e98..09eb4678cd 100644
--- a/test/config_schema_SUITE.erl
+++ b/test/config_schema_SUITE.erl
@@ -39,7 +39,19 @@ groups() ->
init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
- rabbit_ct_helpers:run_setup_steps(Config).
+ Config1 = rabbit_ct_helpers:run_setup_steps(Config),
+ DepsDir = ?config(erlang_mk_depsdir, Config1),
+ Schemas = filelib:wildcard(DepsDir ++ "/*/priv/schema/*.schema"),
+ ct:pal("Schemas ~p~n", [Schemas]),
+ SchemaDir = filename:join(?config(data_dir, Config1), "schema"),
+ file:make_dir(SchemaDir),
+ ct:pal("Schema DIR ~p~n", [SchemaDir]),
+ [ copy_to(Schema, SchemaDir) || Schema <- Schemas ],
+ rabbit_ct_helpers:set_config(Config1, [{schema_dir, SchemaDir}]).
+
+copy_to(File, Dir) ->
+ BaseName = filename:basename(File),
+ {ok, _} = file:copy(File, Dir ++ "/" ++ BaseName).
end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config).
@@ -57,13 +69,11 @@ init_per_testcase(Testcase, Config) ->
]),
Config2 = case Testcase of
run_snippets ->
- SchemaDir = filename:join(?config(data_dir, Config1), "schema"),
ResultsDir = filename:join(?config(priv_dir, Config1), "results"),
Snippets = filename:join(?config(data_dir, Config1),
"snippets.config"),
ok = file:make_dir(ResultsDir),
rabbit_ct_helpers:set_config(Config1, [
- {schema_dir, SchemaDir},
{results_dir, ResultsDir},
{conf_snippets, Snippets}
])
@@ -89,12 +99,21 @@ run_snippets(Config) ->
run_snippets1(Config) ->
{ok, [Snippets]} = file:consult(?config(conf_snippets, Config)),
lists:map(
- fun({N, S, C, P}) -> ok = test_snippet(Config, {integer_to_list(N), S, []}, C, P);
- ({N, S, A, C, P}) -> ok = test_snippet(Config, {integer_to_list(N), S, A}, C, P)
+ 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),
passed.
+snippet_id(N) when is_integer(N) ->
+ integer_to_list(N);
+snippet_id(F) when is_float(F) ->
+ float_to_list(F);
+snippet_id(A) when is_atom(A) ->
+ atom_to_list(A);
+snippet_id(L) when is_list(L) ->
+ L.
+
test_snippet(Config, Snippet, Expected, _Plugins) ->
{ConfFile, AdvancedFile} = write_snippet(Config, Snippet),
{ok, GeneratedFile} = generate_config(Config, ConfFile, AdvancedFile),
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq.schema b/test/config_schema_SUITE_data/schema/rabbitmq.schema
deleted file mode 100644
index bf9cccbcb8..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq.schema
+++ /dev/null
@@ -1,980 +0,0 @@
-% ==============================
-% Rabbit app section
-% ==============================
-
-%%
-%% Network Connectivity
-%% ====================
-%%
-
-%% By default, RabbitMQ will listen on all interfaces, using
-%% the standard (reserved) AMQP port.
-%%
-%% {tcp_listeners, [5672]},
-%% To listen on a specific interface, provide a tuple of {IpAddress, Port}.
-%% For example, to listen only on localhost for both IPv4 and IPv6:
-%%
-%% {tcp_listeners, [{"127.0.0.1", 5672},
-%% {"[::1]", 5672}]},
-
-{mapping, "listeners.tcp", "rabbit.tcp_listeners",[
- {datatype, {enum, [none]}}
-]}.
-
-{mapping, "listeners.tcp.$name", "rabbit.tcp_listeners",[
- {datatype, [integer, ip]}
-]}.
-
-{translation, "rabbit.tcp_listeners",
-fun(Conf) ->
- case cuttlefish:conf_get("listeners.tcp", Conf, undefined) of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("listeners.tcp", Conf),
- [ V || {_, V} <- Settings ]
- end
-end}.
-
-%% SSL listeners are configured in the same fashion as TCP listeners,
-%% including the option to control the choice of interface.
-%%
-%% {ssl_listeners, [5671]},
-
-{mapping, "listeners.ssl", "rabbit.ssl_listeners",[
- {datatype, {enum, [none]}}
-]}.
-
-{mapping, "listeners.ssl.$name", "rabbit.ssl_listeners",[
- {datatype, [integer, ip]}
-]}.
-
-{translation, "rabbit.ssl_listeners",
-fun(Conf) ->
- case cuttlefish:conf_get("listeners.ssl", Conf, undefined) of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("listeners.ssl", Conf),
- [ V || {_, V} <- Settings ]
- end
-end}.
-
-%% Number of Erlang processes that will accept connections for the TCP
-%% and SSL listeners.
-%%
-%% {num_tcp_acceptors, 10},
-%% {num_ssl_acceptors, 1},
-
-{mapping, "num_acceptors.ssl", "rabbit.num_ssl_acceptors", [
- {datatype, integer}
-]}.
-
-{mapping, "num_acceptors.tcp", "rabbit.num_tcp_acceptors", [
- {datatype, integer}
-]}.
-
-
-%% Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection
-%% and SSL handshake), in milliseconds.
-%%
-%% {handshake_timeout, 10000},
-
-{mapping, "handshake_timeout", "rabbit.handshake_timeout", [
- {datatype, integer}
-]}.
-
-%% Set to 'true' to perform reverse DNS lookups when accepting a
-%% connection. Hostnames will then be shown instead of IP addresses
-%% in rabbitmqctl and the management plugin.
-%%
-%% {reverse_dns_lookups, true},
-
-{mapping, "reverse_dns_lookups", "rabbit.reverse_dns_lookups", [
- {datatype, {enum, [true, false]}}
-]}.
-
-{mapping, "erlang.K", "vm_args.+K", [
- {default, "true"},
- {level, advanced}
-]}.
-
-%%
-%% Security / AAA
-%% ==============
-%%
-
-%% The default "guest" user is only permitted to access the server
-%% via a loopback interface (e.g. localhost).
-%% {loopback_users, [<<"guest">>]},
-%%
-%% Uncomment the following line if you want to allow access to the
-%% guest user from anywhere on the network.
-%% {loopback_users, []},
-
-{mapping, "loopback_users", "rabbit.loopback_users", [
- {datatype, {enum, [none]}}
-]}.
-
-{mapping, "loopback_users.$user", "rabbit.loopback_users", [
- {datatype, atom}
-]}.
-
-{translation, "rabbit.loopback_users",
-fun(Conf) ->
- None = cuttlefish:conf_get("loopback_users", Conf, undefined),
- case None of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("loopback_users", Conf),
- [ list_to_binary(U) || {["loopback_users", U], V} <- Settings, V == true ]
- end
-end}.
-
-%% Configuring SSL.
-%% See http://www.rabbitmq.com/ssl.html for full documentation.
-%%
-%% {ssl_options, [{cacertfile, "/path/to/testca/cacert.pem"},
-%% {certfile, "/path/to/server/cert.pem"},
-%% {keyfile, "/path/to/server/key.pem"},
-%% {verify, verify_peer},
-%% {fail_if_no_peer_cert, false}]},
-
-%% SSL options section ========================================================
-
-{mapping, "ssl_allow_poodle_attack", "rabbit.ssl_allow_poodle_attack",
-[{datatype, {enum, [true, false]}}]}.
-
-{mapping, "ssl_options", "rabbit.ssl_options", [
- {datatype, {enum, [none]}}
-]}.
-
-{translation, "rabbit.ssl_options",
-fun(Conf) ->
- case cuttlefish:conf_get("ssl_options", Conf, undefined) of
- none -> [];
- _ -> cuttlefish:invalid("Invalid ssl_options")
- end
-end}.
-
-{mapping, "ssl_options.verify", "rabbit.ssl_options.verify", [
- {datatype, {enum, [verify_peer, verify_none]}}]}.
-
-{mapping, "ssl_options.fail_if_no_peer_cert", "rabbit.ssl_options.fail_if_no_peer_cert", [
- {datatype, {enum, [true, false]}}]}.
-
-{mapping, "ssl_options.cacertfile", "rabbit.ssl_options.cacertfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "ssl_options.certfile", "rabbit.ssl_options.certfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "ssl_options.cacerts.$name", "rabbit.ssl_options.cacerts",
- [{datatype, string}]}.
-
-{translation, "rabbit.ssl_options.cacerts",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("ssl_options.cacerts", Conf),
- [ list_to_binary(V) || {_, V} <- Settings ]
-end}.
-
-{mapping, "ssl_options.cert", "rabbit.ssl_options.cert",
- [{datatype, string}]}.
-
-{translation, "rabbit.ssl_options.cert",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("ssl_options.cert", Conf))
-end}.
-
-{mapping, "ssl_options.client_renegotiation", "rabbit.ssl_options.client_renegotiation",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "ssl_options.crl_check", "rabbit.ssl_options.crl_check",
- [{datatype, [{enum, [true, false, peer, best_effort]}]}]}.
-
-{mapping, "ssl_options.depth", "rabbit.ssl_options.depth",
- [{datatype, integer}, {validators, ["byte"]}]}.
-
-{mapping, "ssl_options.dh", "rabbit.ssl_options.dh",
- [{datatype, string}]}.
-
-{translation, "rabbit.ssl_options.dh",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("ssl_options.dh", Conf))
-end}.
-
-{mapping, "ssl_options.dhfile", "rabbit.ssl_options.dhfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "ssl_options.honor_cipher_order", "rabbit.ssl_options.honor_cipher_order",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "ssl_options.key.RSAPrivateKey", "rabbit.ssl_options.key",
- [{datatype, string}]}.
-
-{mapping, "ssl_options.key.DSAPrivateKey", "rabbit.ssl_options.key",
- [{datatype, string}]}.
-
-{mapping, "ssl_options.key.PrivateKeyInfo", "rabbit.ssl_options.key",
- [{datatype, string}]}.
-
-{translation, "rabbit.ssl_options.key",
-fun(Conf) ->
- case cuttlefish_variable:filter_by_prefix("ssl_options.key", Conf) of
- [{[_,_,Key], Val}|_] -> {list_to_atom(Key), list_to_binary(Val)};
- _ -> undefined
- end
-end}.
-
-{mapping, "ssl_options.keyfile", "rabbit.ssl_options.keyfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "ssl_options.log_alert", "rabbit.ssl_options.log_alert",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "ssl_options.password", "rabbit.ssl_options.password",
- [{datatype, string}]}.
-
-{mapping, "ssl_options.psk_identity", "rabbit.ssl_options.psk_identity",
- [{datatype, string}]}.
-
-{mapping, "ssl_options.reuse_sessions", "rabbit.ssl_options.reuse_sessions",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "ssl_options.secure_renegotiate", "rabbit.ssl_options.secure_renegotiate",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "ssl_options.versions.$version", "rabbit.ssl_options.versions",
- [{datatype, atom}]}.
-
-{translation, "rabbit.ssl_options.versions",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("ssl_options.versions", Conf),
- [ V || {_, V} <- Settings ]
-end}.
-
-%% ===========================================================================
-
-%% Choose the available SASL mechanism(s) to expose.
-%% The two default (built in) mechanisms are 'PLAIN' and
-%% 'AMQPLAIN'. Additional mechanisms can be added via
-%% plugins.
-%%
-%% See http://www.rabbitmq.com/authentication.html for more details.
-%%
-%% {auth_mechanisms, ['PLAIN', 'AMQPLAIN']},
-
-{mapping, "auth_mechanisms.$name", "rabbit.auth_mechanisms", [
- {datatype, atom}]}.
-
-{translation, "rabbit.auth_mechanisms",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("auth_mechanisms", Conf),
- [ V || {_, V} <- Settings ]
-end}.
-
-
-%% Select an authentication backend to use. RabbitMQ provides an
-%% internal backend in the core.
-%%
-%% {auth_backends, [rabbit_auth_backend_internal]},
-
-{translation, "rabbit.auth_backends",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("auth_backends", Conf),
- BackendModule = fun
- (internal) -> rabbit_auth_backend_internal;
- (ldap) -> rabbit_auth_backend_ldap;
- (http) -> rabbit_auth_backend_http;
- (amqp) -> rabbit_auth_backend_amqp;
- (dummy) -> rabbit_auth_backend_dummy;
- (Other) when is_atom(Other) -> Other;
- (_) -> cuttlefish:invalid("Unknown/unsupported auth backend")
- end,
- AuthBackends = [{Num, {default, BackendModule(V)}} || {["auth_backends", Num], V} <- Settings],
- AuthNBackends = [{Num, {authn, BackendModule(V)}} || {["auth_backends", Num, "authn"], V} <- Settings],
- AuthZBackends = [{Num, {authz, BackendModule(V)}} || {["auth_backends", Num, "authz"], V} <- Settings],
- Backends = lists:foldl(
- fun({NumStr, {Type, V}}, Acc) ->
- Num = case catch list_to_integer(NumStr) of
- N when is_integer(N) -> N;
- Err ->
- cuttlefish:invalid(
- iolist_to_binary(io_lib:format(
- "Auth backend position in the chain should be an integer ~p", [Err])))
- end,
- NewVal = case dict:find(Num, Acc) of
- {ok, {AuthN, AuthZ}} ->
- case {Type, AuthN, AuthZ} of
- {authn, undefined, _} ->
- {V, AuthZ};
- {authz, _, undefined} ->
- {AuthN, V};
- _ ->
- cuttlefish:invalid(
- iolist_to_binary(
- io_lib:format(
- "Auth backend already defined for the ~pth ~p backend",
- [Num, Type])))
- end;
- error ->
- case Type of
- authn -> {V, undefined};
- authz -> {undefined, V};
- default -> {V, V}
- end
- end,
- dict:store(Num, NewVal, Acc)
- end,
- dict:new(),
- AuthBackends ++ AuthNBackends ++ AuthZBackends),
- lists:map(
- fun
- ({Num, {undefined, AuthZ}}) ->
- cuttlefish:warn(
- io_lib:format(
- "Auth backend undefined for the ~pth authz backend. Using ~p",
- [Num, AuthZ])),
- {AuthZ, AuthZ};
- ({Num, {AuthN, undefined}}) ->
- cuttlefish:warn(
- io_lib:format(
- "Authz backend undefined for the ~pth authn backend. Using ~p",
- [Num, AuthN])),
- {AuthN, AuthN};
- ({_Num, {Auth, Auth}}) -> Auth;
- ({_Num, {AuthN, AuthZ}}) -> {AuthN, AuthZ}
- end,
- lists:keysort(1, dict:to_list(Backends)))
-end}.
-
-{mapping, "auth_backends.$num", "rabbit.auth_backends", [
- {datatype, atom}
-]}.
-
-{mapping, "auth_backends.$num.authn", "rabbit.auth_backends",[
- {datatype, atom}
-]}.
-
-{mapping, "auth_backends.$num.authz", "rabbit.auth_backends",[
- {datatype, atom}
-]}.
-
-%% This pertains to both the rabbitmq_auth_mechanism_ssl plugin and
-%% STOMP ssl_cert_login configurations. See the rabbitmq_stomp
-%% configuration section later in this file and the README in
-%% https://github.com/rabbitmq/rabbitmq-auth-mechanism-ssl for further
-%% details.
-%%
-%% To use the SSL cert's CN instead of its DN as the username
-%%
-%% {ssl_cert_login_from, common_name},
-
-{mapping, "ssl_cert_login_from", "rabbit.ssl_cert_login_from", [
- {datatype, {enum, [distinguished_name, common_name]}}
-]}.
-
-%% SSL handshake timeout, in milliseconds.
-%%
-%% {ssl_handshake_timeout, 5000},
-
-{mapping, "ssl_handshake_timeout", "rabbit.ssl_handshake_timeout", [
- {datatype, integer}
-]}.
-
-%% Password hashing implementation. Will only affect newly
-%% created users. To recalculate hash for an existing user
-%% it's necessary to update her password.
-%%
-%% When importing definitions exported from versions earlier
-%% than 3.6.0, it is possible to go back to MD5 (only do this
-%% as a temporary measure!) by setting this to rabbit_password_hashing_md5.
-%%
-%% To use SHA-512, set to rabbit_password_hashing_sha512.
-%%
-%% {password_hashing_module, rabbit_password_hashing_sha256},
-
-{mapping, "password_hashing_module", "rabbit.password_hashing_module", [
- {datatype, atom}
-]}.
-
-%%
-%% Default User / VHost
-%% ====================
-%%
-
-%% On first start RabbitMQ will create a vhost and a user. These
-%% config items control what gets created. See
-%% http://www.rabbitmq.com/access-control.html for further
-%% information about vhosts and access control.
-%%
-%% {default_vhost, <<"/">>},
-%% {default_user, <<"guest">>},
-%% {default_pass, <<"guest">>},
-%% {default_permissions, [<<".*">>, <<".*">>, <<".*">>]},
-
-{mapping, "default_vhost", "rabbit.default_vhost", [
- {datatype, string}
-]}.
-
-{translation, "rabbit.default_vhost",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("default_vhost", Conf))
-end}.
-
-{mapping, "default_user", "rabbit.default_user", [
- {datatype, string}
-]}.
-
-{translation, "rabbit.default_user",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("default_user", Conf))
-end}.
-
-{mapping, "default_pass", "rabbit.default_pass", [
- {datatype, string}
-]}.
-
-{translation, "rabbit.default_pass",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("default_pass", Conf))
-end}.
-
-{mapping, "default_permissions.configure", "rabbit.default_permissions", [
- {datatype, string}
-]}.
-
-{mapping, "default_permissions.read", "rabbit.default_permissions", [
- {datatype, string}
-]}.
-
-{mapping, "default_permissions.write", "rabbit.default_permissions", [
- {datatype, string}
-]}.
-
-{translation, "rabbit.default_permissions",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("default_permissions", Conf),
- Configure = proplists:get_value(["default_permissions", "configure"], Settings),
- Read = proplists:get_value(["default_permissions", "read"], Settings),
- Write = proplists:get_value(["default_permissions", "write"], Settings),
- [list_to_binary(Configure), list_to_binary(Read), list_to_binary(Write)]
-end}.
-
-%% Tags for default user
-%%
-%% For more details about tags, see the documentation for the
-%% Management Plugin at http://www.rabbitmq.com/management.html.
-%%
-%% {default_user_tags, [administrator]},
-
-{mapping, "default_user_tags.$tag", "rabbit.default_user_tags",
- [{datatype, {enum, [true, false]}}]}.
-
-{translation, "rabbit.default_user_tags",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("default_user_tags", Conf),
- [ list_to_atom(Key) || {[_,Key], Val} <- Settings, Val == true ]
-end}.
-
-%%
-%% Additional network and protocol related configuration
-%% =====================================================
-%%
-
-%% Set the default AMQP heartbeat delay (in seconds).
-%%
-%% {heartbeat, 600},
-
-{mapping, "heartbeat", "rabbit.heartbeat", [{datatype, integer}]}.
-
-%% Set the max permissible size of an AMQP frame (in bytes).
-%%
-%% {frame_max, 131072},
-
-{mapping, "frame_max", "rabbit.frame_max", [{datatype, bytesize}]}.
-
-%% Set the max frame size the server will accept before connection
-%% tuning occurs
-%%
-%% {initial_frame_max, 4096},
-
-{mapping, "initial_frame_max", "rabbit.initial_frame_max", [{datatype, bytesize}]}.
-
-%% Set the max permissible number of channels per connection.
-%% 0 means "no limit".
-%%
-%% {channel_max, 128},
-
-{mapping, "channel_max", "rabbit.channel_max", [{datatype, integer}]}.
-
-%% Customising Socket Options.
-%%
-%% See (http://www.erlang.org/doc/man/inet.html#setopts-2) for
-%% further documentation.
-%%
-%% {tcp_listen_options, [{backlog, 128},
-%% {nodelay, true},
-%% {exit_on_close, false}]},
-
-%% TCP listener section ======================================================
-
-{mapping, "tcp_listen_options", "rabbit.tcp_listen_options", [
- {datatype, {enum, [none]}}]}.
-
-{translation, "rabbit.tcp_listen_options",
-fun(Conf) ->
- case cuttlefish:conf_get("tcp_listen_options", Conf, undefined) of
- none -> [];
- _ -> cuttlefish:invalid("Invalid tcp_listen_options")
- end
-end}.
-
-{mapping, "tcp_listen_options.backlog", "rabbit.tcp_listen_options.backlog", [
- {datatype, integer}
-]}.
-
-{mapping, "tcp_listen_options.nodelay", "rabbit.tcp_listen_options.nodelay", [
- {datatype, {enum, [true, false]}}
-]}.
-
-{mapping, "tcp_listen_options.buffer", "rabbit.tcp_listen_options.buffer",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.delay_send", "rabbit.tcp_listen_options.delay_send",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "tcp_listen_options.dontroute", "rabbit.tcp_listen_options.dontroute",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "tcp_listen_options.exit_on_close", "rabbit.tcp_listen_options.exit_on_close",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "tcp_listen_options.fd", "rabbit.tcp_listen_options.fd",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.high_msgq_watermark", "rabbit.tcp_listen_options.high_msgq_watermark",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.high_watermark", "rabbit.tcp_listen_options.high_watermark",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.keepalive", "rabbit.tcp_listen_options.keepalive",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "tcp_listen_options.low_msgq_watermark", "rabbit.tcp_listen_options.low_msgq_watermark",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.low_watermark", "rabbit.tcp_listen_options.low_watermark",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.port", "rabbit.tcp_listen_options.port",
- [{datatype, integer}, {validators, ["port"]}]}.
-
-{mapping, "tcp_listen_options.priority", "rabbit.tcp_listen_options.priority",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.recbuf", "rabbit.tcp_listen_options.recbuf",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.send_timeout", "rabbit.tcp_listen_options.send_timeout",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.send_timeout_close", "rabbit.tcp_listen_options.send_timeout_close",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "tcp_listen_options.sndbuf", "rabbit.tcp_listen_options.sndbuf",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.tos", "rabbit.tcp_listen_options.tos",
- [{datatype, integer}]}.
-
-{mapping, "tcp_listen_options.linger.on", "rabbit.tcp_listen_options.linger",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "tcp_listen_options.linger.timeout", "rabbit.tcp_listen_options.linger",
- [{datatype, integer}, {validators, ["non_negative_integer"]}]}.
-
-{translation, "rabbit.tcp_listen_options.linger",
-fun(Conf) ->
- LingerOn = cuttlefish:conf_get("tcp_listen_options.linger.on", Conf, false),
- LingerTimeout = cuttlefish:conf_get("tcp_listen_options.linger.timeout", Conf, 0),
- {LingerOn, LingerTimeout}
-end}.
-
-
-%% ==========================================================================
-
-%%
-%% Resource Limits & Flow Control
-%% ==============================
-%%
-%% See http://www.rabbitmq.com/memory.html for full details.
-
-%% Memory-based Flow Control threshold.
-%%
-%% {vm_memory_high_watermark, 0.4},
-
-%% Alternatively, we can set a limit (in bytes) of RAM used by the node.
-%%
-%% {vm_memory_high_watermark, {absolute, 1073741824}},
-%%
-%% Or you can set absolute value using memory units (with RabbitMQ 3.6.0+).
-%%
-%% {vm_memory_high_watermark, {absolute, "1024M"}},
-%%
-%% Supported units suffixes:
-%%
-%% kb, KB: kibibytes (2^10 bytes)
-%% mb, MB: mebibytes (2^20)
-%% gb, GB: gibibytes (2^30)
-
-{mapping, "vm_memory_high_watermark.relative", "rabbit.vm_memory_high_watermark", [
- {datatype, float}]}.
-
-{mapping, "vm_memory_high_watermark.absolute", "rabbit.vm_memory_high_watermark", [
- {datatype, [integer, string]}]}.
-
-
-{translation, "rabbit.vm_memory_high_watermark",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("vm_memory_high_watermark", Conf),
- Absolute = proplists:get_value(["vm_memory_high_watermark", "absolute"], Settings),
- Relative = proplists:get_value(["vm_memory_high_watermark", "relative"], Settings),
- case {Absolute, Relative} of
- {undefined, undefined} -> cuttlefish:invalid("No vm watermark defined");
- {_, undefined} -> {absolute, Absolute};
- _ -> Relative
- end
-end}.
-
-%% Fraction of the high watermark limit at which queues start to
-%% page message out to disc in order to free up memory.
-%%
-%% Values greater than 0.9 can be dangerous and should be used carefully.
-%%
-%% {vm_memory_high_watermark_paging_ratio, 0.5},
-
-{mapping, "vm_memory_high_watermark_paging_ratio",
- "rabbit.vm_memory_high_watermark_paging_ratio",
- [{datatype, float}, {validators, ["less_than_1"]}]}.
-
-%% Interval (in milliseconds) at which we perform the check of the memory
-%% levels against the watermarks.
-%%
-%% {memory_monitor_interval, 2500},
-
-{mapping, "memory_monitor_interval", "rabbit.memory_monitor_interval",
- [{datatype, integer}]}.
-
-%% Set disk free limit (in bytes). Once free disk space reaches this
-%% lower bound, a disk alarm will be set - see the documentation
-%% listed above for more details.
-%%
-%% {disk_free_limit, 50000000},
-%%
-%% Or you can set it using memory units (same as in vm_memory_high_watermark)
-%% with RabbitMQ 3.6.0+.
-%% {disk_free_limit, "50MB"},
-%% {disk_free_limit, "50000kB"},
-%% {disk_free_limit, "2GB"},
-
-%% Alternatively, we can set a limit relative to total available RAM.
-%%
-%% Values lower than 1.0 can be dangerous and should be used carefully.
-%% {disk_free_limit, {mem_relative, 2.0}},
-
-{mapping, "disk_free_limit.relative", "rabbit.disk_free_limit", [
- {datatype, float}]}.
-
-{mapping, "disk_free_limit.absolute", "rabbit.disk_free_limit", [
- {datatype, [integer, string]}]}.
-
-
-{translation, "rabbit.disk_free_limit",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("disk_free_limit", Conf),
- Absolute = proplists:get_value(["disk_free_limit", "absolute"], Settings),
- Relative = proplists:get_value(["disk_free_limit", "relative"], Settings),
- case {Absolute, Relative} of
- {undefined, undefined} -> cuttlefish:invalid("No disk limit defined");
- {_, undefined} -> Absolute;
- _ -> {mem_relative, Relative}
- end
-end}.
-
-%%
-%% Clustering
-%% =====================
-%%
-
-%% How to respond to cluster partitions.
-%% See http://www.rabbitmq.com/partitions.html for further details.
-%%
-%% {cluster_partition_handling, ignore},
-
-{mapping, "cluster_partition_handling", "rabbit.cluster_partition_handling",
- [{datatype, {enum, [ignore, pause_minority, autoheal, pause_if_all_down]}}]}.
-
-{mapping, "cluster_partition_handling.pause_if_all_down.recover",
- "rabbit.cluster_partition_handling",
- [{datatype, {enum, [ignore, autoheal]}}]}.
-
-{mapping, "cluster_partition_handling.pause_if_all_down.nodes.$name",
- "rabbit.cluster_partition_handling",
- [{datatype, atom}]}.
-
-{translation, "rabbit.cluster_partition_handling",
-fun(Conf) ->
- case cuttlefish:conf_get("cluster_partition_handling", Conf) of
- pause_if_all_down ->
- PauseIfAllDownNodes = cuttlefish_variable:filter_by_prefix(
- "cluster_partition_handling.pause_if_all_down.nodes",
- Conf),
- case PauseIfAllDownNodes of
- [] ->
- cuttlefish:invalid("Nodes required for pause_if_all_down");
- _ ->
- Nodes = [ V || {K,V} <- PauseIfAllDownNodes ],
- PauseIfAllDownRecover = cuttlefish:conf_get(
- "cluster_partition_handling.pause_if_all_down.recover",
- Conf),
- case PauseIfAllDownRecover of
- Recover when Recover == ignore; Recover == autoheal ->
- {pause_if_all_down, Nodes, Recover};
- Invalid ->
- cuttlefish:invalid("Recover strategy required for pause_if_all_down")
- end
- end;
- Other -> Other
- end
-end}.
-
-%% Mirror sync batch size, in messages. Increasing this will speed
-%% up syncing but total batch size in bytes must not exceed 2 GiB.
-%% Available in RabbitMQ 3.6.0 or later.
-%%
-%% {mirroring_sync_batch_size, 4096},
-
-{mapping, "mirroring_sync_batch_size", "rabbit.mirroring_sync_batch_size",
- [{datatype, bytesize}, {validators, ["size_less_than_2G"]}]}.
-
-%% Make clustering happen *automatically* at startup - only applied
-%% to nodes that have just been reset or started for the first time.
-%% See http://www.rabbitmq.com/clustering.html#auto-config for
-%% further details.
-%%
-%% {cluster_nodes, {['rabbit@my.host.com'], disc}},
-
-{mapping, "cluster_nodes.disc.$node", "rabbit.cluster_nodes",
- [{datatype, atom}]}.
-
-{mapping, "cluster_nodes.ram.$node", "rabbit.cluster_nodes",
- [{datatype, atom}]}.
-
-{translation, "rabbit.cluster_nodes",
-fun(Conf) ->
- DiskNodes = [ V || {_, V} <- cuttlefish_variable:filter_by_prefix("cluster_nodes.disc", Conf)],
- RamNodes = [ V || {_, V} <- cuttlefish_variable:filter_by_prefix("cluster_nodes.ram", Conf)],
-
- case {DiskNodes, RamNodes} of
- {_, []} -> {DiskNodes, disc};
- {[], _} -> {RamNodes, ram}
- end
-end}.
-
-
-%% Interval (in milliseconds) at which we send keepalive messages
-%% to other cluster members. Note that this is not the same thing
-%% as net_ticktime; missed keepalive messages will not cause nodes
-%% to be considered down.
-%%
-%% {cluster_keepalive_interval, 10000},
-
-{mapping, "cluster_keepalive_interval", "rabbit.cluster_keepalive_interval",
- [{datatype, integer}]}.
-
-
-{mapping, "queue_master_locator", "rabbit.queue_master_locator",
- [{datatype, string}]}.
-
-{translation, "rabbit.queue_master_locator",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("queue_master_locator", Conf))
-end}.
-
-%%
-%% Statistics Collection
-%% =====================
-%%
-
-%% Set (internal) statistics collection granularity.
-%%
-%% {collect_statistics, none},
-
-{mapping, "collect_statistics", "rabbit.collect_statistics",
- [{datatype, {enum, [none, coarse, fine]}}]}.
-
-%% Statistics collection interval (in milliseconds). Increasing
-%% this will reduce the load on management database.
-%%
-%% {collect_statistics_interval, 5000},
-
-{mapping, "collect_statistics_interval", "rabbit.collect_statistics_interval",
- [{datatype, integer}]}.
-
-%%
-%% Misc/Advanced Options
-%% =====================
-%%
-%% NB: Change these only if you understand what you are doing!
-%%
-
-%% Explicitly enable/disable hipe compilation.
-%%
-%% {hipe_compile, true},
-
-{mapping, "hipe_compile", "rabbit.hipe_compile",
- [{datatype, {enum, [true, false]}}]}.
-
-%% Timeout used when waiting for Mnesia tables in a cluster to
-%% become available.
-%%
-%% {mnesia_table_loading_timeout, 30000},
-
-{mapping, "mnesia_table_loading_timeout", "rabbit.mnesia_table_loading_timeout",
- [{datatype, integer}]}.
-
-%% Size in bytes below which to embed messages in the queue index. See
-%% http://www.rabbitmq.com/persistence-conf.html
-%%
-%% {queue_index_embed_msgs_below, 4096}
-
-{mapping, "queue_index_embed_msgs_below", "rabbit.queue_index_embed_msgs_below",
- [{datatype, bytesize}]}.
-
-% ==========================
-% Lager section
-% ==========================
-
-{mapping, "log.dir", "lager.log_root", [
- {datatype, string},
- {validators, ["dir_writable"]}]}.
-
-{mapping, "log.console", "lager.handlers", [
- {datatype, {enum, [true, false]}}
-]}.
-
-{mapping, "log.syslog", "lager.handlers", [
- {datatype, {enum, [true, false]}}
-]}.
-{mapping, "log.file", "lager.handlers", [
- {datatype, [{enum, [false]}, string]}
-]}.
-
-{mapping, "log.file.level", "lager.handlers", [
- {datatype, {enum, [debug, info, warning, error]}}
-]}.
-{mapping, "log.$handler.level", "lager.handlers", [
- {datatype, {enum, [debug, info, warning, error]}}
-]}.
-{mapping, "log.file.rotation.date", "lager.handlers", [
- {datatype, string}
-]}.
-{mapping, "log.file.rotation.size", "lager.handlers", [
- {datatype, integer}
-]}.
-{mapping, "log.file.rotation.count", "lager.handlers", [
- {datatype, integer}
-]}.
-
-{mapping, "log.syslog.identity", "lager.handlers", [
- {datatype, string}
-]}.
-{mapping, "log.syslog.facility", "lager.handlers", [
- {datatype, atom}
-]}.
-
-{translation, "lager.handlers",
-fun(Conf) ->
- ConsoleHandler = case cuttlefish:conf_get("log.console", Conf, false) of
- true ->
- ConsoleLevel = cuttlefish:conf_get("log.console.level", Conf, info),
- [{lager_console_backend, ConsoleLevel}];
- false -> []
- end,
- FileHandler = case cuttlefish:conf_get("log.file", Conf, false) of
- false -> [];
- File ->
- FileLevel = cuttlefish:conf_get("log.file.level", Conf, info),
- RotationDate = cuttlefish:conf_get("log.file.rotation.date", Conf, ""),
- RotationSize = cuttlefish:conf_get("log.file.rotation.size", Conf, 0),
- RotationCount = cuttlefish:conf_get("log.file.rotation.count", Conf, 10),
- [{lager_file_backend, [{file, File},
- {level, FileLevel},
- {date, RotationDate},
- {size, RotationSize},
- {count, RotationCount}]}]
- end,
- SyslogHandler = case cuttlefish:conf_get("log.syslog", Conf, false) of
- false -> [];
- true ->
- SyslogLevel = cuttlefish:conf_get("log.syslog.level", Conf, info),
- Identity = cuttlefish:conf_get("log.syslog.identity", Conf),
- Facility = cuttlefish:conf_get("log.syslog.facility", Conf),
- [{lager_syslog_backend, [Identity, Facility, SyslogLevel]}]
- end,
- case ConsoleHandler ++ FileHandler ++ SyslogHandler of
- [] -> undefined;
- Other -> Other
- end
-end}.
-
-
-% ===============================
-% Validators
-% ===============================
-
-{validator, "size_less_than_2G", "Byte size should be less than 2G and greater than 0",
-fun(Size) when is_integer(Size) ->
- Size > 0 andalso Size < 2147483648
-end}.
-
-{validator, "less_than_1", "Flooat is not beetween 0 and 1",
-fun(Float) when is_float(Float) ->
- Float > 0 andalso Float < 1
-end}.
-
-{validator, "port", "Invalid port number",
-fun(Port) when is_integer(Port) ->
- Port > 0 andalso Port < 65535
-end}.
-
-{validator, "byte", "Integer is not 0<i<255",
-fun(Int) when is_integer(Int) ->
- Int > 0 andalso Int < 255
-end}.
-
-{validator, "dir_writable", "Cannot create file in dir",
-fun(Dir) ->
- TestFile = filename:join(Dir, "test_file"),
- file:delete(TestFile),
- Res = ok == file:write_file(TestFile, <<"test">>),
- file:delete(TestFile),
- Res
-end}.
-
-{validator, "file_accessible", "file doesnt exist or unaccessible",
-fun(File) ->
- ReadFile = file:read_file_info(File),
- element(1, ReadFile) == ok
-end}.
-
-{validator, "is_ip", "string is a valid IP address",
-fun(IpStr) ->
- Res = inet:parse_address(IpStr),
- element(1, Res) == ok
-end}.
-
-{validator, "non_negative_integer", "number should be greater or equal to zero",
-fun(Int) when is_integer(Int) ->
- Int >= 0
-end}.
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_amqp1_0.schema b/test/config_schema_SUITE_data/schema/rabbitmq_amqp1_0.schema
deleted file mode 100644
index e6cfb68262..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_amqp1_0.schema
+++ /dev/null
@@ -1,31 +0,0 @@
-%% ----------------------------------------------------------------------------
-%% RabbitMQ AMQP 1.0 Support
-%%
-%% See https://github.com/rabbitmq/rabbitmq-amqp1.0/blob/stable/README.md
-%% for details
-%% ----------------------------------------------------------------------------
-
-% {rabbitmq_amqp1_0,[
-%% Connections that are not authenticated with SASL will connect as this
-%% account. See the README for more information.
-%%
-%% Please note that setting this will allow clients to connect without
-%% authenticating!
-%%
-%% {default_user, "guest"},
-{mapping, "amqp1_0.default_user", "rabbitmq_amqp1_0.default_user",
- [{datatype, [{enum, [none]}, string]}]}.
-%% Enable protocol strict mode. See the README for more information.
-%%
-%% {protocol_strict_mode, false}
-% ]},
-{mapping, "amqp1_0.protocol_strict_mode", "rabbitmq_amqp1_0.protocol_strict_mode",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "amqp1_0.default_vhost", "rabbitmq_amqp1_0.default_vhost",
- [{datatype, string}]}.
-
-{translation , "rabbitmq_amqp1_0.default_vhost",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("amqp1_0.default_vhost", Conf))
-end}. \ No newline at end of file
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_amqp.schema b/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_amqp.schema
deleted file mode 100644
index a30efb6c03..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_amqp.schema
+++ /dev/null
@@ -1,27 +0,0 @@
-{mapping, "rabbitmq_auth_backend_amqp.username", "rabbitmq_auth_backend_amqp.username",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_auth_backend_amqp.username",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("rabbitmq_auth_backend_amqp.username", Conf))
-end}.
-
-{mapping, "rabbitmq_auth_backend_amqp.vhost", "rabbitmq_auth_backend_amqp.vhost",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_auth_backend_amqp.vhost",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("rabbitmq_auth_backend_amqp.vhost", Conf))
-end}.
-
-{mapping, "rabbitmq_auth_backend_amqp.exchange", "rabbitmq_auth_backend_amqp.exchange",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_auth_backend_amqp.exchange",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("rabbitmq_auth_backend_amqp.exchange", Conf))
-end}.
-
-
-{mapping, "rabbitmq_auth_backend_amqp.timeout", "rabbitmq_auth_backend_amqp.timeout",
- [{datatype, [{enum, [infinity]}, integer]}]}.
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_http.schema b/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_http.schema
deleted file mode 100644
index f10eb6710b..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_http.schema
+++ /dev/null
@@ -1,15 +0,0 @@
-
-%% ==========================================================================
-%% ----------------------------------------------------------------------------
-%% RabbitMQ HTTP Authorization
-%%
-%% ----------------------------------------------------------------------------
-
-{mapping, "rabbitmq_auth_backend_http.user_path", "rabbitmq_auth_backend_http.user_path",
- [{datatype, string}, {validators, ["uri"]}]}.
-
-{mapping, "rabbitmq_auth_backend_http.vhost_path", "rabbitmq_auth_backend_http.vhost_path",
- [{datatype, string}, {validators, ["uri"]}]}.
-
-{mapping, "rabbitmq_auth_backend_http.resource_path", "rabbitmq_auth_backend_http.resource_path",
- [{datatype, string}, {validators, ["uri"]}]}.
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_ldap.schema b/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_ldap.schema
deleted file mode 100644
index 334fd014c1..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_auth_backend_ldap.schema
+++ /dev/null
@@ -1,183 +0,0 @@
-%% ----------------------------------------------------------------------------
-%% RabbitMQ LDAP Plugin
-%%
-%% See http://www.rabbitmq.com/ldap.html for details.
-%%
-%% ----------------------------------------------------------------------------
-
-% {rabbitmq_auth_backend_ldap,
-% [
-%%
-%% Connecting to the LDAP server(s)
-%% ================================
-%%
-
-%% Specify servers to bind to. You *must* set this in order for the plugin
-%% to work properly.
-%%
-%% {servers, ["your-server-name-goes-here"]},
-
-{mapping, "rabbitmq_auth_backend_ldap.servers", "rabbitmq_auth_backend_ldap.servers",
- [{datatype, {enum, [none]}}]}.
-
-{mapping, "rabbitmq_auth_backend_ldap.servers.$server", "rabbitmq_auth_backend_ldap.servers",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_auth_backend_ldap.servers",
-fun(Conf) ->
- case cuttlefish:conf_get("rabbitmq_auth_backend_ldap.servers", Conf, undefined) of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("rabbitmq_auth_backend_ldap.servers", Conf),
- [ V || {_, V} <- Settings ]
- end
-end}.
-
-%% Connect to the LDAP server using SSL
-%%
-%% {use_ssl, false},
-
-{mapping, "rabbitmq_auth_backend_ldap.use_ssl", "rabbitmq_auth_backend_ldap.use_ssl",
- [{datatype, {enum, [true, false]}}]}.
-
-%% Specify the LDAP port to connect to
-%%
-%% {port, 389},
-
-{mapping, "rabbitmq_auth_backend_ldap.port", "rabbitmq_auth_backend_ldap.port",
- [{datatype, integer}]}.
-
-%% LDAP connection timeout, in milliseconds or 'infinity'
-%%
-%% {timeout, infinity},
-
-{mapping, "rabbitmq_auth_backend_ldap.timeout", "rabbitmq_auth_backend_ldap.timeout",
- [{datatype, [integer, {atom, infinity}]}]}.
-
-%% Enable logging of LDAP queries.
-%% One of
-%% - false (no logging is performed)
-%% - true (verbose logging of the logic used by the plugin)
-%% - network (as true, but additionally logs LDAP network traffic)
-%%
-%% Defaults to false.
-%%
-%% {log, false},
-
-{mapping, "rabbitmq_auth_backend_ldap.log", "rabbitmq_auth_backend_ldap.log",
- [{datatype, {enum, [true, false, network]}}]}.
-
-%%
-%% Authentication
-%% ==============
-%%
-
-%% Pattern to convert the username given through AMQP to a DN before
-%% binding
-%%
-%% {user_dn_pattern, "cn=${username},ou=People,dc=example,dc=com"},
-
-{mapping, "rabbitmq_auth_backend_ldap.user_dn_pattern", "rabbitmq_auth_backend_ldap.user_dn_pattern",
- [{datatype, string}]}.
-
-%% Alternatively, you can convert a username to a Distinguished
-%% Name via an LDAP lookup after binding. See the documentation for
-%% full details.
-
-%% When converting a username to a dn via a lookup, set these to
-%% the name of the attribute that represents the user name, and the
-%% base DN for the lookup query.
-%%
-%% {dn_lookup_attribute, "userPrincipalName"},
-%% {dn_lookup_base, "DC=gopivotal,DC=com"},
-
-{mapping, "rabbitmq_auth_backend_ldap.dn_lookup_attribute", "rabbitmq_auth_backend_ldap.dn_lookup_attribute",
- [{datatype, [{enum, [none]}, string]}]}.
-
-{mapping, "rabbitmq_auth_backend_ldap.dn_lookup_base", "rabbitmq_auth_backend_ldap.dn_lookup_base",
- [{datatype, [{enum, [none]}, string]}]}.
-
-{mapping, "rabbitmq_auth_backend_ldap.dn_lookup_bind", "rabbitmq_auth_backend_ldap.dn_lookup_bind",
- [{datatype, [{enum, [as_user]}]}]}.
-
-{mapping, "rabbitmq_auth_backend_ldap.dn_lookup_bind.user_dn", "rabbitmq_auth_backend_ldap.dn_lookup_bind",
- [{datatype, [string]}]}.
-
-{mapping, "rabbitmq_auth_backend_ldap.dn_lookup_bind.password", "rabbitmq_auth_backend_ldap.dn_lookup_bind",
- [{datatype, [string]}]}.
-
-{translation, "rabbitmq_auth_backend_ldap.dn_lookup_bind",
-fun(Conf) ->
- case cuttlefish:conf_get("rabbitmq_auth_backend_ldap.dn_lookup_bind", Conf, undefined) of
- as_user -> as_user;
- _ ->
- User = cuttlefish:conf_get("rabbitmq_auth_backend_ldap.dn_lookup_bind.user_dn", Conf),
- Pass = cuttlefish:conf_get("rabbitmq_auth_backend_ldap.dn_lookup_bind.password", Conf),
- case {User, Pass} of
- {undefined, _} -> as_user;
- {_, undefined} -> as_user;
- _ -> {User, Pass}
- end
- end
-end}.
-
-%% Controls how to bind for authorisation queries and also to
-%% retrieve the details of users logging in without presenting a
-%% password (e.g., SASL EXTERNAL).
-%% One of
-%% - as_user (to bind as the authenticated user - requires a password)
-%% - anon (to bind anonymously)
-%% - {UserDN, Password} (to bind with a specified user name and password)
-%%
-%% Defaults to 'as_user'.
-%%
-%% {other_bind, as_user},
-
-{mapping, "rabbitmq_auth_backend_ldap.other_bind", "rabbitmq_auth_backend_ldap.other_bind",
- [{datatype, {enum, [as_user, anon]}}]}.
-
-{mapping, "rabbitmq_auth_backend_ldap.other_bind.user_dn", "rabbitmq_auth_backend_ldap.other_bind",
- [{datatype, string}]}.
-
-{mapping, "rabbitmq_auth_backend_ldap.other_bind.password", "rabbitmq_auth_backend_ldap.other_bind",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_auth_backend_ldap.other_bind",
-fun(Conf) ->
- case cuttlefish:conf_get("rabbitmq_auth_backend_ldap.other_bind", Conf, undefined) of
- as_user -> as_user;
- anon -> anon;
- _ ->
- User = cuttlefish:conf_get("rabbitmq_auth_backend_ldap.other_bind.user_dn", Conf),
- Pass = cuttlefish:conf_get("rabbitmq_auth_backend_ldap.other_bind.password", Conf),
- case {User, Pass} of
- {undefined, _} -> as_user;
- {_, undefined} -> as_user;
- _ -> {User, Pass}
- end
- end
-end}.
-
-%%
-%% Authorisation
-%% =============
-%%
-
-%% The LDAP plugin can perform a variety of queries against your
-%% LDAP server to determine questions of authorisation. See
-%% http://www.rabbitmq.com/ldap.html#authorisation for more
-%% information.
-
-%% Set the query to use when determining vhost access
-%%
-%% {vhost_access_query, {in_group,
-%% "ou=${vhost}-users,ou=vhosts,dc=example,dc=com"}},
-
-%% Set the query to use when determining resource (e.g., queue) access
-%%
-%% {resource_access_query, {constant, true}},
-
-%% Set queries to determine which tags a user has
-%%
-%% {tag_queries, []}
-% ]},
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_clusterer.schema b/test/config_schema_SUITE_data/schema/rabbitmq_clusterer.schema
deleted file mode 100644
index ba127f00c1..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_clusterer.schema
+++ /dev/null
@@ -1,58 +0,0 @@
-{mapping, "clusterer.config", "rabbitmq_clusterer.config",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{translation, "rabbitmq_clusterer.config",
-fun(Conf) ->
- case cuttlefish:conf_get("clusterer.config", Conf, undefined) of
- String when is_list(String) ->
- case cuttlefish_variable:filter_by_prefix("clusterer", Conf) of
- [{["clusterer", "config"], String}] -> String;
- _ -> cuttlefish:invalid("Config for clusterer defined in "++
- String ++ " file. " ++
- "All other clusterer configurations should be removed")
- end;
- _ -> []
- end
-end}.
-
-{mapping, "clusterer.version", "rabbitmq_clusterer.config.version",
- [{datatype, integer}]}.
-
-{mapping, "clusterer.nodes.$node", "rabbitmq_clusterer.config.nodes",
- [{datatype, atom}]}.
-
-{mapping, "clusterer.nodes.ram.$node", "rabbitmq_clusterer.config.nodes",
- [{datatype, atom}]}.
-
-{mapping, "clusterer.nodes.disk.$node", "rabbitmq_clusterer.config.nodes",
- [{datatype, atom}]}.
-
-{mapping, "clusterer.nodes.disc.$node", "rabbitmq_clusterer.config.nodes",
- [{datatype, atom}]}.
-
-{translation, "rabbitmq_clusterer.config.nodes",
-fun(Conf) ->
- DiskNodes = cuttlefish_variable:filter_by_prefix("clusterer.nodes", Conf)
- ++ cuttlefish_variable:filter_by_prefix("clusterer.nodes.disk", Conf)
- ++ cuttlefish_variable:filter_by_prefix("clusterer.nodes.disc", Conf),
- RamNodes = cuttlefish_variable:filter_by_prefix("clusterer.nodes.ram", Conf),
- [{Node, disk} || {_, Node} <- DiskNodes] ++ [{Node, ram} || Node <- RamNodes]
-end}.
-
-{mapping, "clusterer.gospel", "rabbitmq_clusterer.config.gospel",
- [{datatype, {enum, [reset]}}]}.
-
-{mapping, "clusterer.gospel.node", "rabbitmq_clusterer.config.gospel",
- [{datatype, atom}]}.
-
-{translation, "rabbitmq_clusterer.config.gospel",
-fun(Conf) ->
- case cuttlefish:conf_get("clusterer.gospel", Conf, undefined) of
- reset -> reset;
- _ ->
- {node, cuttlefish:conf_get("clusterer.gospel.node", Conf)}
- end
-end}.
-
-
-
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_management.schema b/test/config_schema_SUITE_data/schema/rabbitmq_management.schema
deleted file mode 100644
index 7ac6d21b93..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_management.schema
+++ /dev/null
@@ -1,203 +0,0 @@
-%% ----------------------------------------------------------------------------
-%% RabbitMQ Management Plugin
-%%
-%% See http://www.rabbitmq.com/management.html for details
-%% ----------------------------------------------------------------------------
-
- % {rabbitmq_management,
- % [%% Pre-Load schema definitions from the following JSON file. See
-%% http://www.rabbitmq.com/management.html#load-definitions
-%%
-%% {load_definitions, "/path/to/schema.json"},
-{mapping, "management.load_definitions", "rabbitmq_management.load_definitions",
- [{datatype, string},
- {validators, ["file_accessible"]}]}.
-
-%% Log all requests to the management HTTP API to a file.
-%%
-%% {http_log_dir, "/path/to/access.log"},
-
-{mapping, "management.http_log_dir", "rabbitmq_management.http_log_dir",
- [{datatype, string}]}.
-
-
-%% Change the port on which the HTTP listener listens,
-%% specifying an interface for the web server to bind to.
-%% Also set the listener to use SSL and provide SSL options.
-%%
-%% {listener, [{port, 12345},
-%% {ip, "127.0.0.1"},
-%% {ssl, true},
-%% {ssl_opts, [{cacertfile, "/path/to/cacert.pem"},
-%% {certfile, "/path/to/cert.pem"},
-%% {keyfile, "/path/to/key.pem"}]}]},
-
-{mapping, "management.listener.port", "rabbitmq_management.listener.port",
- [{datatype, integer}]}.
-
-{mapping, "management.listener.ip", "rabbitmq_management.listener.ip",
- [{datatype, string},
- {validators, ["is_ip"]}]}.
-
-{mapping, "management.listener.ssl", "rabbitmq_management.listener.ssl",
- [{datatype, {enum, [true, false]}}]}.
-
-
-%% SSL options section ========================================================
-
-{mapping, "management.listener.ssl_opts", "rabbitmq_management.listener.ssl_opts", [
- {datatype, {enum, [none]}}
-]}.
-
-{translation, "rabbitmq_management.listener.ssl_opts",
-fun(Conf) ->
- case cuttlefish:conf_get("management.listener.ssl_opts", Conf, undefined) of
- none -> [];
- _ -> cuttlefish:invalid("Invalid management.listener.ssl_opts")
- end
-end}.
-
-{mapping, "management.listener.ssl_opts.verify", "rabbitmq_management.listener.ssl_opts.verify", [
- {datatype, {enum, [verify_peer, verify_none]}}]}.
-
-{mapping, "management.listener.ssl_opts.fail_if_no_peer_cert", "rabbitmq_management.listener.ssl_opts.fail_if_no_peer_cert", [
- {datatype, {enum, [true, false]}}]}.
-
-{mapping, "management.listener.ssl_opts.cacertfile", "rabbitmq_management.listener.ssl_opts.cacertfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "management.listener.ssl_opts.certfile", "rabbitmq_management.listener.ssl_opts.certfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "management.listener.ssl_opts.cacerts.$name", "rabbitmq_management.listener.ssl_opts.cacerts",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_management.listener.ssl_opts.cacerts",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("management.listener.ssl_opts.cacerts", Conf),
- [ list_to_binary(V) || {_, V} <- Settings ]
-end}.
-
-{mapping, "management.listener.ssl_opts.cert", "rabbitmq_management.listener.ssl_opts.cert",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_management.listener.ssl_opts.cert",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("management.listener.ssl_opts.cert", Conf))
-end}.
-
-{mapping, "management.listener.ssl_opts.client_renegotiation", "rabbitmq_management.listener.ssl_opts.client_renegotiation",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "management.listener.ssl_opts.crl_check", "rabbitmq_management.listener.ssl_opts.crl_check",
- [{datatype, [{enum, [true, false, peer, best_effort]}]}]}.
-
-{mapping, "management.listener.ssl_opts.depth", "rabbitmq_management.listener.ssl_opts.depth",
- [{datatype, integer}, {validators, ["byte"]}]}.
-
-{mapping, "management.listener.ssl_opts.dh", "rabbitmq_management.listener.ssl_opts.dh",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_management.listener.ssl_opts.dh",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("management.listener.ssl_opts.dh", Conf))
-end}.
-
-{mapping, "management.listener.ssl_opts.dhfile", "rabbitmq_management.listener.ssl_opts.dhfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "management.listener.ssl_opts.honor_cipher_order", "rabbitmq_management.listener.ssl_opts.honor_cipher_order",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "management.listener.ssl_opts.key.RSAPrivateKey", "rabbitmq_management.listener.ssl_opts.key",
- [{datatype, string}]}.
-
-{mapping, "management.listener.ssl_opts.key.DSAPrivateKey", "rabbitmq_management.listener.ssl_opts.key",
- [{datatype, string}]}.
-
-{mapping, "management.listener.ssl_opts.key.PrivateKeyInfo", "rabbitmq_management.listener.ssl_opts.key",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_management.listener.ssl_opts.key",
-fun(Conf) ->
- case cuttlefish_variable:filter_by_prefix("management.listener.ssl_opts.key", Conf) of
- [{[_,_,Key], Val}|_] -> {list_to_atom(Key), list_to_binary(Val)};
- _ -> undefined
- end
-end}.
-
-{mapping, "management.listener.ssl_opts.keyfile", "rabbitmq_management.listener.ssl_opts.keyfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-
-{mapping, "management.listener.ssl_opts.log_alert", "rabbitmq_management.listener.ssl_opts.log_alert",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "management.listener.ssl_opts.password", "rabbitmq_management.listener.ssl_opts.password",
- [{datatype, string}]}.
-
-{mapping, "management.listener.ssl_opts.psk_identity", "rabbitmq_management.listener.ssl_opts.psk_identity",
- [{datatype, string}]}.
-
-{mapping, "management.listener.ssl_opts.reuse_sessions", "rabbitmq_management.listener.ssl_opts.reuse_sessions",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "management.listener.ssl_opts.secure_renegotiate", "rabbitmq_management.listener.ssl_opts.secure_renegotiate",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "management.listener.ssl_opts.versions.$version", "rabbitmq_management.listener.ssl_opts.versions",
- [{datatype, atom}]}.
-
-{translation, "rabbitmq_management.listener.ssl_opts.versions",
-fun(Conf) ->
- Settings = cuttlefish_variable:filter_by_prefix("management.listener.ssl_opts.versions", Conf),
- [ V || {_, V} <- Settings ]
-end}.
-
-%% ===========================================================================
-
-
-%% One of 'basic', 'detailed' or 'none'. See
-%% http://www.rabbitmq.com/management.html#fine-stats for more details.
-%% {rates_mode, basic},
-{mapping, "management.rates_mode", "rabbitmq_management.rates_mode",
- [{datatype, {enum, [basic, detailed, none]}}]}.
-
-%% Configure how long aggregated data (such as message rates and queue
-%% lengths) is retained. Please read the plugin's documentation in
-%% http://www.rabbitmq.com/management.html#configuration for more
-%% details.
-%%
-%% {sample_retention_policies,
-%% [{global, [{60, 5}, {3600, 60}, {86400, 1200}]},
-%% {basic, [{60, 5}, {3600, 60}]},
-%% {detailed, [{10, 5}]}]}
-% ]},
-
-{mapping, "management.sample_retention_policies.$section.$interval",
- "rabbitmq_management.sample_retention_policies",
- [{datatype, integer}]}.
-
-{translation, "rabbitmq_management.sample_retention_policies",
-fun(Conf) ->
- Global = cuttlefish_variable:filter_by_prefix("management.sample_retention_policies.global", Conf),
- Basic = cuttlefish_variable:filter_by_prefix("management.sample_retention_policies.basic", Conf),
- Detailed = cuttlefish_variable:filter_by_prefix("management.sample_retention_policies.detailed", Conf),
- TranslateKey = fun("minute") -> 60;
- ("hour") -> 3600;
- ("day") -> 86400;
- (Other) -> list_to_integer(Other)
- end,
- TranslatePolicy = fun(Section) ->
- [ {TranslateKey(Key), Val} || {[_,_,_,Key], Val} <- Section ]
- end,
- [{global, TranslatePolicy(Global)},
- {basic, TranslatePolicy(Basic)},
- {detailed, TranslatePolicy(Detailed)}]
-end}.
-
-
-{validator, "is_dir", "is not directory",
-fun(File) ->
- ReadFile = file:list_dir(File),
- element(1, ReadFile) == ok
-end}.
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_metronome.schema b/test/config_schema_SUITE_data/schema/rabbitmq_metronome.schema
deleted file mode 100644
index 53cf8f003e..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_metronome.schema
+++ /dev/null
@@ -1,9 +0,0 @@
-
-{mapping, "metronome.exchange", "rabbitmq_metronome.exchange",
- [{datatype, string}]}.
-
-{translation, "rabbitmq_metronome.exchange",
-fun(Conf) ->
- Exchange = cuttlefish:conf_get("metronome.exchange", Conf),
- list_to_binary(Exchange)
-end}. \ No newline at end of file
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_mqtt.schema b/test/config_schema_SUITE_data/schema/rabbitmq_mqtt.schema
deleted file mode 100644
index ffda10beaa..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_mqtt.schema
+++ /dev/null
@@ -1,248 +0,0 @@
-%% ----------------------------------------------------------------------------
-%% RabbitMQ MQTT Adapter
-%%
-%% See https://github.com/rabbitmq/rabbitmq-mqtt/blob/stable/README.md
-%% for details
-%% ----------------------------------------------------------------------------
-
-% {rabbitmq_mqtt,
-% [%% Set the default user name and password. Will be used as the default login
-%% if a connecting client provides no other login details.
-%%
-%% Please note that setting this will allow clients to connect without
-%% authenticating!
-%%
-%% {default_user, <<"guest">>},
-%% {default_pass, <<"guest">>},
-
-{mapping, "mqtt.default_user", "rabbitmq_mqtt.default_user", [
- {datatype, string}
-]}.
-
-{mapping, "mqtt.default_pass", "rabbitmq_mqtt.default_pass", [
- {datatype, string}
-]}.
-
-{translation, "rabbitmq_mqtt.default_user",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("mqtt.default_user", Conf))
-end}.
-
-{translation, "rabbitmq_mqtt.default_pass",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("mqtt.default_pass", Conf))
-end}.
-
-%% Enable anonymous access. If this is set to false, clients MUST provide
-%% login information in order to connect. See the default_user/default_pass
-%% configuration elements for managing logins without authentication.
-%%
-%% {allow_anonymous, true},
-
-{mapping, "mqtt.allow_anonymous", "rabbitmq_mqtt.allow_anonymous",
- [{datatype, {enum, [true, false]}}]}.
-
-%% If you have multiple chosts, specify the one to which the
-%% adapter connects.
-%%
-%% {vhost, <<"/">>},
-
-{mapping, "mqtt.vhost", "rabbitmq_mqtt.vhost", [{datatype, string}]}.
-
-{translation, "rabbitmq_mqtt.vhost",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("mqtt.vhost", Conf))
-end}.
-
-%% Specify the exchange to which messages from MQTT clients are published.
-%%
-%% {exchange, <<"amq.topic">>},
-
-{mapping, "mqtt.exchange", "rabbitmq_mqtt.exchange", [{datatype, string}]}.
-
-{translation, "rabbitmq_mqtt.exchange",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("mqtt.exchange", Conf))
-end}.
-
-%% Specify TTL (time to live) to control the lifetime of non-clean sessions.
-%%
-%% {subscription_ttl, 1800000},
-{mapping, "mqtt.subscription_ttl", "rabbitmq_mqtt.subscription_ttl", [
- {datatype, [{enum, [undefined, infinity]}, integer]}
-]}.
-
-{translation, "rabbitmq_mqtt.subscription_ttl",
-fun(Conf) ->
- case cuttlefish:conf_get("mqtt.subscription_ttl", Conf, undefined) of
- undefined -> undefined;
- infinity -> undefined;
- Ms -> Ms
- end
-end}.
-
-%% Set the prefetch count (governing the maximum number of unacknowledged
-%% messages that will be delivered).
-%%
-%% {prefetch, 10},
-{mapping, "mqtt.prefetch", "rabbitmq_mqtt.prefetch",
- [{datatype, integer}]}.
-
-
-{mapping, "mqtt.retained_message_store", "rabbitmq_mqtt.retained_message_store",
- [{datatype, atom}]}.
-
-{mapping, "mqtt.retained_message_store_dets_sync_interval", "rabbitmq_mqtt.retained_message_store_dets_sync_interval",
- [{datatype, integer}]}.
-
-
-
-%% TCP/SSL Configuration (as per the broker configuration).
-%%
-%% {tcp_listeners, [1883]},
-%% {ssl_listeners, []},
-
-{mapping, "mqtt.listeners.tcp", "rabbitmq_mqtt.tcp_listeners",[
- {datatype, {enum, [none]}}
-]}.
-
-{mapping, "mqtt.listeners.tcp.$name", "rabbitmq_mqtt.tcp_listeners",[
- {datatype, [integer, ip]}
-]}.
-
-{translation, "rabbitmq_mqtt.tcp_listeners",
-fun(Conf) ->
- case cuttlefish:conf_get("mqtt.listeners.tcp", Conf, undefined) of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("mqtt.listeners.tcp", Conf),
- [ V || {_, V} <- Settings ]
- end
-end}.
-
-{mapping, "mqtt.listeners.ssl", "rabbitmq_mqtt.ssl_listeners",[
- {datatype, {enum, [none]}}
-]}.
-
-{mapping, "mqtt.listeners.ssl.$name", "rabbitmq_mqtt.ssl_listeners",[
- {datatype, [integer, ip]}
-]}.
-
-{translation, "rabbitmq_mqtt.ssl_listeners",
-fun(Conf) ->
- case cuttlefish:conf_get("mqtt.listeners.ssl", Conf, undefined) of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("mqtt.listeners.ssl", Conf),
- [ V || {_, V} <- Settings ]
- end
-end}.
-
-%% Number of Erlang processes that will accept connections for the TCP
-%% and SSL listeners.
-%%
-%% {num_tcp_acceptors, 10},
-%% {num_ssl_acceptors, 1},
-
-{mapping, "mqtt.num_acceptors.ssl", "rabbitmq_mqtt.num_ssl_acceptors", [
- {datatype, integer}
-]}.
-
-{mapping, "mqtt.num_acceptors.tcp", "rabbitmq_mqtt.num_tcp_acceptors", [
- {datatype, integer}
-]}.
-
-{mapping, "mqtt.ssl_cert_login", "rabbitmq_mqtt.ssl_cert_login", [
- {datatype, {enum, [true, false]}}]}.
-
-
-%% TCP/Socket options (as per the broker configuration).
-%%
-%% {tcp_listen_options, [{backlog, 128},
-%% {nodelay, true}]}
-% ]},
-
-%% TCP listener section ======================================================
-
-{mapping, "mqtt.tcp_listen_options", "rabbitmq_mqtt.rabbit.tcp_listen_options", [
- {datatype, {enum, [none]}}]}.
-
-{translation, "rabbitmq_mqtt.rabbit.tcp_listen_options",
-fun(Conf) ->
- case cuttlefish:conf_get("mqtt.tcp_listen_options") of
- none -> [];
- _ -> cuttlefish:invalid("Invalid mqtt.tcp_listen_options")
- end
-end}.
-
-{mapping, "mqtt.tcp_listen_options.backlog", "rabbitmq_mqtt.tcp_listen_options.backlog", [
- {datatype, integer}
-]}.
-
-{mapping, "mqtt.tcp_listen_options.nodelay", "rabbitmq_mqtt.tcp_listen_options.nodelay", [
- {datatype, {enum, [true, false]}}
-]}.
-
-{mapping, "mqtt.tcp_listen_options.buffer", "rabbitmq_mqtt.tcp_listen_options.buffer",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.delay_send", "rabbitmq_mqtt.tcp_listen_options.delay_send",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "mqtt.tcp_listen_options.dontroute", "rabbitmq_mqtt.tcp_listen_options.dontroute",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "mqtt.tcp_listen_options.exit_on_close", "rabbitmq_mqtt.tcp_listen_options.exit_on_close",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "mqtt.tcp_listen_options.fd", "rabbitmq_mqtt.tcp_listen_options.fd",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.high_msgq_watermark", "rabbitmq_mqtt.tcp_listen_options.high_msgq_watermark",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.high_watermark", "rabbitmq_mqtt.tcp_listen_options.high_watermark",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.keepalive", "rabbitmq_mqtt.tcp_listen_options.keepalive",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "mqtt.tcp_listen_options.low_msgq_watermark", "rabbitmq_mqtt.tcp_listen_options.low_msgq_watermark",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.low_watermark", "rabbitmq_mqtt.tcp_listen_options.low_watermark",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.port", "rabbitmq_mqtt.tcp_listen_options.port",
- [{datatype, integer}, {validators, ["port"]}]}.
-
-{mapping, "mqtt.tcp_listen_options.priority", "rabbitmq_mqtt.tcp_listen_options.priority",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.recbuf", "rabbitmq_mqtt.tcp_listen_options.recbuf",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.send_timeout", "rabbitmq_mqtt.tcp_listen_options.send_timeout",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.send_timeout_close", "rabbitmq_mqtt.tcp_listen_options.send_timeout_close",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "mqtt.tcp_listen_options.sndbuf", "rabbitmq_mqtt.tcp_listen_options.sndbuf",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.tos", "rabbitmq_mqtt.tcp_listen_options.tos",
- [{datatype, integer}]}.
-
-{mapping, "mqtt.tcp_listen_options.linger.on", "rabbitmq_mqtt.tcp_listen_options.linger",
- [{datatype, {enum, [true, false]}}]}.
-
-{mapping, "mqtt.tcp_listen_options.linger.timeout", "rabbitmq_mqtt.tcp_listen_options.linger",
- [{datatype, integer}]}.
-
-{translation, "rabbitmq_mqtt.tcp_listen_options.linger",
-fun(Conf) ->
- LingerOn = cuttlefish:conf_get("mqtt.tcp_listen_options.linger.on", Conf, false),
- LingerTimeout = cuttlefish:conf_get("mqtt.tcp_listen_options.linger.timeout", Conf, 0),
- {LingerOn, LingerTimeout}
-end}.
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_stomp.schema b/test/config_schema_SUITE_data/schema/rabbitmq_stomp.schema
deleted file mode 100644
index b7619f0b28..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_stomp.schema
+++ /dev/null
@@ -1,110 +0,0 @@
-%% ==========================================================================
-%% ----------------------------------------------------------------------------
-%% RabbitMQ Stomp Adapter
-%%
-%% See http://www.rabbitmq.com/stomp.html for details
-%% ----------------------------------------------------------------------------
-
-% {rabbitmq_stomp,
-% [%% Network Configuration - the format is generally the same as for the broker
-
-%% Listen only on localhost (ipv4 & ipv6) on a specific port.
-%% {tcp_listeners, [{"127.0.0.1", 61613},
-%% {"::1", 61613}]},
-
-{mapping, "stomp.listeners.tcp", "rabbitmq_stomp.tcp_listeners",[
- {datatype, {enum, [none]}}
-]}.
-
-{mapping, "stomp.listeners.tcp.$name", "rabbitmq_stomp.tcp_listeners",[
- {datatype, [integer, ip]}
-]}.
-
-{translation, "rabbitmq_stomp.tcp_listeners",
-fun(Conf) ->
- case cuttlefish:conf_get("stomp.listeners.tcp", Conf, undefined) of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("stomp.listeners.tcp", Conf),
- [ V || {_, V} <- Settings ]
- end
-end}.
-
-{mapping, "stomp.listeners.ssl", "rabbitmq_stomp.ssl_listeners",[
- {datatype, {enum, [none]}}
-]}.
-
-{mapping, "stomp.listeners.ssl.$name", "rabbitmq_stomp.ssl_listeners",[
- {datatype, [integer, ip]}
-]}.
-
-{translation, "rabbitmq_stomp.ssl_listeners",
-fun(Conf) ->
- case cuttlefish:conf_get("stomp.listeners.ssl", Conf, undefined) of
- none -> [];
- _ ->
- Settings = cuttlefish_variable:filter_by_prefix("stomp.listeners.ssl", Conf),
- [ V || {_, V} <- Settings ]
- end
-end}.
-
-%% Number of Erlang processes that will accept connections for the TCP
-%% and SSL listeners.
-%%
-%% {num_tcp_acceptors, 10},
-%% {num_ssl_acceptors, 1},
-
-{mapping, "stomp.num_acceptors.ssl", "rabbitmq_stomp.num_ssl_acceptors", [
- {datatype, integer}
-]}.
-
-{mapping, "stomp.num_acceptors.tcp", "rabbitmq_stomp.num_tcp_acceptors", [
- {datatype, integer}
-]}.
-
-%% Additional SSL options
-
-%% Extract a name from the client's certificate when using SSL.
-%%
-%% {ssl_cert_login, true},
-
-{mapping, "stomp.ssl_cert_login", "rabbitmq_stomp.ssl_cert_login",
- [{datatype, {enum, [true, false]}}]}.
-
-%% Set a default user name and password. This is used as the default login
-%% whenever a CONNECT frame omits the login and passcode headers.
-%%
-%% Please note that setting this will allow clients to connect without
-%% authenticating!
-%%
-%% {default_user, [{login, "guest"},
-%% {passcode, "guest"}]},
-
-{mapping, "stomp.default_vhost", "rabbitmq_stomp.default_vhost", [
- {datatype, string}
-]}.
-
-{translation, "rabbitmq_stomp.default_vhost",
-fun(Conf) ->
- list_to_binary(cuttlefish:conf_get("stomp.default_vhost", Conf, "/"))
-end}.
-
-{mapping, "stomp.default_user", "rabbitmq_stomp.default_user.login", [
- {datatype, string}
-]}.
-
-{mapping, "stomp.default_pass", "rabbitmq_stomp.default_user.passcode", [
- {datatype, string}
-]}.
-
-%% If a default user is configured, or you have configured use SSL client
-%% certificate based authentication, you can choose to allow clients to
-%% omit the CONNECT frame entirely. If set to true, the client is
-%% automatically connected as the default user or user supplied in the
-%% SSL certificate whenever the first frame sent on a session is not a
-%% CONNECT frame.
-%%
-%% {implicit_connect, true}
-% ]},
-{mapping, "stomp.implicit_connect", "rabbitmq_stomp.implicit_connect",
- [{datatype, {enum, [true, false]}}]}.
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_web_mqtt.schema b/test/config_schema_SUITE_data/schema/rabbitmq_web_mqtt.schema
deleted file mode 100644
index acdab62c32..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_web_mqtt.schema
+++ /dev/null
@@ -1,44 +0,0 @@
-{mapping, "web_mqtt.num_acceptors.tcp", "rabbitmq_web_mqtt.num_tcp_acceptors",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.num_acceptors.ssl", "rabbitmq_web_mqtt.num_ssl_acceptors",
- [{datatype, integer}]}.
-
-{mapping, "web_mqtt.tcp.port", "rabbitmq_web_mqtt.tcp_config.port",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.tcp.backlog", "rabbitmq_web_mqtt.tcp_config.backlog",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.tcp.ip", "rabbitmq_web_mqtt.tcp_config.ip",
- [{datatype, string}, {validators, ["is_ip"]}]}.
-
-
-{mapping, "web_mqtt.ssl.port", "rabbitmq_web_mqtt.ssl_config.port",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.ssl.backlog", "rabbitmq_web_mqtt.ssl_config.backlog",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.ssl.ip", "rabbitmq_web_mqtt.ssl_config.ip",
- [{datatype, string}, {validators, ["is_ip"]}]}.
-{mapping, "web_mqtt.ssl.certfile", "rabbitmq_web_mqtt.ssl_config.certfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-{mapping, "web_mqtt.ssl.keyfile", "rabbitmq_web_mqtt.ssl_config.keyfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-{mapping, "web_mqtt.ssl.cacertfile", "rabbitmq_web_mqtt.ssl_config.cacertfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-{mapping, "web_mqtt.ssl.password", "rabbitmq_web_mqtt.ssl_config.password",
- [{datatype, string}]}.
-
-
-{mapping, "web_mqtt.cowboy_opts.max_empty_lines", "rabbitmq_web_mqtt.cowboy_opts.max_empty_lines",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.cowboy_opts.max_header_name_length", "rabbitmq_web_mqtt.cowboy_opts.max_header_name_length",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.cowboy_opts.max_header_value_length", "rabbitmq_web_mqtt.cowboy_opts.max_header_value_length",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.cowboy_opts.max_headers", "rabbitmq_web_mqtt.cowboy_opts.max_headers",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.cowboy_opts.max_keepalive", "rabbitmq_web_mqtt.cowboy_opts.max_keepalive",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.cowboy_opts.max_request_line_length", "rabbitmq_web_mqtt.cowboy_opts.max_request_line_length",
- [{datatype, integer}]}.
-{mapping, "web_mqtt.cowboy_opts.timeout", "rabbitmq_web_mqtt.cowboy_opts.timeout",
- [{datatype, integer}]}.
-
diff --git a/test/config_schema_SUITE_data/schema/rabbitmq_web_stomp.schema b/test/config_schema_SUITE_data/schema/rabbitmq_web_stomp.schema
deleted file mode 100644
index 389da07d14..0000000000
--- a/test/config_schema_SUITE_data/schema/rabbitmq_web_stomp.schema
+++ /dev/null
@@ -1,64 +0,0 @@
-{mapping, "web_stomp.port", "rabbitmq_web_stomp.port",
- [{datatype, integer}]}.
-
-{mapping, "web_stomp.ws_frame", "rabbitmq_web_stomp.ws_frame",
- [{datatype, {enum, [binary, text]}}]}.
-
-{mapping, "web_stomp.num_acceptors.tcp", "rabbitmq_web_stomp.num_tcp_acceptors",
- [{datatype, integer}]}.
-
-{mapping, "web_stomp.num_acceptors.ssl", "rabbitmq_web_stomp.num_ssl_acceptors",
- [{datatype, integer}]}.
-
-{mapping, "web_stomp.tcp.port", "rabbitmq_web_stomp.tcp_config.port",
- [{datatype, integer}]}.
-{mapping, "web_stomp.tcp.backlog", "rabbitmq_web_stomp.tcp_config.backlog",
- [{datatype, integer}]}.
-{mapping, "web_stomp.tcp.ip", "rabbitmq_web_stomp.tcp_config.ip",
- [{datatype, string}, {validators, ["is_ip"]}]}.
-
-
-{mapping, "web_stomp.ssl.port", "rabbitmq_web_stomp.ssl_config.port",
- [{datatype, integer}]}.
-{mapping, "web_stomp.ssl.backlog", "rabbitmq_web_stomp.ssl_config.backlog",
- [{datatype, integer}]}.
-{mapping, "web_stomp.ssl.ip", "rabbitmq_web_stomp.ssl_config.ip",
- [{datatype, string}, {validators, ["is_ip"]}]}.
-{mapping, "web_stomp.ssl.certfile", "rabbitmq_web_stomp.ssl_config.certfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-{mapping, "web_stomp.ssl.keyfile", "rabbitmq_web_stomp.ssl_config.keyfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-{mapping, "web_stomp.ssl.cacertfile", "rabbitmq_web_stomp.ssl_config.cacertfile",
- [{datatype, string}, {validators, ["file_accessible"]}]}.
-{mapping, "web_stomp.ssl.password", "rabbitmq_web_stomp.ssl_config.password",
- [{datatype, string}]}.
-
-
-{mapping, "web_stomp.cowboy_opts.max_empty_lines", "rabbitmq_web_stomp.cowboy_opts.max_empty_lines",
- [{datatype, integer}]}.
-{mapping, "web_stomp.cowboy_opts.max_header_name_length", "rabbitmq_web_stomp.cowboy_opts.max_header_name_length",
- [{datatype, integer}]}.
-{mapping, "web_stomp.cowboy_opts.max_header_value_length", "rabbitmq_web_stomp.cowboy_opts.max_header_value_length",
- [{datatype, integer}]}.
-{mapping, "web_stomp.cowboy_opts.max_headers", "rabbitmq_web_stomp.cowboy_opts.max_headers",
- [{datatype, integer}]}.
-{mapping, "web_stomp.cowboy_opts.max_keepalive", "rabbitmq_web_stomp.cowboy_opts.max_keepalive",
- [{datatype, integer}]}.
-{mapping, "web_stomp.cowboy_opts.max_request_line_length", "rabbitmq_web_stomp.cowboy_opts.max_request_line_length",
- [{datatype, integer}]}.
-{mapping, "web_stomp.cowboy_opts.timeout", "rabbitmq_web_stomp.cowboy_opts.timeout",
- [{datatype, integer}]}.
-
-
-{mapping, "web_stomp.sockjs_opts.url", "rabbitmq_web_stomp.sockjs_opts.sockjs_url",
- [{datatype, string}]}.
-{mapping, "web_stomp.sockjs_opts.websocket", "rabbitmq_web_stomp.sockjs_opts.websocket",
- [{datatype, {enum, [true, false]}}]}.
-{mapping, "web_stomp.sockjs_opts.cookie_needed", "rabbitmq_web_stomp.sockjs_opts.cookie_needed",
- [{datatype, {enum, [true, false]}}]}.
-{mapping, "web_stomp.sockjs_opts.heartbeat_delay", "rabbitmq_web_stomp.sockjs_opts.heartbeat_delay",
- [{datatype, integer}]}.
-{mapping, "web_stomp.sockjs_opts.disconnect_delay", "rabbitmq_web_stomp.sockjs_opts.disconnect_delay",
- [{datatype, integer}]}.
-{mapping, "web_stomp.sockjs_opts.response_limit", "rabbitmq_web_stomp.sockjs_opts.response_limit",
- [{datatype, integer}]}.
diff --git a/test/config_schema_SUITE_data/snippets.config b/test/config_schema_SUITE_data/snippets.config
index abfc28441e..8c4319fa53 100644
--- a/test/config_schema_SUITE_data/snippets.config
+++ b/test/config_schema_SUITE_data/snippets.config
@@ -94,12 +94,25 @@ default_permissions.write = .*",
{default_permissions, [<<".*">>, <<".*">>, <<".*">>]}]}],[]}
,
{13,
-"cluster_nodes.disc.1 = rabbit@hostname1
-cluster_nodes.disc.2 = rabbit@hostname2",
+"autocluster.classic_config.nodes.peer1 = rabbit@hostname1
+autocluster.classic_config.nodes.peer2 = rabbit@hostname2
+autocluster.classic_config.node_type = disc",
[{rabbit, [
{cluster_nodes, {[rabbit@hostname2,rabbit@hostname1], disc}}
]}],[]}
,
+{13.1,
+"autocluster.classic_config.nodes.peer1 = rabbit@hostname1
+autocluster.classic_config.nodes.peer2 = rabbit@hostname2
+autocluster.classic_config.node_type = disk",
+[{rabbit, [
+ {cluster_nodes, {[rabbit@hostname2,rabbit@hostname1], disc}}
+]}],[]}
+,
+{13.2,
+"autocluster.classic_config.node_type = ram",
+[],[]}
+,
{14,
"tcp_listen_options.backlog = 128
tcp_listen_options.nodelay = true
diff --git a/test/dynamic_ha_SUITE.erl b/test/dynamic_ha_SUITE.erl
index bba7fad707..502e3a7e86 100644
--- a/test/dynamic_ha_SUITE.erl
+++ b/test/dynamic_ha_SUITE.erl
@@ -61,7 +61,8 @@ groups() ->
]},
{cluster_size_3, [], [
change_policy,
- rapid_change
+ rapid_change,
+ nodes_policy_should_pick_master_from_its_params
% FIXME: Re-enable those tests when the know issues are
% fixed.
%failing_random_policies,
@@ -258,6 +259,48 @@ promote_on_shutdown(Config) ->
durable = true}),
ok.
+nodes_policy_should_pick_master_from_its_params(Config) ->
+ [A | _] = rabbit_ct_broker_helpers:get_node_configs(Config,
+ nodename),
+
+ Ch = rabbit_ct_client_helpers:open_channel(Config, A),
+ ?assertEqual(true, apply_policy_to_declared_queue(Config, Ch, [A],
+ [all])),
+ %% --> Master: A
+ %% Slaves: [B, C] or [C, B]
+ Info = find_queue(?QNAME, A),
+ SSPids = proplists:get_value(synchronised_slave_pids, Info),
+
+ %% Choose slave that isn't the first sync slave. Cover a bug that always
+ %% chose the first, even if it was not part of the policy
+ LastSlave = node(lists:last(SSPids)),
+ ?assertEqual(true, apply_policy_to_declared_queue(Config, Ch, [A],
+ [{nodes, [LastSlave]}])),
+ %% --> Master: B or C (depends on the order of current slaves)
+ %% Slaves: []
+
+ %% Now choose a new master that isn't synchronised. The previous
+ %% policy made sure that the queue only runs on one node (the last
+ %% from the initial synchronised list). Thus, by taking the first
+ %% node from this list, we know it is not synchronised.
+ %%
+ %% Because the policy doesn't cover any synchronised slave, RabbitMQ
+ %% should instead use an existing synchronised slave as the new master,
+ %% even though that isn't in the policy.
+ ?assertEqual(true, apply_policy_to_declared_queue(Config, Ch, [A],
+ [{nodes, [LastSlave, A]}])),
+ %% --> Master: B or C (same as previous policy)
+ %% Slaves: [A]
+
+ NewMaster = node(erlang:hd(SSPids)),
+ ?assertEqual(true, apply_policy_to_declared_queue(Config, Ch, [A],
+ [{nodes, [NewMaster]}])),
+ %% --> Master: B or C (the other one compared to previous policy)
+ %% Slaves: []
+
+ amqp_channel:call(Ch, #'queue.delete'{queue = ?QNAME}),
+ _ = rabbit_ct_broker_helpers:clear_policy(Config, A, ?POLICY).
+
random_policy(Config) ->
run_proper(fun prop_random_policy/1, [Config]).
@@ -364,9 +407,8 @@ prop_random_policy(Config) ->
Policies, non_empty(list(policy_gen(Nodes))),
test_random_policy(Config, Nodes, Policies)).
-test_random_policy(Config, Nodes, Policies) ->
+apply_policy_to_declared_queue(Config, Ch, Nodes, Policies) ->
[NodeA | _] = Nodes,
- Ch = rabbit_ct_client_helpers:open_channel(Config, NodeA),
amqp_channel:call(Ch, #'queue.declare'{queue = ?QNAME}),
%% Add some load so mirrors can be busy synchronising
rabbit_ct_client_helpers:publish(Ch, ?QNAME, 100000),
@@ -375,7 +417,12 @@ test_random_policy(Config, Nodes, Policies) ->
%% Give it some time to generate all internal notifications
timer:sleep(2000),
%% Check the result
- Result = wait_for_last_policy(?QNAME, NodeA, Policies, 30),
+ wait_for_last_policy(?QNAME, NodeA, Policies, 30).
+
+test_random_policy(Config, Nodes, Policies) ->
+ [NodeA | _] = Nodes,
+ Ch = rabbit_ct_client_helpers:open_channel(Config, NodeA),
+ Result = apply_policy_to_declared_queue(Config, Ch, Nodes, Policies),
%% Cleanup
amqp_channel:call(Ch, #'queue.delete'{queue = ?QNAME}),
_ = rabbit_ct_broker_helpers:clear_policy(Config, NodeA, ?POLICY),
diff --git a/test/unit_SUITE.erl b/test/unit_SUITE.erl
index 5faeccdaab..b270a3a432 100644
--- a/test/unit_SUITE.erl
+++ b/test/unit_SUITE.erl
@@ -24,7 +24,8 @@
all() ->
[
- {group, parallel_tests}
+ {group, parallel_tests},
+ {group, sequential_tests}
].
groups() ->
@@ -41,6 +42,10 @@ groups() ->
]},
content_framing,
content_transcoding,
+ encrypt_decrypt,
+ encrypt_decrypt_term,
+ decrypt_config,
+ rabbitmqctl_encode,
pg_local,
pmerge,
plmerge,
@@ -63,12 +68,36 @@ groups() ->
{vm_memory_monitor, [parallel], [
parse_line_linux
]}
+ ]},
+ {sequential_tests, [], [
+ decrypt_start_app,
+ decrypt_start_app_file,
+ decrypt_start_app_undefined,
+ decrypt_start_app_wrong_passphrase
]}
].
init_per_group(_, Config) -> Config.
end_per_group(_, Config) -> Config.
+init_per_testcase(TC, Config) when TC =:= decrypt_start_app;
+ TC =:= decrypt_start_app_file;
+ TC =:= decrypt_start_app_undefined ->
+ application:load(rabbit),
+ Config;
+init_per_testcase(_, Config) ->
+ Config.
+
+end_per_testcase(TC, _Config) when TC =:= decrypt_start_app;
+ TC =:= decrypt_start_app_file;
+ TC =:= decrypt_start_app_undefined ->
+ application:unload(rabbit),
+ application:unload(rabbit_shovel_test);
+end_per_testcase(decrypt_config, _Config) ->
+ application:unload(rabbit);
+end_per_testcase(_TC, _Config) ->
+ ok.
+
%% -------------------------------------------------------------------
%% Argument parsing.
%% -------------------------------------------------------------------
@@ -233,6 +262,254 @@ prepend_check(HeaderKey, HeaderTable, Headers) ->
rabbit_misc:table_lookup(Invalid, HeaderKey),
Headers1.
+encrypt_decrypt(_Config) ->
+ %% Take all available block ciphers.
+ Hashes = rabbit_pbe:supported_hashes(),
+ Ciphers = rabbit_pbe:supported_ciphers(),
+ %% For each cipher, try to encrypt and decrypt data sizes from 0 to 64 bytes
+ %% with a random passphrase.
+ _ = [begin
+ PassPhrase = crypto:strong_rand_bytes(16),
+ Iterations = rand:uniform(100),
+ Data = crypto:strong_rand_bytes(64),
+ [begin
+ Expected = binary:part(Data, 0, Len),
+ Enc = rabbit_pbe:encrypt(C, H, Iterations, PassPhrase, Expected),
+ Expected = iolist_to_binary(rabbit_pbe:decrypt(C, H, Iterations, PassPhrase, Enc))
+ end || Len <- lists:seq(0, byte_size(Data))]
+ end || H <- Hashes, C <- Ciphers],
+ ok.
+
+encrypt_decrypt_term(_Config) ->
+ %% Take all available block ciphers.
+ Hashes = rabbit_pbe:supported_hashes(),
+ Ciphers = rabbit_pbe:supported_ciphers(),
+ %% Different Erlang terms to try encrypting.
+ DataSet = [
+ 10000,
+ [5672],
+ [{"127.0.0.1", 5672},
+ {"::1", 5672}],
+ [{connection, info}, {channel, info}],
+ [{cacertfile, "/path/to/testca/cacert.pem"},
+ {certfile, "/path/to/server/cert.pem"},
+ {keyfile, "/path/to/server/key.pem"},
+ {verify, verify_peer},
+ {fail_if_no_peer_cert, false}],
+ [<<".*">>, <<".*">>, <<".*">>]
+ ],
+ _ = [begin
+ PassPhrase = crypto:strong_rand_bytes(16),
+ Iterations = rand:uniform(100),
+ Enc = rabbit_pbe:encrypt_term(C, H, Iterations, PassPhrase, Data),
+ Data = rabbit_pbe:decrypt_term(C, H, Iterations, PassPhrase, Enc)
+ end || H <- Hashes, C <- Ciphers, Data <- DataSet],
+ ok.
+
+decrypt_config(_Config) ->
+ %% Take all available block ciphers.
+ Hashes = rabbit_pbe:supported_hashes(),
+ Ciphers = rabbit_pbe:supported_ciphers(),
+ Iterations = [1, 10, 100, 1000],
+ %% Loop through all hashes, ciphers and iterations.
+ _ = [begin
+ PassPhrase = crypto:strong_rand_bytes(16),
+ do_decrypt_config({C, H, I, PassPhrase})
+ end || H <- Hashes, C <- Ciphers, I <- Iterations],
+ ok.
+
+do_decrypt_config(Algo = {C, H, I, P}) ->
+ application:load(rabbit),
+ RabbitConfig = application:get_all_env(rabbit),
+ %% Encrypt a few values in configuration.
+ %% Common cases.
+ _ = [encrypt_value(Key, Algo) || Key <- [
+ tcp_listeners,
+ num_tcp_acceptors,
+ ssl_options,
+ vm_memory_high_watermark,
+ default_pass,
+ default_permissions,
+ cluster_nodes,
+ auth_mechanisms,
+ msg_store_credit_disc_bound]],
+ %% Special case: encrypt a value in a list.
+ {ok, [LoopbackUser]} = application:get_env(rabbit, loopback_users),
+ EncLoopbackUser = rabbit_pbe:encrypt_term(C, H, I, P, LoopbackUser),
+ application:set_env(rabbit, loopback_users, [{encrypted, EncLoopbackUser}]),
+ %% Special case: encrypt a value in a key/value list.
+ {ok, TCPOpts} = application:get_env(rabbit, tcp_listen_options),
+ {_, Backlog} = lists:keyfind(backlog, 1, TCPOpts),
+ {_, Linger} = lists:keyfind(linger, 1, TCPOpts),
+ EncBacklog = rabbit_pbe:encrypt_term(C, H, I, P, Backlog),
+ EncLinger = rabbit_pbe:encrypt_term(C, H, I, P, Linger),
+ TCPOpts1 = lists:keyreplace(backlog, 1, TCPOpts, {backlog, {encrypted, EncBacklog}}),
+ TCPOpts2 = lists:keyreplace(linger, 1, TCPOpts1, {linger, {encrypted, EncLinger}}),
+ application:set_env(rabbit, tcp_listen_options, TCPOpts2),
+ %% Decrypt configuration.
+ rabbit:decrypt_config([rabbit], Algo),
+ %% Check that configuration was decrypted properly.
+ RabbitConfig = application:get_all_env(rabbit),
+ application:unload(rabbit),
+ ok.
+
+encrypt_value(Key, {C, H, I, P}) ->
+ {ok, Value} = application:get_env(rabbit, Key),
+ EncValue = rabbit_pbe:encrypt_term(C, H, I, P, Value),
+ application:set_env(rabbit, Key, {encrypted, EncValue}).
+
+decrypt_start_app(Config) ->
+ do_decrypt_start_app(Config, "hello").
+
+decrypt_start_app_file(Config) ->
+ do_decrypt_start_app(Config, {file, ?config(data_dir, Config) ++ "/rabbit_shovel_test.passphrase"}).
+
+do_decrypt_start_app(Config, Passphrase) ->
+ %% Configure rabbit for decrypting configuration.
+ application:set_env(rabbit, decoder_config, [
+ {cipher, aes_cbc256},
+ {hash, sha512},
+ {iterations, 1000},
+ {passphrase, Passphrase}
+ ]),
+ %% Add the path to our test application.
+ code:add_path(?config(data_dir, Config) ++ "/lib/rabbit_shovel_test/ebin"),
+ %% Attempt to start our test application.
+ %%
+ %% We expect a failure *after* the decrypting has been done.
+ try
+ rabbit:start_apps([rabbit_shovel_test])
+ catch _:_ ->
+ ok
+ end,
+ %% Check if the values have been decrypted.
+ {ok, Shovels} = application:get_env(rabbit_shovel_test, shovels),
+ {_, FirstShovel} = lists:keyfind(my_first_shovel, 1, Shovels),
+ {_, Sources} = lists:keyfind(sources, 1, FirstShovel),
+ {_, Brokers} = lists:keyfind(brokers, 1, Sources),
+ ["amqp://fred:secret@host1.domain/my_vhost",
+ "amqp://john:secret@host2.domain/my_vhost"] = Brokers,
+ ok.
+
+decrypt_start_app_undefined(Config) ->
+ %% Configure rabbit for decrypting configuration.
+ application:set_env(rabbit, decoder_config, [
+ {cipher, aes_cbc256},
+ {hash, sha512},
+ {iterations, 1000}
+ %% No passphrase option!
+ ]),
+ %% Add the path to our test application.
+ code:add_path(?config(data_dir, Config) ++ "/lib/rabbit_shovel_test/ebin"),
+ %% Attempt to start our test application.
+ %%
+ %% We expect a failure during decryption because the passphrase is missing.
+ try
+ rabbit:start_apps([rabbit_shovel_test])
+ catch
+ exit:{bad_configuration,decoder_config} -> ok;
+ _:_ -> exit(unexpected_exception)
+ end.
+
+decrypt_start_app_wrong_passphrase(Config) ->
+ %% Configure rabbit for decrypting configuration.
+ application:set_env(rabbit, decoder_config, [
+ {cipher, aes_cbc256},
+ {hash, sha512},
+ {iterations, 1000},
+ {passphrase, "wrong passphrase"}
+ ]),
+ %% Add the path to our test application.
+ code:add_path(?config(data_dir, Config) ++ "/lib/rabbit_shovel_test/ebin"),
+ %% Attempt to start our test application.
+ %%
+ %% We expect a failure during decryption because the passphrase is wrong.
+ try
+ rabbit:start_apps([rabbit_shovel_test])
+ catch
+ exit:{decryption_error,_,_} -> ok;
+ _:_ -> exit(unexpected_exception)
+ end.
+
+rabbitmqctl_encode(_Config) ->
+ % list ciphers and hashes
+ {ok, _} = rabbit_control_pbe:encode(true, false, undefined, undefined, undefined, undefined, undefined),
+ {ok, _} = rabbit_control_pbe:encode(false, true, undefined, undefined, undefined, undefined, undefined),
+ % incorrect ciphers, hashes and iteration number
+ {error, _} = rabbit_control_pbe:encode(false, false, undefined, funny_cipher, undefined, undefined, undefined),
+ {error, _} = rabbit_control_pbe:encode(false, false, undefined, undefined, funny_hash, undefined, undefined),
+ {error, _} = rabbit_control_pbe:encode(false, false, undefined, undefined, undefined, -1, undefined),
+ {error, _} = rabbit_control_pbe:encode(false, false, undefined, undefined, undefined, 0, undefined),
+ % incorrect number of arguments
+ {error, _} = rabbit_control_pbe:encode(
+ false, false,
+ false, % encrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ []
+ ),
+ {error, _} = rabbit_control_pbe:encode(
+ false, false,
+ false, % encrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ [undefined]
+ ),
+ {error, _} = rabbit_control_pbe:encode(
+ false, false,
+ false, % encrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ [undefined, undefined, undefined]
+ ),
+
+ % encrypt/decrypt
+ % string
+ rabbitmqctl_encode_encrypt_decrypt("foobar"),
+ % binary
+ rabbitmqctl_encode_encrypt_decrypt("<<\"foobar\">>"),
+ % tuple
+ rabbitmqctl_encode_encrypt_decrypt("{password,<<\"secret\">>}"),
+
+ ok.
+
+rabbitmqctl_encode_encrypt_decrypt(Secret) ->
+ PassPhrase = "passphrase",
+ {ok, Output} = rabbit_control_pbe:encode(
+ false, false,
+ false, % encrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ [Secret, PassPhrase]
+ ),
+ {encrypted, Encrypted} = rabbit_control_pbe:evaluate_input_as_term(lists:flatten(Output)),
+
+ {ok, Result} = rabbit_control_pbe:encode(
+ false, false,
+ true, % decrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ [lists:flatten(io_lib:format("~p", [Encrypted])), PassPhrase]
+ ),
+ Secret = lists:flatten(Result),
+ % decrypt with {encrypted, ...} form as input
+ {ok, Result} = rabbit_control_pbe:encode(
+ false, false,
+ true, % decrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ [lists:flatten(io_lib:format("~p", [{encrypted, Encrypted}])), PassPhrase]
+ ),
+
+ % wrong passphrase
+ {error, _} = rabbit_control_pbe:encode(
+ false, false,
+ true, % decrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ [lists:flatten(io_lib:format("~p", [Encrypted])), PassPhrase ++ " "]
+ ),
+ {error, _} = rabbit_control_pbe:encode(
+ false, false,
+ true, % decrypt
+ rabbit_pbe:default_cipher(), rabbit_pbe:default_hash(), rabbit_pbe:default_iterations(),
+ [lists:flatten(io_lib:format("~p", [{encrypted, Encrypted}])), PassPhrase ++ " "]
+ )
+ .
+
%% -------------------------------------------------------------------
%% pg_local.
%% -------------------------------------------------------------------
diff --git a/test/unit_SUITE_data/lib/rabbit_shovel_test/ebin/rabbit_shovel_test.app b/test/unit_SUITE_data/lib/rabbit_shovel_test/ebin/rabbit_shovel_test.app
new file mode 100644
index 0000000000..a8481c9aa4
--- /dev/null
+++ b/test/unit_SUITE_data/lib/rabbit_shovel_test/ebin/rabbit_shovel_test.app
@@ -0,0 +1,46 @@
+{application, rabbit_shovel_test,
+ [{description, "Test .app file for tests for encrypting configuration"},
+ {vsn, ""},
+ {modules, []},
+ {env, [ {shovels, [ {my_first_shovel,
+ [ {sources,
+ [ {brokers, [ {encrypted, <<"CfJXuka/uJYsqAtiJnwKpSY4moMPcOBh4sO8XDcdmhXbVYGKCDLKEilWPMfvOAQ2lN1BQneGn6bvDZi2+gDu6iHVKfafQAZSv8zcsVB3uYdBXFzqTCWO8TAsgG6LUMPT">>}
+ , {encrypted, <<"dBO6n+G1OiBwZeLXhvmNYeTE57nhBOmicUBF34zo4nQjerzQaNoEk8GA2Ts5PzMhYeO6U6Y9eEmheqIr9Gzh2duLZic65ZMQtIKNpWcZJllEhGpk7aV1COr23Yur9fWG">>}
+ ]}
+ , {declarations, [ {'exchange.declare',
+ [ {exchange, <<"my_fanout">>}
+ , {type, <<"fanout">>}
+ , durable
+ ]}
+ , {'queue.declare',
+ [{arguments,
+ [{<<"x-message-ttl">>, long, 60000}]}]}
+ , {'queue.bind',
+ [ {exchange, <<"my_direct">>}
+ , {queue, <<>>}
+ ]}
+ ]}
+ ]}
+ , {destinations,
+ [ {broker, "amqp://"}
+ , {declarations, [ {'exchange.declare',
+ [ {exchange, <<"my_direct">>}
+ , {type, <<"direct">>}
+ , durable
+ ]}
+ ]}
+ ]}
+ , {queue, <<>>}
+ , {prefetch_count, 10}
+ , {ack_mode, on_confirm}
+ , {publish_properties, [ {delivery_mode, 2} ]}
+ , {add_forward_headers, true}
+ , {publish_fields, [ {exchange, <<"my_direct">>}
+ , {routing_key, <<"from_shovel">>}
+ ]}
+ , {reconnect_delay, 5}
+ ]}
+ ]}
+ ]},
+
+ {applications, [kernel, stdlib]}]}.
diff --git a/test/unit_SUITE_data/rabbit_shovel_test.passphrase b/test/unit_SUITE_data/rabbit_shovel_test.passphrase
new file mode 100644
index 0000000000..ce01362503
--- /dev/null
+++ b/test/unit_SUITE_data/rabbit_shovel_test.passphrase
@@ -0,0 +1 @@
+hello