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.

Reply via email to