fix: allow empty cacertfile pem

This commit is contained in:
zhongwencool 2023-08-16 20:15:21 +08:00
parent b23da691c0
commit b733adca06
3 changed files with 36 additions and 16 deletions

View File

@ -2001,8 +2001,8 @@ filter(Opts) ->
%% SSL listener and client. %% SSL listener and client.
-spec common_ssl_opts_schema(map(), server | client) -> hocon_schema:field_schema(). -spec common_ssl_opts_schema(map(), server | client) -> hocon_schema:field_schema().
common_ssl_opts_schema(Defaults, Type) -> common_ssl_opts_schema(Defaults, Type) ->
D = fun(Field) -> maps:get(to_atom(Field), Defaults, undefined) end, D = fun(Field) -> maps:get(Field, Defaults, undefined) end,
Df = fun(Field, Default) -> maps:get(to_atom(Field), Defaults, Default) end, Df = fun(Field, Default) -> maps:get(Field, Defaults, Default) end,
Collection = maps:get(versions, Defaults, tls_all_available), Collection = maps:get(versions, Defaults, tls_all_available),
DefaultVersions = default_tls_vsns(Collection), DefaultVersions = default_tls_vsns(Collection),
[ [
@ -2045,7 +2045,7 @@ common_ssl_opts_schema(Defaults, Type) ->
sc( sc(
hoconsc:enum([verify_peer, verify_none]), hoconsc:enum([verify_peer, verify_none]),
#{ #{
default => Df("verify", verify_none), default => Df(verify, verify_none),
desc => ?DESC(common_ssl_opts_schema_verify) desc => ?DESC(common_ssl_opts_schema_verify)
} }
)}, )},
@ -2053,7 +2053,7 @@ common_ssl_opts_schema(Defaults, Type) ->
sc( sc(
boolean(), boolean(),
#{ #{
default => Df("reuse_sessions", true), default => Df(reuse_sessions, true),
desc => ?DESC(common_ssl_opts_schema_reuse_sessions) desc => ?DESC(common_ssl_opts_schema_reuse_sessions)
} }
)}, )},
@ -2061,7 +2061,7 @@ common_ssl_opts_schema(Defaults, Type) ->
sc( sc(
non_neg_integer(), non_neg_integer(),
#{ #{
default => Df("depth", 10), default => Df(depth, 10),
desc => ?DESC(common_ssl_opts_schema_depth) desc => ?DESC(common_ssl_opts_schema_depth)
} }
)}, )},
@ -2088,7 +2088,7 @@ common_ssl_opts_schema(Defaults, Type) ->
validator => fun(Input) -> validate_tls_versions(Collection, Input) end validator => fun(Input) -> validate_tls_versions(Collection, Input) end
} }
)}, )},
{"ciphers", ciphers_schema(D("ciphers"))}, {"ciphers", ciphers_schema(D(ciphers))},
{"user_lookup_fun", {"user_lookup_fun",
sc( sc(
typerefl:alias("string", any()), typerefl:alias("string", any()),
@ -2103,7 +2103,7 @@ common_ssl_opts_schema(Defaults, Type) ->
sc( sc(
boolean(), boolean(),
#{ #{
default => Df("secure_renegotiate", true), default => Df(secure_renegotiate, true),
desc => ?DESC(common_ssl_opts_schema_secure_renegotiate) desc => ?DESC(common_ssl_opts_schema_secure_renegotiate)
} }
)}, )},
@ -2123,7 +2123,7 @@ common_ssl_opts_schema(Defaults, Type) ->
sc( sc(
duration(), duration(),
#{ #{
default => Df("hibernate_after", <<"5s">>), default => Df(hibernate_after, <<"5s">>),
desc => ?DESC(common_ssl_opts_schema_hibernate_after) desc => ?DESC(common_ssl_opts_schema_hibernate_after)
} }
)} )}
@ -2132,15 +2132,15 @@ common_ssl_opts_schema(Defaults, Type) ->
%% @doc Make schema for SSL listener options. %% @doc Make schema for SSL listener options.
-spec server_ssl_opts_schema(map(), boolean()) -> hocon_schema:field_schema(). -spec server_ssl_opts_schema(map(), boolean()) -> hocon_schema:field_schema().
server_ssl_opts_schema(Defaults, IsRanchListener) -> server_ssl_opts_schema(Defaults, IsRanchListener) ->
D = fun(Field) -> maps:get(to_atom(Field), Defaults, undefined) end, D = fun(Field) -> maps:get(Field, Defaults, undefined) end,
Df = fun(Field, Default) -> maps:get(to_atom(Field), Defaults, Default) end, Df = fun(Field, Default) -> maps:get(Field, Defaults, Default) end,
common_ssl_opts_schema(Defaults, server) ++ common_ssl_opts_schema(Defaults, server) ++
[ [
{"dhfile", {"dhfile",
sc( sc(
string(), string(),
#{ #{
default => D("dhfile"), default => D(dhfile),
required => false, required => false,
desc => ?DESC(server_ssl_opts_schema_dhfile) desc => ?DESC(server_ssl_opts_schema_dhfile)
} }
@ -2149,7 +2149,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
sc( sc(
boolean(), boolean(),
#{ #{
default => Df("fail_if_no_peer_cert", false), default => Df(fail_if_no_peer_cert, false),
desc => ?DESC(server_ssl_opts_schema_fail_if_no_peer_cert) desc => ?DESC(server_ssl_opts_schema_fail_if_no_peer_cert)
} }
)}, )},
@ -2157,7 +2157,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
sc( sc(
boolean(), boolean(),
#{ #{
default => Df("honor_cipher_order", true), default => Df(honor_cipher_order, true),
desc => ?DESC(server_ssl_opts_schema_honor_cipher_order) desc => ?DESC(server_ssl_opts_schema_honor_cipher_order)
} }
)}, )},
@ -2165,7 +2165,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
sc( sc(
boolean(), boolean(),
#{ #{
default => Df("client_renegotiation", true), default => Df(client_renegotiation, true),
desc => ?DESC(server_ssl_opts_schema_client_renegotiation) desc => ?DESC(server_ssl_opts_schema_client_renegotiation)
} }
)}, )},
@ -2173,7 +2173,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) ->
sc( sc(
duration(), duration(),
#{ #{
default => Df("handshake_timeout", <<"15s">>), default => Df(handshake_timeout, <<"15s">>),
desc => ?DESC(server_ssl_opts_schema_handshake_timeout) desc => ?DESC(server_ssl_opts_schema_handshake_timeout)
} }
)} )}

View File

@ -62,6 +62,8 @@
[ocsp, issuer_pem] [ocsp, issuer_pem]
]). ]).
-define(ALLOW_EMPTY_PEM, [[<<"cacertfile">>], [cacertfile]]).
%% non-empty string %% non-empty string
-define(IS_STRING(L), (is_list(L) andalso L =/= [] andalso is_integer(hd(L)))). -define(IS_STRING(L), (is_list(L) andalso L =/= [] andalso is_integer(hd(L)))).
%% non-empty list of strings %% non-empty list of strings
@ -330,6 +332,13 @@ ensure_ssl_files_per_key(Dir, SSL, [KeyPath | KeyPaths], Opts) ->
ensure_ssl_file(_Dir, _KeyPath, SSL, undefined, _Opts) -> ensure_ssl_file(_Dir, _KeyPath, SSL, undefined, _Opts) ->
{ok, SSL}; {ok, SSL};
ensure_ssl_file(_Dir, KeyPath, SSL, MaybePem, _Opts) when
MaybePem =:= "" orelse MaybePem =:= <<"">>
->
case lists:member(KeyPath, ?ALLOW_EMPTY_PEM) of
true -> {ok, SSL};
false -> {error, #{reason => pem_file_path_or_string_is_required}}
end;
ensure_ssl_file(Dir, KeyPath, SSL, MaybePem, Opts) -> ensure_ssl_file(Dir, KeyPath, SSL, MaybePem, Opts) ->
case is_valid_string(MaybePem) of case is_valid_string(MaybePem) of
true -> true ->

View File

@ -113,11 +113,22 @@ ssl_files_failure_test_() ->
}) })
) )
end}, end},
{"empty_cacertfile", fun() ->
?assertMatch(
{ok, _},
emqx_tls_lib:ensure_ssl_files("/tmp", #{
<<"keyfile">> => test_key(),
<<"certfile">> => test_key(),
<<"cacertfile">> => <<"">>
})
)
end},
{"bad_pem_string", fun() -> {"bad_pem_string", fun() ->
%% empty string %% empty string
?assertMatch( ?assertMatch(
{error, #{ {error, #{
reason := invalid_file_path_or_pem_string, which_options := [[<<"keyfile">>]] reason := pem_file_path_or_string_is_required,
which_options := [[<<"keyfile">>]]
}}, }},
emqx_tls_lib:ensure_ssl_files("/tmp", #{ emqx_tls_lib:ensure_ssl_files("/tmp", #{
<<"keyfile">> => <<>>, <<"keyfile">> => <<>>,