Merge pull request #7519 from zmstone/0405-5.0-sync-ssl-lib-from-4.3
5.0 refactor: delete deprecated emqx_plugin_libs_ssl module
This commit is contained in:
commit
356fbf6ce1
|
@ -69,7 +69,9 @@
|
||||||
remove_config/2,
|
remove_config/2,
|
||||||
reset_config/2,
|
reset_config/2,
|
||||||
data_dir/0,
|
data_dir/0,
|
||||||
certs_dir/0
|
etc_file/1,
|
||||||
|
cert_file/1,
|
||||||
|
mutable_certs_dir/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-define(APP, ?MODULE).
|
-define(APP, ?MODULE).
|
||||||
|
@ -253,8 +255,31 @@ reset_config([RootName | _] = KeyPath, Opts) ->
|
||||||
Error
|
Error
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% @doc Returns the data directory which is set at boot time.
|
||||||
data_dir() ->
|
data_dir() ->
|
||||||
application:get_env(emqx, data_dir, "data").
|
application:get_env(emqx, data_dir, "data").
|
||||||
|
|
||||||
certs_dir() ->
|
%% @doc Returns the directory for user uploaded certificates.
|
||||||
|
mutable_certs_dir() ->
|
||||||
filename:join([data_dir(), certs]).
|
filename:join([data_dir(), certs]).
|
||||||
|
|
||||||
|
%% @doc Returns the absolute path for a PEM certificate file
|
||||||
|
%% which is installed or provisioned by sysadmin in $EMQX_ETC_DIR/certs.
|
||||||
|
cert_file(SubPath) ->
|
||||||
|
filename:join([etc_dir(), "certs", SubPath]).
|
||||||
|
|
||||||
|
%% @doc Returns the absolute path for a file in EMQX's etc dir.
|
||||||
|
%% i.e. for rpm and deb installation, it's /etc/emqx/
|
||||||
|
%% for other installation, it's <install_root>/etc/
|
||||||
|
etc_file(SubPath) ->
|
||||||
|
filename:join([etc_dir(), SubPath]).
|
||||||
|
|
||||||
|
etc_dir() ->
|
||||||
|
%% EMQX_ETC_DIR set by emqx boot script,
|
||||||
|
%% if it's not set, then it must be test environment
|
||||||
|
%% which should uses default path
|
||||||
|
Env = os:getenv("EMQX_ETC_DIR"),
|
||||||
|
case Env =:= "" orelse Env =:= false of
|
||||||
|
true -> "etc";
|
||||||
|
false -> Env
|
||||||
|
end.
|
||||||
|
|
|
@ -34,6 +34,10 @@
|
||||||
file_content_as_options/1
|
file_content_as_options/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
-export([
|
||||||
|
to_client_opts/1
|
||||||
|
]).
|
||||||
|
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
|
|
||||||
-define(IS_TRUE(Val), ((Val =:= true) or (Val =:= <<"true">>))).
|
-define(IS_TRUE(Val), ((Val =:= true) or (Val =:= <<"true">>))).
|
||||||
|
@ -389,7 +393,7 @@ pem_file_name(Dir, Key, Pem) ->
|
||||||
<<CK:8/binary, _/binary>> = crypto:hash(md5, Pem),
|
<<CK:8/binary, _/binary>> = crypto:hash(md5, Pem),
|
||||||
Suffix = hex_str(CK),
|
Suffix = hex_str(CK),
|
||||||
FileName = binary:replace(Key, <<"file">>, <<"-", Suffix/binary>>),
|
FileName = binary:replace(Key, <<"file">>, <<"-", Suffix/binary>>),
|
||||||
filename:join([emqx:certs_dir(), Dir, FileName]).
|
filename:join([emqx:mutable_certs_dir(), Dir, FileName]).
|
||||||
|
|
||||||
hex_str(Bin) ->
|
hex_str(Bin) ->
|
||||||
iolist_to_binary([io_lib:format("~2.16.0b", [X]) || <<X:8>> <= Bin]).
|
iolist_to_binary([io_lib:format("~2.16.0b", [X]) || <<X:8>> <= Bin]).
|
||||||
|
@ -426,6 +430,48 @@ file_content_as_options([Key | Keys], SSL) ->
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% @doc Convert hocon-checked ssl client options (map()) to
|
||||||
|
%% proplist accepted by ssl library.
|
||||||
|
to_client_opts(Opts) ->
|
||||||
|
GetD = fun(Key, Default) -> fuzzy_map_get(Key, Opts, Default) end,
|
||||||
|
Get = fun(Key) -> GetD(Key, undefined) end,
|
||||||
|
KeyFile = ensure_str(Get(keyfile)),
|
||||||
|
CertFile = ensure_str(Get(certfile)),
|
||||||
|
CAFile = ensure_str(Get(cacertfile)),
|
||||||
|
Verify = GetD(verify, verify_none),
|
||||||
|
SNI = ensure_str(Get(server_name_indication)),
|
||||||
|
Versions = integral_versions(Get(versions)),
|
||||||
|
Ciphers = integral_ciphers(Versions, Get(ciphers)),
|
||||||
|
filter([
|
||||||
|
{keyfile, KeyFile},
|
||||||
|
{certfile, CertFile},
|
||||||
|
{cacertfile, CAFile},
|
||||||
|
{verify, Verify},
|
||||||
|
{server_name_indication, SNI},
|
||||||
|
{versions, Versions},
|
||||||
|
{ciphers, Ciphers}
|
||||||
|
]).
|
||||||
|
|
||||||
|
filter([]) -> [];
|
||||||
|
filter([{_, undefined} | T]) -> filter(T);
|
||||||
|
filter([{_, ""} | T]) -> filter(T);
|
||||||
|
filter([H | T]) -> [H | filter(T)].
|
||||||
|
|
||||||
|
-spec fuzzy_map_get(atom() | binary(), map(), any()) -> any().
|
||||||
|
fuzzy_map_get(Key, Options, Default) ->
|
||||||
|
case maps:find(Key, Options) of
|
||||||
|
{ok, Val} ->
|
||||||
|
Val;
|
||||||
|
error when is_atom(Key) ->
|
||||||
|
fuzzy_map_get(atom_to_binary(Key, utf8), Options, Default);
|
||||||
|
error ->
|
||||||
|
Default
|
||||||
|
end.
|
||||||
|
|
||||||
|
ensure_str(undefined) -> undefined;
|
||||||
|
ensure_str(L) when is_list(L) -> L;
|
||||||
|
ensure_str(B) when is_binary(B) -> unicode:characters_to_list(B, utf8).
|
||||||
|
|
||||||
-if(?OTP_RELEASE > 22).
|
-if(?OTP_RELEASE > 22).
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
|
@ -1196,8 +1196,12 @@ convert_certs(#{ssl := #{enable := true} = SSLOpts} = Config) ->
|
||||||
undefined ->
|
undefined ->
|
||||||
Acc;
|
Acc;
|
||||||
Filename ->
|
Filename ->
|
||||||
{ok, Bin} = file:read_file(Filename),
|
case file:read_file(Filename) of
|
||||||
Acc#{K => Bin}
|
{ok, Bin} ->
|
||||||
|
Acc#{K => Bin};
|
||||||
|
{error, _} ->
|
||||||
|
Acc#{K => Filename}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
SSLOpts,
|
SSLOpts,
|
||||||
|
|
|
@ -831,7 +831,7 @@ tr_config_files(Conf) ->
|
||||||
[_ | _] = Files ->
|
[_ | _] = Files ->
|
||||||
Files;
|
Files;
|
||||||
_ ->
|
_ ->
|
||||||
case os:getenv("RUNNER_ETC_DIR") of
|
case os:getenv("EMQX_ETC_DIR") of
|
||||||
false ->
|
false ->
|
||||||
[filename:join([code:lib_dir(emqx), "etc", "emqx.conf"])];
|
[filename:join([code:lib_dir(emqx), "etc", "emqx.conf"])];
|
||||||
Dir ->
|
Dir ->
|
||||||
|
|
|
@ -153,14 +153,14 @@ on_start(InstId, #{base_url := #{scheme := Scheme,
|
||||||
pool_size := PoolSize} = Config) ->
|
pool_size := PoolSize} = Config) ->
|
||||||
?SLOG(info, #{msg => "starting_http_connector",
|
?SLOG(info, #{msg => "starting_http_connector",
|
||||||
connector => InstId, config => Config}),
|
connector => InstId, config => Config}),
|
||||||
{Transport, TransportOpts} = case Scheme of
|
{Transport, TransportOpts} =
|
||||||
http ->
|
case Scheme of
|
||||||
{tcp, []};
|
http ->
|
||||||
https ->
|
{tcp, []};
|
||||||
SSLOpts = emqx_plugin_libs_ssl:save_files_return_opts(
|
https ->
|
||||||
maps:get(ssl, Config), "connectors", InstId),
|
SSLOpts = emqx_tls_lib:to_client_opts(maps:get(ssl, Config)),
|
||||||
{tls, SSLOpts}
|
{tls, SSLOpts}
|
||||||
end,
|
end,
|
||||||
NTransportOpts = emqx_misc:ipv6_probe(TransportOpts),
|
NTransportOpts = emqx_misc:ipv6_probe(TransportOpts),
|
||||||
PoolOpts = [ {host, Host}
|
PoolOpts = [ {host, Host}
|
||||||
, {port, Port}
|
, {port, Port}
|
||||||
|
|
|
@ -57,10 +57,7 @@ on_start(InstId, #{servers := Servers0,
|
||||||
SslOpts = case maps:get(enable, SSL) of
|
SslOpts = case maps:get(enable, SSL) of
|
||||||
true ->
|
true ->
|
||||||
[{ssl, true},
|
[{ssl, true},
|
||||||
{sslopts, emqx_plugin_libs_ssl:save_files_return_opts(
|
{sslopts, emqx_tls_lib:to_client_opts(SSL)}
|
||||||
SSL,
|
|
||||||
"connectors",
|
|
||||||
InstId)}
|
|
||||||
];
|
];
|
||||||
false -> [{ssl, false}]
|
false -> [{ssl, false}]
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -135,11 +135,7 @@ on_start(InstId, Config = #{mongo_type := Type,
|
||||||
SslOpts = case maps:get(enable, SSL) of
|
SslOpts = case maps:get(enable, SSL) of
|
||||||
true ->
|
true ->
|
||||||
[{ssl, true},
|
[{ssl, true},
|
||||||
{ssl_opts,
|
{ssl_opts, emqx_tls_lib:to_client_opts(SSL)}
|
||||||
emqx_plugin_libs_ssl:save_files_return_opts(
|
|
||||||
SSL,
|
|
||||||
"connectors",
|
|
||||||
InstId)}
|
|
||||||
];
|
];
|
||||||
false -> [{ssl, false}]
|
false -> [{ssl, false}]
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -67,10 +67,11 @@ on_start(InstId, #{server := {Host, Port},
|
||||||
?SLOG(info, #{msg => "starting_mysql_connector",
|
?SLOG(info, #{msg => "starting_mysql_connector",
|
||||||
connector => InstId, config => Config}),
|
connector => InstId, config => Config}),
|
||||||
SslOpts = case maps:get(enable, SSL) of
|
SslOpts = case maps:get(enable, SSL) of
|
||||||
true ->
|
true ->
|
||||||
[{ssl, emqx_plugin_libs_ssl:save_files_return_opts(SSL, "connectors", InstId)}];
|
[{ssl, emqx_tls_lib:to_client_opts(SSL)}];
|
||||||
false -> []
|
false ->
|
||||||
end,
|
[]
|
||||||
|
end,
|
||||||
Options = [{host, Host},
|
Options = [{host, Host},
|
||||||
{port, Port},
|
{port, Port},
|
||||||
{user, User},
|
{user, User},
|
||||||
|
|
|
@ -80,8 +80,7 @@ on_start(InstId, #{server := {Host, Port},
|
||||||
SslOpts = case maps:get(enable, SSL) of
|
SslOpts = case maps:get(enable, SSL) of
|
||||||
true ->
|
true ->
|
||||||
[{ssl, true},
|
[{ssl, true},
|
||||||
{ssl_opts,
|
{ssl_opts, emqx_tls_lib:to_client_opts(SSL)}];
|
||||||
emqx_plugin_libs_ssl:save_files_return_opts(SSL, "connectors", InstId)}];
|
|
||||||
false ->
|
false ->
|
||||||
[{ssl, false}]
|
[{ssl, false}]
|
||||||
end,
|
end,
|
||||||
|
|
|
@ -116,9 +116,7 @@ on_start(InstId, #{redis_type := Type,
|
||||||
Options = case maps:get(enable, SSL) of
|
Options = case maps:get(enable, SSL) of
|
||||||
true ->
|
true ->
|
||||||
[{ssl, true},
|
[{ssl, true},
|
||||||
{ssl_options,
|
{ssl_options, emqx_tls_lib:to_client_opts(SSL)}];
|
||||||
emqx_plugin_libs_ssl:save_files_return_opts(SSL, "connectors", InstId)}
|
|
||||||
];
|
|
||||||
false -> [{ssl, false}]
|
false -> [{ssl, false}]
|
||||||
end ++ [{sentinel, maps:get(sentinel, Config, undefined)}],
|
end ++ [{sentinel, maps:get(sentinel, Config, undefined)}],
|
||||||
PoolName = emqx_plugin_libs_pool:pool_name(InstId),
|
PoolName = emqx_plugin_libs_pool:pool_name(InstId),
|
||||||
|
|
|
@ -171,6 +171,11 @@ params_server_name_in_path() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
server_conf_schema() ->
|
server_conf_schema() ->
|
||||||
|
SSL = #{ enable => false
|
||||||
|
, cacertfile => emqx:cert_file(<<"cacert.pem">>)
|
||||||
|
, certfile => emqx:cert_file(<<"cert.pem">>)
|
||||||
|
, keyfile => emqx:cert_file(<<"key.pem">>)
|
||||||
|
},
|
||||||
schema_with_example(ref(server_config),
|
schema_with_example(ref(server_config),
|
||||||
#{ name => "default"
|
#{ name => "default"
|
||||||
, enable => true
|
, enable => true
|
||||||
|
@ -179,11 +184,7 @@ server_conf_schema() ->
|
||||||
, failed_action => deny
|
, failed_action => deny
|
||||||
, auto_reconnect => "60s"
|
, auto_reconnect => "60s"
|
||||||
, pool_size => 8
|
, pool_size => 8
|
||||||
, ssl => #{ enable => false
|
, ssl => SSL
|
||||||
, cacertfile => <<"{{ platform_etc_dir }}/certs/cacert.pem">>
|
|
||||||
, certfile => <<"{{ platform_etc_dir }}/certs/cert.pem">>
|
|
||||||
, keyfile => <<"{{ platform_etc_dir }}/certs/key.pem">>
|
|
||||||
}
|
|
||||||
}).
|
}).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
|
@ -600,7 +600,7 @@ examples_gateway_confs() ->
|
||||||
enable_stats => true,
|
enable_stats => true,
|
||||||
idle_timeout => <<"30s">>,
|
idle_timeout => <<"30s">>,
|
||||||
mountpoint => <<"lwm2m/">>,
|
mountpoint => <<"lwm2m/">>,
|
||||||
xml_dir => <<"etc/lwm2m_xml">>,
|
xml_dir => emqx:etc_file(<<"lwm2m_xml">>),
|
||||||
lifetime_min => <<"1s">>,
|
lifetime_min => <<"1s">>,
|
||||||
lifetime_max => <<"86400s">>,
|
lifetime_max => <<"86400s">>,
|
||||||
qmode_time_window => <<"22s">>,
|
qmode_time_window => <<"22s">>,
|
||||||
|
@ -719,7 +719,7 @@ examples_update_gateway_confs() ->
|
||||||
enable_stats => true,
|
enable_stats => true,
|
||||||
idle_timeout => <<"30s">>,
|
idle_timeout => <<"30s">>,
|
||||||
mountpoint => <<"lwm2m2/">>,
|
mountpoint => <<"lwm2m2/">>,
|
||||||
xml_dir => <<"etc/lwm2m_xml">>,
|
xml_dir => emqx:etc_file(<<"lwm2m_xml">>),
|
||||||
lifetime_min => <<"1s">>,
|
lifetime_min => <<"1s">>,
|
||||||
lifetime_max => <<"86400s">>,
|
lifetime_max => <<"86400s">>,
|
||||||
qmode_time_window => <<"22s">>,
|
qmode_time_window => <<"22s">>,
|
||||||
|
|
|
@ -833,9 +833,9 @@ examples_listener() ->
|
||||||
<<"tlsv1.1">>,
|
<<"tlsv1.1">>,
|
||||||
<<"tlsv1">>
|
<<"tlsv1">>
|
||||||
],
|
],
|
||||||
cacertfile => <<"etc/certs/cacert.pem">>,
|
cacertfile => emqx:cert_file(<<"cacert.pem">>),
|
||||||
certfile => <<"etc/certs/cert.pem">>,
|
certfile => emqx:cert_file(<<"cert.pem">>),
|
||||||
keyfile => <<"etc/certs/key.pem">>,
|
keyfile => emqx:cert_file(<<"key.pem">>),
|
||||||
verify => <<"verify_none">>,
|
verify => <<"verify_none">>,
|
||||||
fail_if_no_peer_cert => false
|
fail_if_no_peer_cert => false
|
||||||
},
|
},
|
||||||
|
@ -879,9 +879,9 @@ examples_listener() ->
|
||||||
dtls =>
|
dtls =>
|
||||||
#{
|
#{
|
||||||
versions => [<<"dtlsv1.2">>, <<"dtlsv1">>],
|
versions => [<<"dtlsv1.2">>, <<"dtlsv1">>],
|
||||||
cacertfile => <<"etc/certs/cacert.pem">>,
|
cacertfile => emqx:cert_file(<<"cacert.pem">>),
|
||||||
certfile => <<"etc/certs/cert.pem">>,
|
certfile => emqx:cert_file(<<"cert.pem">>),
|
||||||
keyfile => <<"etc/certs/key.pem">>,
|
keyfile => emqx:cert_file(<<"key.pem">>),
|
||||||
verify => <<"verify_none">>,
|
verify => <<"verify_none">>,
|
||||||
fail_if_no_peer_cert => false
|
fail_if_no_peer_cert => false
|
||||||
},
|
},
|
||||||
|
@ -906,9 +906,9 @@ examples_listener() ->
|
||||||
dtls =>
|
dtls =>
|
||||||
#{
|
#{
|
||||||
versions => [<<"dtlsv1.2">>, <<"dtlsv1">>],
|
versions => [<<"dtlsv1.2">>, <<"dtlsv1">>],
|
||||||
cacertfile => <<"etc/certs/cacert.pem">>,
|
cacertfile => emqx:cert_file(<<"cacert.pem">>),
|
||||||
certfile => <<"etc/certs/cert.pem">>,
|
certfile => emqx:cert_file(<<"cert.pem">>),
|
||||||
keyfile => <<"etc/certs/key.pem">>,
|
keyfile => emqx:cert_file(<<"key.pem">>),
|
||||||
verify => <<"verify_none">>,
|
verify => <<"verify_none">>,
|
||||||
user_lookup_fun => <<"emqx_tls_psk:lookup">>,
|
user_lookup_fun => <<"emqx_tls_psk:lookup">>,
|
||||||
ciphers =>
|
ciphers =>
|
||||||
|
|
|
@ -290,7 +290,7 @@ fields(lwm2m) ->
|
||||||
sc(
|
sc(
|
||||||
binary(),
|
binary(),
|
||||||
#{
|
#{
|
||||||
default => "etc/lwm2m_xml",
|
default => emqx:etc_file("lwm2m_xml"),
|
||||||
required => true,
|
required => true,
|
||||||
desc => "The Directory for LwM2M Resource definition"
|
desc => "The Directory for LwM2M Resource definition"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,3 @@
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
-module(emqx_plugin_libs).
|
-module(emqx_plugin_libs).
|
||||||
|
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing, software
|
|
||||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
%% See the License for the specific language governing permissions and
|
|
||||||
%% limitations under the License.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(emqx_plugin_libs_ssl).
|
|
||||||
|
|
||||||
-export([save_files_return_opts/2,
|
|
||||||
save_files_return_opts/3,
|
|
||||||
save_file/2
|
|
||||||
]).
|
|
||||||
|
|
||||||
-type file_input_key() :: atom() | binary(). %% <<"file">> | <<"filename">>
|
|
||||||
-type file_input() :: #{file_input_key() => binary()}.
|
|
||||||
|
|
||||||
%% options are below paris
|
|
||||||
%% <<"keyfile">> => file_input()
|
|
||||||
%% <<"certfile">> => file_input()
|
|
||||||
%% <<"cafile">> => file_input() %% backward compatible
|
|
||||||
%% <<"cacertfile">> => file_input()
|
|
||||||
%% <<"verify">> => verify_none | verify_peer
|
|
||||||
%% <<"tls_versions">> => binary()
|
|
||||||
%% <<"ciphers">> => binary()
|
|
||||||
-type opts_key() :: binary() | atom().
|
|
||||||
-type opts_input() :: #{opts_key() => term()}.
|
|
||||||
|
|
||||||
-type opt_key() :: keyfile | certfile | cacertfile | verify | versions | ciphers.
|
|
||||||
-type opt_value() :: term().
|
|
||||||
-type opts() :: [{opt_key(), opt_value()}].
|
|
||||||
|
|
||||||
%% @doc Parse ssl options input.
|
|
||||||
%% If the input contains file content, save the files in the given dir.
|
|
||||||
%% Returns ssl options for Erlang's ssl application.
|
|
||||||
%%
|
|
||||||
%% For SSL files in the input Option, it can either be a file path
|
|
||||||
%% or a map like `#{filename := FileName, file := Content}`.
|
|
||||||
%% In case it's a map, the file is saved in EMQX's `data_dir'
|
|
||||||
%% (unless `SubDir' is an absolute path).
|
|
||||||
%% NOTE: This function is now deprecated, use emqx_tls_lib:ensure_ssl_files/2 instead.
|
|
||||||
-spec save_files_return_opts(opts_input(), atom() | string() | binary(),
|
|
||||||
string() | binary()) -> opts().
|
|
||||||
save_files_return_opts(Options, SubDir, ResId) ->
|
|
||||||
Dir = filename:join([emqx:data_dir(), SubDir, ResId]),
|
|
||||||
save_files_return_opts(Options, Dir).
|
|
||||||
|
|
||||||
%% @doc Parse ssl options input.
|
|
||||||
%% If the input contains file content, save the files in the given dir.
|
|
||||||
%% Returns ssl options for Erlang's ssl application.
|
|
||||||
%%
|
|
||||||
%% For SSL files in the input Option, it can either be a file path
|
|
||||||
%% or a map like `#{filename := FileName, file := Content}`.
|
|
||||||
%% In case it's a map, the file is saved in EMQX's `data_dir'
|
|
||||||
%% (unless `SubDir' is an absolute path).
|
|
||||||
%% NOTE: This function is now deprecated, use emqx_tls_lib:ensure_ssl_files/2 instead.
|
|
||||||
-spec save_files_return_opts(opts_input(), file:name_all()) -> opts().
|
|
||||||
save_files_return_opts(Options, Dir) ->
|
|
||||||
GetD = fun(Key, Default) -> fuzzy_map_get(Key, Options, Default) end,
|
|
||||||
Get = fun(Key) -> GetD(Key, undefined) end,
|
|
||||||
KeyFile = Get(keyfile),
|
|
||||||
CertFile = Get(certfile),
|
|
||||||
CAFile = Get(cacertfile),
|
|
||||||
Key = do_save_file(KeyFile, Dir),
|
|
||||||
Cert = do_save_file(CertFile, Dir),
|
|
||||||
CA = do_save_file(CAFile, Dir),
|
|
||||||
Verify = GetD(verify, verify_none),
|
|
||||||
SNI = Get(server_name_indication),
|
|
||||||
Versions = emqx_tls_lib:integral_versions(Get(versions)),
|
|
||||||
Ciphers = emqx_tls_lib:integral_ciphers(Versions, Get(ciphers)),
|
|
||||||
filter([{keyfile, Key}, {certfile, Cert}, {cacertfile, CA},
|
|
||||||
{verify, Verify}, {server_name_indication, SNI},
|
|
||||||
{versions, Versions}, {ciphers, Ciphers}]).
|
|
||||||
|
|
||||||
%% @doc Save a key or certificate file in data dir,
|
|
||||||
%% and return path of the saved file.
|
|
||||||
%% empty string is returned if the input is empty.
|
|
||||||
-spec save_file(file_input(), atom() | string() | binary()) -> string().
|
|
||||||
save_file(Param, SubDir) ->
|
|
||||||
Dir = filename:join([emqx:data_dir(), SubDir]),
|
|
||||||
do_save_file(Param, Dir).
|
|
||||||
|
|
||||||
filter([]) -> [];
|
|
||||||
filter([{_, undefined} | T]) -> filter(T);
|
|
||||||
filter([{_, ""} | T]) -> filter(T);
|
|
||||||
filter([H | T]) -> [H | filter(T)].
|
|
||||||
|
|
||||||
do_save_file(#{filename := FileName, file := Content}, Dir)
|
|
||||||
when FileName =/= undefined andalso Content =/= undefined ->
|
|
||||||
do_save_file(ensure_str(FileName), iolist_to_binary(Content), Dir);
|
|
||||||
do_save_file(FilePath, _) when is_list(FilePath) ->
|
|
||||||
FilePath;
|
|
||||||
do_save_file(FilePath, _) when is_binary(FilePath) ->
|
|
||||||
ensure_str(FilePath);
|
|
||||||
do_save_file(_, _) -> "".
|
|
||||||
|
|
||||||
do_save_file("", _, _Dir) -> ""; %% ignore
|
|
||||||
do_save_file(_, <<>>, _Dir) -> ""; %% ignore
|
|
||||||
do_save_file(FileName, Content, Dir) ->
|
|
||||||
FullFilename = filename:join([Dir, FileName]),
|
|
||||||
ok = filelib:ensure_dir(FullFilename),
|
|
||||||
case file:write_file(FullFilename, Content) of
|
|
||||||
ok ->
|
|
||||||
ensure_str(FullFilename);
|
|
||||||
{error, Reason} ->
|
|
||||||
logger:error("failed_to_save_ssl_file ~ts: ~0p", [FullFilename, Reason]),
|
|
||||||
error({"failed_to_save_ssl_file", FullFilename, Reason})
|
|
||||||
end.
|
|
||||||
|
|
||||||
ensure_str(L) when is_list(L) -> L;
|
|
||||||
ensure_str(B) when is_binary(B) -> unicode:characters_to_list(B, utf8).
|
|
||||||
|
|
||||||
-spec fuzzy_map_get(atom() | binary(), map(), any()) -> any().
|
|
||||||
fuzzy_map_get(Key, Options, Default) ->
|
|
||||||
case maps:find(Key, Options) of
|
|
||||||
{ok, Val} -> Val;
|
|
||||||
error when is_atom(Key) ->
|
|
||||||
fuzzy_map_get(atom_to_binary(Key, utf8), Options, Default);
|
|
||||||
error -> Default
|
|
||||||
end.
|
|
|
@ -1,78 +0,0 @@
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
%% Copyright (c) 2021-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
||||||
%%
|
|
||||||
%% Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
|
||||||
%%
|
|
||||||
%% Unless required by applicable law or agreed to in writing, software
|
|
||||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
%% See the License for the specific language governing permissions and
|
|
||||||
%% limitations under the License.
|
|
||||||
%%--------------------------------------------------------------------
|
|
||||||
|
|
||||||
-module(emqx_plugin_libs_ssl_tests).
|
|
||||||
|
|
||||||
-include_lib("proper/include/proper.hrl").
|
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
|
||||||
|
|
||||||
no_crash_test_() ->
|
|
||||||
Opts = [{numtests, 1000}, {to_file, user}],
|
|
||||||
{timeout, 60,
|
|
||||||
fun() -> ?assert(proper:quickcheck(prop_run(), Opts)) end}.
|
|
||||||
|
|
||||||
prop_run() ->
|
|
||||||
?FORALL(Generated, prop_opts_input(), test_opts_input(Generated)).
|
|
||||||
|
|
||||||
%% proper type to generate input value.
|
|
||||||
prop_opts_input() ->
|
|
||||||
[{keyfile, prop_file_or_content()},
|
|
||||||
{certfile, prop_file_or_content()},
|
|
||||||
{cacertfile, prop_file_or_content()},
|
|
||||||
{verify, proper_types:oneof([verify_none, verify_peer])},
|
|
||||||
{versions, prop_tls_versions()},
|
|
||||||
{ciphers, prop_tls_ciphers()},
|
|
||||||
{other, proper_types:binary()}].
|
|
||||||
|
|
||||||
prop_file_or_content() ->
|
|
||||||
proper_types:oneof([prop_cert_file_name(),
|
|
||||||
{prop_cert_file_name(), proper_types:binary()}]).
|
|
||||||
|
|
||||||
prop_cert_file_name() ->
|
|
||||||
proper_types:oneof(["certname1", <<"certname2">>, "", <<>>, undefined]).
|
|
||||||
|
|
||||||
prop_tls_versions() ->
|
|
||||||
proper_types:oneof(["tlsv1.3",
|
|
||||||
<<"tlsv1.3,tlsv1.2">>,
|
|
||||||
"tlsv1.2 , tlsv1.1",
|
|
||||||
"1.2",
|
|
||||||
"v1.3",
|
|
||||||
"",
|
|
||||||
<<>>,
|
|
||||||
undefined]).
|
|
||||||
|
|
||||||
prop_tls_ciphers() ->
|
|
||||||
proper_types:oneof(["TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256",
|
|
||||||
<<>>,
|
|
||||||
"",
|
|
||||||
undefined]).
|
|
||||||
|
|
||||||
test_opts_input(Inputs) ->
|
|
||||||
KF = fun(K) -> {_, V} = lists:keyfind(K, 1, Inputs), V end,
|
|
||||||
Generated = #{<<"keyfile">> => file_or_content(KF(keyfile)),
|
|
||||||
<<"certfile">> => file_or_content(KF(certfile)),
|
|
||||||
<<"cafile">> => file_or_content(KF(cacertfile)),
|
|
||||||
<<"verify">> => file_or_content(KF(verify)),
|
|
||||||
<<"tls_versions">> => KF(versions),
|
|
||||||
<<"ciphers">> => KF(ciphers),
|
|
||||||
<<"other">> => KF(other)},
|
|
||||||
_ = emqx_plugin_libs_ssl:save_files_return_opts(Generated, "test-data"),
|
|
||||||
true.
|
|
||||||
|
|
||||||
file_or_content({Name, Content}) ->
|
|
||||||
#{<<"file">> => Content, <<"filename">> => Name};
|
|
||||||
file_or_content(Name) ->
|
|
||||||
Name.
|
|
10
bin/emqx
10
bin/emqx
|
@ -15,7 +15,7 @@ ROOT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/..; pwd -P)"
|
||||||
|
|
||||||
# defined in emqx_vars
|
# defined in emqx_vars
|
||||||
export RUNNER_ROOT_DIR
|
export RUNNER_ROOT_DIR
|
||||||
export RUNNER_ETC_DIR
|
export EMQX_ETC_DIR
|
||||||
export REL_VSN
|
export REL_VSN
|
||||||
export SCHEMA_MOD
|
export SCHEMA_MOD
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ call_hocon() {
|
||||||
|
|
||||||
get_config_value() {
|
get_config_value() {
|
||||||
path_to_value="$1"
|
path_to_value="$1"
|
||||||
call_hocon -s "$SCHEMA_MOD" -c "$RUNNER_ETC_DIR"/emqx.conf get "$path_to_value" | tr -d \"
|
call_hocon -s "$SCHEMA_MOD" -c "$EMQX_ETC_DIR"/emqx.conf get "$path_to_value" | tr -d \"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_license() {
|
check_license() {
|
||||||
|
@ -418,7 +418,7 @@ generate_config() {
|
||||||
## NOTE: the generate command merges environment variables to the base config (emqx.conf),
|
## NOTE: the generate command merges environment variables to the base config (emqx.conf),
|
||||||
## but does not include the cluster-override.conf and local-override.conf
|
## but does not include the cluster-override.conf and local-override.conf
|
||||||
## meaning, certain overrides will not be mapped to app.<time>.config file
|
## meaning, certain overrides will not be mapped to app.<time>.config file
|
||||||
call_hocon -v -t "$NOW_TIME" -s "$SCHEMA_MOD" -c "$RUNNER_ETC_DIR"/emqx.conf -d "$DATA_DIR"/configs generate
|
call_hocon -v -t "$NOW_TIME" -s "$SCHEMA_MOD" -c "$EMQX_ETC_DIR"/emqx.conf -d "$DATA_DIR"/configs generate
|
||||||
|
|
||||||
## filenames are per-hocon convention
|
## filenames are per-hocon convention
|
||||||
local CONF_FILE="$CONFIGS_DIR/app.$NOW_TIME.config"
|
local CONF_FILE="$CONFIGS_DIR/app.$NOW_TIME.config"
|
||||||
|
@ -433,7 +433,7 @@ generate_config() {
|
||||||
|
|
||||||
## Merge hocon generated *.args into the vm.args
|
## Merge hocon generated *.args into the vm.args
|
||||||
TMP_ARG_FILE="$CONFIGS_DIR/vm.args.tmp"
|
TMP_ARG_FILE="$CONFIGS_DIR/vm.args.tmp"
|
||||||
cp "$RUNNER_ETC_DIR/vm.args" "$TMP_ARG_FILE"
|
cp "$EMQX_ETC_DIR/vm.args" "$TMP_ARG_FILE"
|
||||||
echo "" >> "$TMP_ARG_FILE"
|
echo "" >> "$TMP_ARG_FILE"
|
||||||
echo "-pa ${REL_DIR}/consolidated" >> "$TMP_ARG_FILE"
|
echo "-pa ${REL_DIR}/consolidated" >> "$TMP_ARG_FILE"
|
||||||
## read lines from generated vm.<time>.args file
|
## read lines from generated vm.<time>.args file
|
||||||
|
@ -649,7 +649,7 @@ if [ -z "$COOKIE" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$COOKIE" ]; then
|
if [ -z "$COOKIE" ]; then
|
||||||
die "Please set node.cookie in $RUNNER_ETC_DIR/emqx.conf or override from environment variable EMQX_NODE__COOKIE"
|
die "Please set node.cookie in $EMQX_ETC_DIR/emqx.conf or override from environment variable EMQX_NODE__COOKIE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd "$ROOTDIR"
|
cd "$ROOTDIR"
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
@set "rel_dir=%rel_root_dir%\releases\%rel_vsn%"
|
@set "rel_dir=%rel_root_dir%\releases\%rel_vsn%"
|
||||||
@set "RUNNER_ROOT_DIR=%rel_root_dir%"
|
@set "RUNNER_ROOT_DIR=%rel_root_dir%"
|
||||||
:: hard code etc dir
|
:: hard code etc dir
|
||||||
@set "RUNNER_ETC_DIR=%rel_root_dir%\etc"
|
@set "EMQX_ETC_DIR=%rel_root_dir%\etc"
|
||||||
@set "etc_dir=%rel_root_dir%\etc"
|
@set "etc_dir=%rel_root_dir%\etc"
|
||||||
@set "lib_dir=%rel_root_dir%\lib"
|
@set "lib_dir=%rel_root_dir%\lib"
|
||||||
@set "emqx_conf=%etc_dir%\emqx.conf"
|
@set "emqx_conf=%etc_dir%\emqx.conf"
|
||||||
|
|
2
build
2
build
|
@ -281,6 +281,8 @@ case "$ARTIFACT" in
|
||||||
make_tgz
|
make_tgz
|
||||||
;;
|
;;
|
||||||
pkg)
|
pkg)
|
||||||
|
# this only affect build artifacts, such as schema doc
|
||||||
|
export EMQX_ETC_DIR='/etc/emqx/'
|
||||||
if [ -z "${PKGERDIR:-}" ]; then
|
if [ -z "${PKGERDIR:-}" ]; then
|
||||||
log "Skipped making deb/rpm package for $SYSTEM"
|
log "Skipped making deb/rpm package for $SYSTEM"
|
||||||
exit 0
|
exit 0
|
||||||
|
|
4
mix.exs
4
mix.exs
|
@ -539,7 +539,7 @@ defmodule EMQXUmbrella.MixProject do
|
||||||
platform_plugins_dir: "plugins",
|
platform_plugins_dir: "plugins",
|
||||||
runner_root_dir: "$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)",
|
runner_root_dir: "$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)",
|
||||||
runner_bin_dir: "$RUNNER_ROOT_DIR/bin",
|
runner_bin_dir: "$RUNNER_ROOT_DIR/bin",
|
||||||
runner_etc_dir: "$RUNNER_ROOT_DIR/etc",
|
emqx_etc_dir: "$RUNNER_ROOT_DIR/etc",
|
||||||
runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
|
runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
|
||||||
runner_log_dir: "$RUNNER_ROOT_DIR/log",
|
runner_log_dir: "$RUNNER_ROOT_DIR/log",
|
||||||
runner_user: "",
|
runner_user: "",
|
||||||
|
@ -565,7 +565,7 @@ defmodule EMQXUmbrella.MixProject do
|
||||||
platform_plugins_dir: "/var/lib/emqx/plugins",
|
platform_plugins_dir: "/var/lib/emqx/plugins",
|
||||||
runner_root_dir: "/usr/lib/emqx",
|
runner_root_dir: "/usr/lib/emqx",
|
||||||
runner_bin_dir: "/usr/bin",
|
runner_bin_dir: "/usr/bin",
|
||||||
runner_etc_dir: "/etc/emqx",
|
emqx_etc_dir: "/etc/emqx",
|
||||||
runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
|
runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
|
||||||
runner_log_dir: "/var/log/emqx",
|
runner_log_dir: "/var/log/emqx",
|
||||||
runner_user: "emqx",
|
runner_user: "emqx",
|
||||||
|
|
|
@ -83,3 +83,5 @@
|
||||||
emqx_exhook_pb, % generated code for protobuf
|
emqx_exhook_pb, % generated code for protobuf
|
||||||
emqx_exproto_pb % generated code for protobuf
|
emqx_exproto_pb % generated code for protobuf
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
|
{project_plugins, [erlfmt]}.
|
||||||
|
|
|
@ -275,7 +275,7 @@ overlay_vars_pkg(bin) ->
|
||||||
, {platform_plugins_dir, "plugins"}
|
, {platform_plugins_dir, "plugins"}
|
||||||
, {runner_root_dir, "$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"}
|
, {runner_root_dir, "$(cd $(dirname $(readlink $0 || echo $0))/..; pwd -P)"}
|
||||||
, {runner_bin_dir, "$RUNNER_ROOT_DIR/bin"}
|
, {runner_bin_dir, "$RUNNER_ROOT_DIR/bin"}
|
||||||
, {runner_etc_dir, "$RUNNER_ROOT_DIR/etc"}
|
, {emqx_etc_dir, "$RUNNER_ROOT_DIR/etc"}
|
||||||
, {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"}
|
, {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"}
|
||||||
, {runner_log_dir, "$RUNNER_ROOT_DIR/log"}
|
, {runner_log_dir, "$RUNNER_ROOT_DIR/log"}
|
||||||
, {runner_user, ""}
|
, {runner_user, ""}
|
||||||
|
@ -290,7 +290,7 @@ overlay_vars_pkg(pkg) ->
|
||||||
, {platform_plugins_dir, "/var/lib/emqx/plugins"}
|
, {platform_plugins_dir, "/var/lib/emqx/plugins"}
|
||||||
, {runner_root_dir, "/usr/lib/emqx"}
|
, {runner_root_dir, "/usr/lib/emqx"}
|
||||||
, {runner_bin_dir, "/usr/bin"}
|
, {runner_bin_dir, "/usr/bin"}
|
||||||
, {runner_etc_dir, "/etc/emqx"}
|
, {emqx_etc_dir, "/etc/emqx"}
|
||||||
, {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"}
|
, {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"}
|
||||||
, {runner_log_dir, "/var/log/emqx"}
|
, {runner_log_dir, "/var/log/emqx"}
|
||||||
, {runner_user, "emqx"}
|
, {runner_user, "emqx"}
|
||||||
|
|
|
@ -10,7 +10,7 @@ RUNNER_ROOT_DIR="{{ runner_root_dir }}"
|
||||||
RUNNER_BIN_DIR="{{ runner_bin_dir }}"
|
RUNNER_BIN_DIR="{{ runner_bin_dir }}"
|
||||||
RUNNER_LOG_DIR="{{ runner_log_dir }}"
|
RUNNER_LOG_DIR="{{ runner_log_dir }}"
|
||||||
RUNNER_LIB_DIR="{{ runner_lib_dir }}"
|
RUNNER_LIB_DIR="{{ runner_lib_dir }}"
|
||||||
RUNNER_ETC_DIR="{{ runner_etc_dir }}"
|
EMQX_ETC_DIR="{{ emqx_etc_dir }}"
|
||||||
RUNNER_USER="{{ runner_user }}"
|
RUNNER_USER="{{ runner_user }}"
|
||||||
IS_ELIXIR="{{ is_elixir }}"
|
IS_ELIXIR="{{ is_elixir }}"
|
||||||
SCHEMA_MOD="{{ emqx_schema_mod }}"
|
SCHEMA_MOD="{{ emqx_schema_mod }}"
|
||||||
|
|
Loading…
Reference in New Issue