This is an automated email from the ASF dual-hosted git repository. vatamane pushed a commit to branch load-os-ca-certs-in-replicator in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 3994920b622dcba26eaba59d3637ee01263c3cb9 Author: Nick Vatamaniuc <[email protected]> AuthorDate: Fri Sep 5 19:06:02 2025 -0400 Load and use operating system CA certs for the replicator client Since OTP 25 there is an easy way to load OS provided CA certificates on all of our supported platforms. Use that to simplify peer verification in the replicator. If the user already provided a path to the CA certificates file, load that. If there isn't a CA cert path, attempt use the OS CA certs, and if that fails too, then crash with an error and do not continue. To help users diagnose the issue early, explicitly load the OS CA certs in the replicator supervisor. Emit an info log about the number of loaded certs or emit an error if it fails. CA certs after the first successful load are cached in a persistent term by the OTP and will always be available after that. Issue: https://github.com/apache/couchdb/issues/5638 --- .../src/couch_replicator_parse.erl | 25 ++++++++++++++++------ src/couch_replicator/src/couch_replicator_sup.erl | 13 +++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/couch_replicator/src/couch_replicator_parse.erl b/src/couch_replicator/src/couch_replicator_parse.erl index b72e1f576..5f8437992 100644 --- a/src/couch_replicator/src/couch_replicator_parse.erl +++ b/src/couch_replicator/src/couch_replicator_parse.erl @@ -488,15 +488,28 @@ ssl_params(Url) -> -spec ssl_verify_options(true | false) -> [_]. ssl_verify_options(true) -> - CAFile = cfg("ssl_trusted_certificates_file"), - [ - {verify, verify_peer}, - {customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}, - {cacertfile, CAFile} - ]; + % https://security.erlef.org/secure_coding_and_deployment_hardening/ssl.html + ssl_ca_cert_opts() ++ + [ + {verify, verify_peer}, + {customize_hostname_check, [ + {match_fun, public_key:pkix_verify_hostname_match_fun(https)} + ]} + ]; ssl_verify_options(false) -> [{verify, verify_none}]. +ssl_ca_cert_opts() -> + % Try to use the CA cert file from config first, and if not specified, use + % the CA certificates from the OS. If those can't be loaded either, then + % crash: cacerts_get/0 raises an error in that case and we do not catch it. + case cfg("ssl_trusted_certificates_file") of + undefined -> + [{cacerts, public_key:cacerts_get()}]; + CAFile when is_list(CAFile) -> + [{cacertfile, CAFile}] + end. + get_value(Key, Props) -> couch_util:get_value(Key, Props). diff --git a/src/couch_replicator/src/couch_replicator_sup.erl b/src/couch_replicator/src/couch_replicator_sup.erl index 710919c45..32b94b19f 100644 --- a/src/couch_replicator/src/couch_replicator_sup.erl +++ b/src/couch_replicator/src/couch_replicator_sup.erl @@ -37,7 +37,20 @@ init(_Args) -> worker(couch_replicator_doc_processor) ], SupFlags = #{strategy => rest_for_one, intensity => 10, period => 1}, + ok = load_os_ca_certs(), {ok, {SupFlags, Children}}. worker(Mod) -> #{id => Mod, start => {Mod, start_link, []}}. + +load_os_ca_certs() -> + case public_key:cacerts_load() of + ok -> + CertCount = length(public_key:cacerts_get()), + InfoMsg = "~p : successfully loaded ~p OS CA certificates", + couch_log:info(InfoMsg, [?MODULE, CertCount]); + {error, Reason} -> + ErrMsg = "~p : error loading OS CA certificates: ~p", + couch_log:error(ErrMsg, [?MODULE, Reason]) + end, + ok.
