diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl index 5cab3cbc5..95d6a46cf 100644 --- a/apps/emqx/src/emqx_schema.erl +++ b/apps/emqx/src/emqx_schema.erl @@ -2017,6 +2017,14 @@ common_ssl_opts_schema(Defaults, Type) -> desc => ?DESC(common_ssl_opts_schema_cacertfile) } )}, + {"cacerts", + sc( + boolean(), + #{ + default => false, + desc => ?DESC(common_ssl_opts_schema_cacerts) + } + )}, {"certfile", sc( binary(), diff --git a/apps/emqx/src/emqx_tls_lib.erl b/apps/emqx/src/emqx_tls_lib.erl index b5b653f56..cd83df179 100644 --- a/apps/emqx/src/emqx_tls_lib.erl +++ b/apps/emqx/src/emqx_tls_lib.erl @@ -478,11 +478,13 @@ to_server_opts(Type, Opts) -> Versions = integral_versions(Type, maps:get(versions, Opts, undefined)), Ciphers = integral_ciphers(Versions, maps:get(ciphers, Opts, undefined)), Path = fun(Key) -> resolve_cert_path_for_read_strict(maps:get(Key, Opts, undefined)) end, + CACerts = get_cacerts(maps:get(cacerts, Opts, false)), ensure_valid_options( maps:to_list(Opts#{ keyfile => Path(keyfile), certfile => Path(certfile), cacertfile => Path(cacertfile), + cacerts => CACerts, ciphers => Ciphers, versions => Versions }), @@ -511,11 +513,13 @@ to_client_opts(Type, Opts) -> SNI = ensure_sni(Get(server_name_indication)), Versions = integral_versions(Type, Get(versions)), Ciphers = integral_ciphers(Versions, Get(ciphers)), + CACerts = get_cacerts(GetD(cacerts, false)), ensure_valid_options( [ {keyfile, KeyFile}, {certfile, CertFile}, {cacertfile, CAFile}, + {cacerts, CACerts}, {verify, Verify}, {server_name_indication, SNI}, {versions, Versions}, @@ -661,3 +665,13 @@ ensure_ssl_file_key(SSL, RequiredKeyPaths) -> [] -> ok; Miss -> {error, #{reason => ssl_file_option_not_found, which_options => Miss}} end. + +get_cacerts(true = _UseSystemCACerts) -> + try + public_key:cacerts_get() + catch + _:_ -> + undefined + end; +get_cacerts(false = _UseSystemCACerts) -> + undefined. diff --git a/apps/emqx/test/emqx_tls_lib_tests.erl b/apps/emqx/test/emqx_tls_lib_tests.erl index 8a412af05..f90ee9c44 100644 --- a/apps/emqx/test/emqx_tls_lib_tests.erl +++ b/apps/emqx/test/emqx_tls_lib_tests.erl @@ -229,6 +229,7 @@ to_client_opts_test() -> Versions13Only = ['tlsv1.3'], Options = #{ enable => true, + cacerts => true, verify => "Verify", server_name_indication => "SNI", ciphers => "Ciphers", @@ -263,6 +264,28 @@ to_client_opts_test() -> emqx_tls_lib:to_client_opts(tls, Options#{depth := undefined, password := ""}) ) ) + ), + Expected4 = lists:usort(maps:keys(Options) -- [enable, cacerts]), + ?assertEqual( + Expected4, + lists:usort( + proplists:get_keys( + emqx_tls_lib:to_client_opts(tls, Options#{cacerts := false}) + ) + ) + ), + emqx_common_test_helpers:with_mock( + public_key, + cacerts_get, + fun() -> ok = {error, enoent} end, + fun() -> + ?assertNot( + lists:member( + cacerts, + proplists:get_keys(emqx_tls_lib:to_client_opts(tls, Options)) + ) + ) + end ). to_server_opts_test() -> diff --git a/rel/i18n/emqx_schema.hocon b/rel/i18n/emqx_schema.hocon index f871cfc49..ee555fc1f 100644 --- a/rel/i18n/emqx_schema.hocon +++ b/rel/i18n/emqx_schema.hocon @@ -262,6 +262,12 @@ already established connections.""" common_ssl_opts_schema_cacertfile.label: """CACertfile""" +common_ssl_opts_schema_cacerts.desc: +"""When enabled, uses the system trusted CA certificates for establishing to TLS connections.""" + +common_ssl_opts_schema_cacerts.label: +"""Use System CA Certificates""" + fields_ws_opts_mqtt_path.desc: """WebSocket's MQTT protocol path. So the address of EMQX Broker's WebSocket is: ws://{ip}:{port}/mqtt"""