Merge pull request #7527 from zmstone/0405-5.0-provide-defaults-for-ssl-files
5.0 provide defaults for ssl files
This commit is contained in:
commit
fb7c7dffb7
|
@ -2071,7 +2071,13 @@ common_ssl_opts_schema(Defaults) ->
|
|||
%% @doc Make schema for SSL listener options.
|
||||
%% When it's for ranch listener, an extra field `handshake_timeout' is added.
|
||||
-spec server_ssl_opts_schema(map(), boolean()) -> hocon_schema:field_schema().
|
||||
server_ssl_opts_schema(Defaults, IsRanchListener) ->
|
||||
server_ssl_opts_schema(Defaults1, IsRanchListener) ->
|
||||
Defaults0 = #{
|
||||
cacertfile => emqx:cert_file("cacert.pem"),
|
||||
certfile => emqx:cert_file("cert.pem"),
|
||||
keyfile => emqx:cert_file("key.pem")
|
||||
},
|
||||
Defaults = maps:merge(Defaults0, Defaults1),
|
||||
D = fun(Field) -> maps:get(to_atom(Field), Defaults, undefined) end,
|
||||
Df = fun(Field, Default) -> maps:get(to_atom(Field), Defaults, Default) end,
|
||||
common_ssl_opts_schema(Defaults) ++
|
||||
|
@ -2148,7 +2154,15 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
|
|||
|
||||
%% @doc Make schema for SSL client.
|
||||
-spec client_ssl_opts_schema(map()) -> hocon_schema:field_schema().
|
||||
client_ssl_opts_schema(Defaults) ->
|
||||
client_ssl_opts_schema(Defaults1) ->
|
||||
%% assert
|
||||
true = lists:all(fun(K) -> is_atom(K) end, maps:keys(Defaults1)),
|
||||
Defaults0 = #{
|
||||
cacertfile => emqx:cert_file("cacert.pem"),
|
||||
certfile => emqx:cert_file("client-cert.pem"),
|
||||
keyfile => emqx:cert_file("client-key.pem")
|
||||
},
|
||||
Defaults = maps:merge(Defaults0, Defaults1),
|
||||
common_ssl_opts_schema(Defaults) ++
|
||||
[
|
||||
{"server_name_indication",
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
-export([
|
||||
ensure_ssl_files/2,
|
||||
delete_ssl_files/3,
|
||||
file_content_as_options/1
|
||||
drop_invalid_certs/1,
|
||||
is_valid_pem_file/1
|
||||
]).
|
||||
|
||||
-export([
|
||||
|
@ -40,10 +41,11 @@
|
|||
|
||||
-include("logger.hrl").
|
||||
|
||||
-define(IS_TRUE(Val), ((Val =:= true) or (Val =:= <<"true">>))).
|
||||
-define(IS_FALSE(Val), ((Val =:= false) or (Val =:= <<"false">>))).
|
||||
-define(IS_TRUE(Val), ((Val =:= true) orelse (Val =:= <<"true">>))).
|
||||
-define(IS_FALSE(Val), ((Val =:= false) orelse (Val =:= <<"false">>))).
|
||||
|
||||
-define(SSL_FILE_OPT_NAMES, [<<"keyfile">>, <<"certfile">>, <<"cacertfile">>]).
|
||||
-define(SSL_FILE_OPT_NAMES_A, [keyfile, certfile, cacertfile]).
|
||||
|
||||
%% non-empty string
|
||||
-define(IS_STRING(L), (is_list(L) andalso L =/= [] andalso is_integer(hd(L)))).
|
||||
|
@ -398,35 +400,37 @@ pem_file_name(Dir, Key, Pem) ->
|
|||
hex_str(Bin) ->
|
||||
iolist_to_binary([io_lib:format("~2.16.0b", [X]) || <<X:8>> <= Bin]).
|
||||
|
||||
%% @doc Returns 'true' when the file is a valid pem, otherwise {error, Reason}.
|
||||
is_valid_pem_file(Path) ->
|
||||
case file:read_file(Path) of
|
||||
{ok, Pem} -> is_pem(Pem) orelse {error, not_pem};
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
%% @doc This is to return SSL file content in management APIs.
|
||||
file_content_as_options(undefined) ->
|
||||
undefined;
|
||||
file_content_as_options(#{<<"enable">> := False} = SSL) when ?IS_FALSE(False) ->
|
||||
{ok, maps:without(?SSL_FILE_OPT_NAMES, SSL)};
|
||||
file_content_as_options(#{<<"enable">> := True} = SSL) when ?IS_TRUE(True) ->
|
||||
file_content_as_options(?SSL_FILE_OPT_NAMES, SSL).
|
||||
%% @doc Input and output are both HOCON-checked maps, with invalid SSL
|
||||
%% file options dropped.
|
||||
%% This is to give a feedback to the front-end or management API caller
|
||||
%% so they are forced to upload a cert file, or use an existing file path.
|
||||
-spec drop_invalid_certs(map()) -> map().
|
||||
drop_invalid_certs(#{enable := False} = SSL) when ?IS_FALSE(False) ->
|
||||
maps:without(?SSL_FILE_OPT_NAMES_A, SSL);
|
||||
drop_invalid_certs(#{<<"enable">> := False} = SSL) when ?IS_FALSE(False) ->
|
||||
maps:without(?SSL_FILE_OPT_NAMES, SSL);
|
||||
drop_invalid_certs(#{enable := True} = SSL) when ?IS_TRUE(True) ->
|
||||
drop_invalid_certs(?SSL_FILE_OPT_NAMES_A, SSL);
|
||||
drop_invalid_certs(#{<<"enable">> := True} = SSL) when ?IS_TRUE(True) ->
|
||||
drop_invalid_certs(?SSL_FILE_OPT_NAMES, SSL).
|
||||
|
||||
file_content_as_options([], SSL) ->
|
||||
{ok, SSL};
|
||||
file_content_as_options([Key | Keys], SSL) ->
|
||||
drop_invalid_certs([], SSL) ->
|
||||
SSL;
|
||||
drop_invalid_certs([Key | Keys], SSL) ->
|
||||
case maps:get(Key, SSL, undefined) of
|
||||
undefined ->
|
||||
file_content_as_options(Keys, SSL);
|
||||
drop_invalid_certs(Keys, SSL);
|
||||
Path ->
|
||||
case file:read_file(Path) of
|
||||
{ok, Bin} ->
|
||||
file_content_as_options(Keys, SSL#{Key => Bin});
|
||||
{error, Reason} ->
|
||||
{error, #{
|
||||
file_path => Path,
|
||||
reason => Reason
|
||||
}}
|
||||
case is_valid_pem_file(Path) of
|
||||
true -> SSL;
|
||||
{error, _} -> maps:without([Key], SSL)
|
||||
end
|
||||
end.
|
||||
|
||||
|
|
|
@ -1202,25 +1202,8 @@ fill_defaults(Configs) when is_list(Configs) ->
|
|||
fill_defaults(Config) ->
|
||||
emqx_authn:check_config(Config, #{only_fill_defaults => true}).
|
||||
|
||||
convert_certs(#{ssl := #{enable := true} = SSLOpts} = Config) ->
|
||||
NSSLOpts = lists:foldl(
|
||||
fun(K, Acc) ->
|
||||
case maps:get(K, Acc, undefined) of
|
||||
undefined ->
|
||||
Acc;
|
||||
Filename ->
|
||||
case file:read_file(Filename) of
|
||||
{ok, Bin} ->
|
||||
Acc#{K => Bin};
|
||||
{error, _} ->
|
||||
Acc#{K => Filename}
|
||||
end
|
||||
end
|
||||
end,
|
||||
SSLOpts,
|
||||
[certfile, keyfile, cacertfile]
|
||||
),
|
||||
Config#{ssl => NSSLOpts};
|
||||
convert_certs(#{ssl := SSL} = Config) when SSL =/= undefined ->
|
||||
Config#{ssl := emqx_tls_lib:drop_invalid_certs(SSL)};
|
||||
convert_certs(Config) ->
|
||||
Config.
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ sources(get, _) ->
|
|||
])
|
||||
end;
|
||||
(Source, AccIn) ->
|
||||
lists:append(AccIn, [read_certs(Source)])
|
||||
lists:append(AccIn, [drop_invalid_certs(Source)])
|
||||
end,
|
||||
[],
|
||||
get_raw_sources()
|
||||
|
@ -248,7 +248,7 @@ source(get, #{bindings := #{type := Type}}) ->
|
|||
}}
|
||||
end;
|
||||
[Source] ->
|
||||
{200, read_certs(Source)}
|
||||
{200, drop_invalid_certs(Source)}
|
||||
end;
|
||||
source(put, #{bindings := #{type := <<"file">>}, body := #{<<"type">> := <<"file">>} = Body}) ->
|
||||
update_authz_file(Body);
|
||||
|
@ -498,15 +498,9 @@ update_config(Cmd, Sources) ->
|
|||
}}
|
||||
end.
|
||||
|
||||
read_certs(#{<<"ssl">> := SSL} = Source) ->
|
||||
case emqx_tls_lib:file_content_as_options(SSL) of
|
||||
{error, Reason} ->
|
||||
?SLOG(error, Reason#{msg => failed_to_read_ssl_file}),
|
||||
throw(failed_to_read_ssl_file);
|
||||
{ok, NewSSL} ->
|
||||
Source#{<<"ssl">> => NewSSL}
|
||||
end;
|
||||
read_certs(Source) ->
|
||||
drop_invalid_certs(#{<<"ssl">> := SSL} = Source) when SSL =/= undefined ->
|
||||
Source#{<<"ssl">> => emqx_tls_lib:drop_invalid_certs(SSL)};
|
||||
drop_invalid_certs(Source) ->
|
||||
Source.
|
||||
|
||||
parameters_field() ->
|
||||
|
|
|
@ -94,9 +94,6 @@
|
|||
>>
|
||||
}).
|
||||
|
||||
-define(MATCH_RSA_KEY, <<"-----BEGIN RSA PRIVATE KEY", _/binary>>).
|
||||
-define(MATCH_CERT, <<"-----BEGIN CERTIFICATE", _/binary>>).
|
||||
|
||||
all() ->
|
||||
emqx_common_test_helpers:all(?MODULE).
|
||||
|
||||
|
@ -279,9 +276,9 @@ t_api(_) ->
|
|||
<<"type">> := <<"mongodb">>,
|
||||
<<"ssl">> := #{
|
||||
<<"enable">> := <<"true">>,
|
||||
<<"cacertfile">> := ?MATCH_CERT,
|
||||
<<"certfile">> := ?MATCH_CERT,
|
||||
<<"keyfile">> := ?MATCH_RSA_KEY,
|
||||
<<"cacertfile">> := _,
|
||||
<<"certfile">> := _,
|
||||
<<"keyfile">> := _,
|
||||
<<"verify">> := <<"verify_none">>
|
||||
}
|
||||
},
|
||||
|
@ -313,9 +310,9 @@ t_api(_) ->
|
|||
<<"type">> := <<"mongodb">>,
|
||||
<<"ssl">> := #{
|
||||
<<"enable">> := <<"true">>,
|
||||
<<"cacertfile">> := ?MATCH_CERT,
|
||||
<<"certfile">> := ?MATCH_CERT,
|
||||
<<"keyfile">> := ?MATCH_RSA_KEY,
|
||||
<<"cacertfile">> := _,
|
||||
<<"certfile">> := _,
|
||||
<<"keyfile">> := _,
|
||||
<<"verify">> := <<"verify_none">>
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue