diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 86ddb6577..88243a308 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -2001,8 +2001,8 @@ filter(Opts) -> %% SSL listener and client. -spec common_ssl_opts_schema(map(), server | client) -> hocon_schema:field_schema(). common_ssl_opts_schema(Defaults, Type) -> - D = fun(Field) -> maps:get(to_atom(Field), Defaults, undefined) end, - Df = fun(Field, Default) -> maps:get(to_atom(Field), Defaults, Default) end, + D = fun(Field) -> maps:get(Field, Defaults, undefined) end, + Df = fun(Field, Default) -> maps:get(Field, Defaults, Default) end, Collection = maps:get(versions, Defaults, tls_all_available), DefaultVersions = default_tls_vsns(Collection), [ @@ -2045,7 +2045,7 @@ common_ssl_opts_schema(Defaults, Type) -> sc( hoconsc:enum([verify_peer, verify_none]), #{ - default => Df("verify", verify_none), + default => Df(verify, verify_none), desc => ?DESC(common_ssl_opts_schema_verify) } )}, @@ -2053,7 +2053,7 @@ common_ssl_opts_schema(Defaults, Type) -> sc( boolean(), #{ - default => Df("reuse_sessions", true), + default => Df(reuse_sessions, true), desc => ?DESC(common_ssl_opts_schema_reuse_sessions) } )}, @@ -2061,7 +2061,7 @@ common_ssl_opts_schema(Defaults, Type) -> sc( non_neg_integer(), #{ - default => Df("depth", 10), + default => Df(depth, 10), 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 } )}, - {"ciphers", ciphers_schema(D("ciphers"))}, + {"ciphers", ciphers_schema(D(ciphers))}, {"user_lookup_fun", sc( typerefl:alias("string", any()), @@ -2103,7 +2103,7 @@ common_ssl_opts_schema(Defaults, Type) -> sc( boolean(), #{ - default => Df("secure_renegotiate", true), + default => Df(secure_renegotiate, true), desc => ?DESC(common_ssl_opts_schema_secure_renegotiate) } )}, @@ -2123,7 +2123,7 @@ common_ssl_opts_schema(Defaults, Type) -> sc( duration(), #{ - default => Df("hibernate_after", <<"5s">>), + default => Df(hibernate_after, <<"5s">>), 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. -spec server_ssl_opts_schema(map(), boolean()) -> hocon_schema:field_schema(). server_ssl_opts_schema(Defaults, IsRanchListener) -> - D = fun(Field) -> maps:get(to_atom(Field), Defaults, undefined) end, - Df = fun(Field, Default) -> maps:get(to_atom(Field), Defaults, Default) end, + D = fun(Field) -> maps:get(Field, Defaults, undefined) end, + Df = fun(Field, Default) -> maps:get(Field, Defaults, Default) end, common_ssl_opts_schema(Defaults, server) ++ [ {"dhfile", sc( string(), #{ - default => D("dhfile"), + default => D(dhfile), required => false, desc => ?DESC(server_ssl_opts_schema_dhfile) } @@ -2149,7 +2149,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) -> sc( 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) } )}, @@ -2157,7 +2157,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) -> sc( boolean(), #{ - default => Df("honor_cipher_order", true), + default => Df(honor_cipher_order, true), desc => ?DESC(server_ssl_opts_schema_honor_cipher_order) } )}, @@ -2165,7 +2165,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) -> sc( boolean(), #{ - default => Df("client_renegotiation", true), + default => Df(client_renegotiation, true), desc => ?DESC(server_ssl_opts_schema_client_renegotiation) } )}, @@ -2173,7 +2173,7 @@ server_ssl_opts_schema(Defaults, IsRanchListener) -> sc( duration(), #{ - default => Df("handshake_timeout", <<"15s">>), + default => Df(handshake_timeout, <<"15s">>), desc => ?DESC(server_ssl_opts_schema_handshake_timeout) } )} diff --git a/apps/emqx/src/emqx_tls_lib.erl b/apps/emqx/src/emqx_tls_lib.erl index b5b653f56..9113bd5e6 100644 --- a/apps/emqx/src/emqx_tls_lib.erl +++ b/apps/emqx/src/emqx_tls_lib.erl @@ -62,6 +62,8 @@ [ocsp, issuer_pem] ]). +-define(ALLOW_EMPTY_PEM, [[<<"cacertfile">>], [cacertfile]]). + %% non-empty string -define(IS_STRING(L), (is_list(L) andalso L =/= [] andalso is_integer(hd(L)))). %% 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) -> {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) -> case is_valid_string(MaybePem) of true -> diff --git a/apps/emqx/test/emqx_tls_lib_tests.erl b/apps/emqx/test/emqx_tls_lib_tests.erl index 481b9378e..ae7caa4fb 100644 --- a/apps/emqx/test/emqx_tls_lib_tests.erl +++ b/apps/emqx/test/emqx_tls_lib_tests.erl @@ -113,11 +113,22 @@ ssl_files_failure_test_() -> }) ) 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() -> %% empty string ?assertMatch( {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", #{ <<"keyfile">> => <<>>,