Merge branch 'stable'
This commit is contained in:
commit
fe2a3c3b3c
|
|
@ -22,6 +22,10 @@ The list is node-local.
|
|||
|
||||
This plugin requires RabbitMQ `3.6.1` or later.
|
||||
|
||||
## Erlang Version Requirements
|
||||
|
||||
This plugin requires Erlang version 17.3 or later.
|
||||
|
||||
## Installation and Binary Builds
|
||||
|
||||
This plugin is now available from the [RabbitMQ community plugins page](http://www.rabbitmq.com/community-plugins.html).
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ list_certs(_Config) ->
|
|||
%% so they should be unique (there is no need to add change time)
|
||||
{ok,
|
||||
[{CertName,
|
||||
#{name => CertName,
|
||||
[{name, CertName},
|
||||
%% Url can be formed from CertName, so there is no
|
||||
%% need for this attribute.
|
||||
%% But we use it as an example for providers where CertName and
|
||||
%% url are different.
|
||||
url => <<"https://certs.opera.com/02/roots/", CertName/binary>>}}
|
||||
{url, <<"https://certs.opera.com/02/roots/", CertName/binary>>}]}
|
||||
|| CertName <- CertNames],
|
||||
nostate};
|
||||
Other -> {error, {http_error, Other}}
|
||||
|
|
@ -46,7 +46,8 @@ list_certs(Config, _) -> list_certs(Config).
|
|||
%% This function loads a certificate data using certifocate ID and attributes.
|
||||
%% We use the url parameter in attributes.
|
||||
%% Some providers can ignore attributes and use CertId instead
|
||||
load_cert(_CertId, #{url := Url}, _Config) ->
|
||||
load_cert(_CertId, Attributes, _Config) ->
|
||||
Url = proplists:get_value(url, Attributes),
|
||||
case httpc:request(get, {rabbit_data_coercion:to_list(Url), []},
|
||||
[], [{body_format, binary}]) of
|
||||
{ok, {{_,Code,_}, _Headers, Body}} when Code div 100 == 2 ->
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ update_certs(CertsList, Provider, Config) ->
|
|||
lists:foreach(
|
||||
fun(CertId) ->
|
||||
Attributes = proplists:get_value(CertId, CertsList),
|
||||
Name = maps:get(name, Attributes, undefined),
|
||||
Name = proplists:get_value(name, Attributes, undefined),
|
||||
case load_and_decode_cert(Provider, CertId, Attributes, Config) of
|
||||
{ok, Cert, IssuerId} ->
|
||||
save_cert(CertId, Provider, IssuerId, Cert, Name);
|
||||
|
|
@ -295,7 +295,7 @@ get_old_cert_ids(Provider) ->
|
|||
when P == Provider ->
|
||||
CId
|
||||
end),
|
||||
lists:append(ets:select(table_name(), MS)).
|
||||
ets:select(table_name(), MS).
|
||||
|
||||
providers(Config) ->
|
||||
Providers = proplists:get_value(providers, Config, []),
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@
|
|||
-> no_change | {ok, [{CertId, Attributes}]}
|
||||
when Config :: list(),
|
||||
CertId :: term(),
|
||||
Attributes :: map().
|
||||
Attributes :: list().
|
||||
|
||||
-callback list_certs(Config, ProviderState)
|
||||
-> no_change | {ok, [{CertId, Attributes}]}
|
||||
when Config :: list(),
|
||||
ProviderState :: term(),
|
||||
CertId :: term(),
|
||||
Attributes :: map().
|
||||
Attributes :: list().
|
||||
|
||||
-callback load_cert(CertId, Attributes, Config)
|
||||
-> {ok, Cert} | {error, term()}
|
||||
when CertId :: term(),
|
||||
Attributes :: map(),
|
||||
Attributes :: list(),
|
||||
Config :: list(),
|
||||
Cert :: public_key:der_encoded().
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
-type cert_id() :: {FileName :: string(), ChangeTime :: integer()}.
|
||||
|
||||
-spec list_certs(Config :: list())
|
||||
-> no_change | {ok, [{cert_id(), map()}], State}
|
||||
-> no_change | {ok, [{cert_id(), list()}], State}
|
||||
when State :: #directory_state{}.
|
||||
list_certs(Config) ->
|
||||
Path = directory_path(Config),
|
||||
|
|
@ -25,7 +25,7 @@ list_certs(Config) ->
|
|||
directory_change_time = NewChangeTime}}.
|
||||
|
||||
-spec list_certs(Config :: list(), State)
|
||||
-> no_change | {ok, [{cert_id(), map()}], State}
|
||||
-> no_change | {ok, [{cert_id(), list()}], State}
|
||||
when State :: #directory_state{}.
|
||||
list_certs(Config, #directory_state{directory_path = DirPath,
|
||||
directory_change_time = ChangeTime}) ->
|
||||
|
|
@ -40,9 +40,9 @@ list_certs(Config, #directory_state{directory_path = DirPath,
|
|||
directory_change_time = NewChangeTime}}
|
||||
end.
|
||||
|
||||
-spec load_cert(cert_id(), map(), Config :: list())
|
||||
-spec load_cert(cert_id(), list(), Config :: list())
|
||||
-> {ok, Cert :: public_key:der_encoded()}.
|
||||
load_cert({FileName, _}, #{}, Config) ->
|
||||
load_cert({FileName, _}, _, Config) ->
|
||||
Path = directory_path(Config),
|
||||
Cert = extract_cert(Path, FileName),
|
||||
rabbit_log:info(
|
||||
|
|
@ -64,7 +64,7 @@ list_certs_0(Path) ->
|
|||
fun(FileName) ->
|
||||
AbsName = filename:absname(FileName, Path),
|
||||
CertId = {FileName, modification_time(AbsName)},
|
||||
{CertId, #{name => FileName}}
|
||||
{CertId, [{name, FileName}]}
|
||||
end,
|
||||
FileNames).
|
||||
|
||||
|
|
@ -92,9 +92,8 @@ default_directory() ->
|
|||
%% directory, then the Mesia database directory, finally the node
|
||||
%% directory where we will place the default whitelist in `Full`.
|
||||
Table = filename:split(rabbit_mnesia:dir()),
|
||||
Mnesia = lists:droplast(Table),
|
||||
Node = lists:droplast(Mnesia),
|
||||
Full = Node ++ ["trust_store", "whitelist"],
|
||||
Node = lists:sublist(Table, length(Table) - 2),
|
||||
Full = Node ++ ["trust_store", "whitelist"],
|
||||
filename:join(Full).
|
||||
|
||||
ensure_directory(Path) ->
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@
|
|||
-define(SERVER_REJECT_CLIENT, {tls_alert, "unknown ca"}).
|
||||
all() ->
|
||||
[
|
||||
{group, non_parallel_tests}
|
||||
{group, file_provider_tests}
|
||||
].
|
||||
|
||||
groups() ->
|
||||
[
|
||||
{non_parallel_tests, [], [
|
||||
{file_provider_tests, [], [
|
||||
library,
|
||||
invasive_SSL_option_change,
|
||||
validation_success_for_AMQP_client,
|
||||
|
|
@ -57,19 +57,31 @@ end_per_suite(Config) ->
|
|||
rabbit_ct_client_helpers:teardown_steps() ++
|
||||
rabbit_ct_broker_helpers:teardown_steps()).
|
||||
|
||||
init_per_group(_, Config) ->
|
||||
Config.
|
||||
init_per_group(file_provider_tests, Config) ->
|
||||
WhitelistDir = filename:join([?config(rmq_certsdir, Config),
|
||||
"trust_store",
|
||||
"file_provider_tests"]),
|
||||
ok = filelib:ensure_dir(WhitelistDir),
|
||||
ok = file:make_dir(WhitelistDir),
|
||||
Config1 = rabbit_ct_helpers:set_config(Config, {whitelist_dir, WhitelistDir}),
|
||||
ok = rabbit_ct_broker_helpers:rpc(Config, 0,
|
||||
?MODULE, change_configuration,
|
||||
[rabbitmq_trust_store, [{directory, WhitelistDir},
|
||||
{refresh_interval, interval()},
|
||||
{providers, [rabbit_trust_store_file_provider]}]]),
|
||||
Config1.
|
||||
|
||||
end_per_group(_, Config) ->
|
||||
Config.
|
||||
|
||||
init_per_testcase(Testcase, Config) ->
|
||||
TestCaseDir = rabbit_ct_helpers:config_to_testcase_name(Config, Testcase),
|
||||
WhitelistDir = filename:join([?config(rmq_certsdir, Config), "trust_store", TestCaseDir]),
|
||||
ok = filelib:ensure_dir(WhitelistDir),
|
||||
WhitelistDir = ?config(whitelist_dir, Config),
|
||||
ok = rabbit_file:recursive_delete([WhitelistDir]),
|
||||
ok = file:make_dir(WhitelistDir),
|
||||
Config1 = rabbit_ct_helpers:set_config(Config, {whitelist_dir, WhitelistDir}),
|
||||
rabbit_ct_helpers:testcase_started(Config1, Testcase).
|
||||
ok = rabbit_ct_broker_helpers:rpc(Config, 0,
|
||||
?MODULE, change_configuration,
|
||||
[rabbitmq_trust_store, [{directory, WhitelistDir}]]),
|
||||
rabbit_ct_helpers:testcase_started(Config, Testcase).
|
||||
|
||||
end_per_testcase(Testcase, Config) ->
|
||||
rabbit_ct_helpers:testcase_finished(Config, Testcase).
|
||||
|
|
@ -178,7 +190,7 @@ validate_chain1(Config) ->
|
|||
Host = rabbit_ct_helpers:get_config(Config, rmq_hostname),
|
||||
|
||||
ok = whitelist(Config, "alice", CertTrusted, KeyTrusted),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
catch rabbit_networking:stop_tcp_listener(Port),
|
||||
ok = rabbit_networking:start_ssl_listener(Port, [{cacerts, [Root]},
|
||||
|
|
@ -221,7 +233,7 @@ validate_longer_chain1(Config) ->
|
|||
Host = rabbit_ct_helpers:get_config(Config, rmq_hostname),
|
||||
|
||||
ok = whitelist(Config, "alice", CertTrusted, KeyTrusted),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
catch rabbit_networking:stop_tcp_listener(Port),
|
||||
ok = rabbit_networking:start_ssl_listener(Port, [{cacerts, [Root]},
|
||||
|
|
@ -287,8 +299,7 @@ validate_chain_without_whitelisted1(Config) ->
|
|||
|
||||
Port = port(Config),
|
||||
Host = rabbit_ct_helpers:get_config(Config, rmq_hostname),
|
||||
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
catch rabbit_networking:stop_tcp_listener(Port),
|
||||
ok = rabbit_networking:start_ssl_listener(Port, [{cacerts, [Root]},
|
||||
|
|
@ -320,7 +331,7 @@ whitelisted_certificate_accepted_from_AMQP_client_regardless_of_validation_to_ro
|
|||
Host = rabbit_ct_helpers:get_config(Config, rmq_hostname),
|
||||
|
||||
ok = whitelist(Config, "alice", CertTrusted, KeyTrusted),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
%% When: Rabbit validates paths with a different root `R` than
|
||||
%% that of the certificate `CertTrusted`.
|
||||
|
|
@ -353,9 +364,7 @@ removed_certificate_denied_from_AMQP_client1(Config) ->
|
|||
Port = port(Config),
|
||||
Host = rabbit_ct_helpers:get_config(Config, rmq_hostname),
|
||||
ok = whitelist(Config, "bob", CertOther, KeyOther),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)},
|
||||
{refresh_interval,
|
||||
{seconds, interval()}}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
%% When: we wait for at least one second (the accuracy of the
|
||||
%% file system's time), remove the whitelisted certificate,
|
||||
|
|
@ -392,10 +401,7 @@ installed_certificate_accepted_from_AMQP_client1(Config) ->
|
|||
|
||||
Port = port(Config),
|
||||
Host = rabbit_ct_helpers:get_config(Config, rmq_hostname),
|
||||
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)},
|
||||
{refresh_interval,
|
||||
{seconds, interval()}}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
%% When: we wait for at least one second (the accuracy of the
|
||||
%% file system's time), add a certificate to the directory,
|
||||
|
|
@ -440,9 +446,7 @@ whitelist_directory_DELTA1(Config) ->
|
|||
|
||||
ok = whitelist(Config, "foo", CertListed1, KeyListed1),
|
||||
ok = whitelist(Config, "bar", CertRevoked, KeyRevoked),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)},
|
||||
{refresh_interval,
|
||||
{seconds, interval()}}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
%% When: we wait for at least one second (the accuracy
|
||||
%% of the file system's time), delete a certificate and
|
||||
|
|
@ -500,8 +504,7 @@ replaced_whitelisted_certificate_should_be_accepted1(Config) ->
|
|||
{key, Key} | cfg()], 1),
|
||||
%% And: the first certificate has been whitelisted
|
||||
ok = whitelist(Config, "bart", CertFirst, KeyFirst),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, whitelist_dir(Config)},
|
||||
{refresh_interval, {seconds, interval()}}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
wait_for_trust_store_refresh(),
|
||||
|
||||
|
|
@ -570,13 +573,12 @@ ignore_corrupt_cert1(Config) ->
|
|||
{Root, Cert, Key} = ct_helper:make_certs(),
|
||||
{_, CertTrusted, KeyTrusted} = ct_helper:make_certs(),
|
||||
|
||||
WhitelistDir = whitelist_dir(Config),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, WhitelistDir}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
ok = whitelist(Config, "alice", CertTrusted, KeyTrusted),
|
||||
|
||||
%% When: Rabbit tries to whitelist the corrupt certificate.
|
||||
ok = whitelist(Config, "corrupt", <<48>>, KeyTrusted),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, WhitelistDir}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
catch rabbit_networking:stop_tcp_listener(Port),
|
||||
ok = rabbit_networking:start_ssl_listener(Port, [{cacerts, [Root]},
|
||||
|
|
@ -608,13 +610,11 @@ ignore_same_cert_with_different_name1(Config) ->
|
|||
{Root, Cert, Key} = ct_helper:make_certs(),
|
||||
{_, CertTrusted, KeyTrusted} = ct_helper:make_certs(),
|
||||
|
||||
WhitelistDir = whitelist_dir(Config),
|
||||
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, WhitelistDir}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
ok = whitelist(Config, "alice", CertTrusted, KeyTrusted),
|
||||
%% When: Rabbit tries to insert the duplicate certificate
|
||||
ok = whitelist(Config, "malice", CertTrusted, KeyTrusted),
|
||||
ok = change_configuration(rabbitmq_trust_store, [{directory, WhitelistDir}]),
|
||||
rabbit_trust_store:refresh(),
|
||||
|
||||
catch rabbit_networking:stop_tcp_listener(Port),
|
||||
ok = rabbit_networking:start_ssl_listener(Port, [{cacerts, [Root]},
|
||||
|
|
@ -636,8 +636,8 @@ ignore_same_cert_with_different_name1(Config) ->
|
|||
list(Config) ->
|
||||
{_Root, Cert, Key} = ct_helper:make_certs(),
|
||||
ok = whitelist(Config, "alice", Cert, Key),
|
||||
ok = rabbit_ct_broker_helpers:rpc(Config, 0,
|
||||
?MODULE, change_configuration, [rabbitmq_trust_store, [{directory, whitelist_dir(Config)}]]),
|
||||
% wait_for_trust_store_refresh(),
|
||||
ok = rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_trust_store, refresh, []),
|
||||
Certs = rabbit_ct_broker_helpers:rpc(Config, 0,
|
||||
rabbit_trust_store, list, []),
|
||||
% only really tests it isn't totally broken.
|
||||
|
|
@ -646,8 +646,7 @@ list(Config) ->
|
|||
disabled_provider_removes_certificates(Config) ->
|
||||
{_Root, Cert, Key} = ct_helper:make_certs(),
|
||||
ok = whitelist(Config, "alice", Cert, Key),
|
||||
ok = rabbit_ct_broker_helpers:rpc(Config, 0,
|
||||
?MODULE, change_configuration, [rabbitmq_trust_store, [{directory, whitelist_dir(Config)}]]),
|
||||
ok = rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_trust_store, refresh, []),
|
||||
|
||||
%% Certificate is there
|
||||
Certs = rabbit_ct_broker_helpers:rpc(Config, 0,
|
||||
|
|
|
|||
Loading…
Reference in New Issue