[3.14] Can't set LDAPS in "Authentication Sources"

Hello

Problem:
I want to set a new authentication source to use LDAP (Active Directory) using TLS. However I have a certificate error when I test the connexion or if I try to login.

My company use certificates. The CA , and chain are imported.

The error is

ERF50-1006 [Foreman::WrappedException]: Unable to connect to LDAP server ([Net::LDAP::Error]: SSL_connect SYSCALL returned=5 errno=0 peeraddr=<LDAP IP>:636 state=error: certificate verify failed)

Expected outcome:
Test connexion and login operationnal with LDAPS

Foreman and Proxy versions:
3.14

Foreman and Proxy plugin versions:

  • Foreman_puppet : 8.1.0

Distribution and version:
Ubuntu 22.04

Other relevant data:
Commands

  • openssl is ok
# openssl s_client -connect <LDAP IP>:636
CONNECTED(00000003)
...
  • curl is ok
 curl -L ldaps://<LDAP IP>:636
DN:
        domainFunctionality: 7

        forestFunctionality: 7
...
  • ldpasearch is ok (can connect and do search) :
# ldapsearch -x -v -Z -H ldaps://<LDAP IP>:636 (with options)
# extended LDIF
#
# LDAPv3
# base <dc=one,dc=local> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# one.local
dn: DC=one,DC=local
objectClass: top
objectClass: domain
objectClass: domainDNS
distinguishedName: DC=one,DC=local

production logs when I try the connexion :

2025-04-29T14:11:35 [I|app|4a3227e2] Started GET "/auth_sources" for <IP> at 2025-04-29 14:11:35 +0200
2025-04-29T14:11:35 [I|app|4a3227e2] Processing by AuthSourcesController#index as HTML
2025-04-29T14:11:35 [I|app|4a3227e2]   Rendered auth_sources/index.html.erb within layouts/application (Duration: 5.9ms | Allocations: 2816)
2025-04-29T14:11:35 [I|app|4a3227e2]   Rendered layouts/base.html.erb (Duration: 10.4ms | Allocations: 11819)
2025-04-29T14:11:35 [I|app|4a3227e2]   Rendered layout layouts/application.html.erb (Duration: 17.2ms | Allocations: 14949)
2025-04-29T14:11:35 [I|app|4a3227e2] Completed 200 OK in 35ms (Views: 16.7ms | ActiveRecord: 3.6ms | Allocations: 23875)
2025-04-29T14:11:35 [I|app|71d4908c] Started GET "/notification_recipients" for 10.100.0.22 at 2025-04-29 14:11:35 +0200
2025-04-29T14:11:35 [I|app|71d4908c] Processing by NotificationRecipientsController#index as JSON
2025-04-29T14:11:35 [I|app|71d4908c] Completed 200 OK in 5ms (Views: 0.1ms | ActiveRecord: 0.6ms | Allocations: 2215)
2025-04-29T14:11:37 [I|app|36671ed2] Started GET "/auth_source_ldaps/4-ONE/edit" for 10.100.0.22 at 2025-04-29 14:11:37 +0200
2025-04-29T14:11:37 [I|app|36671ed2] Processing by AuthSourceLdapsController#edit as HTML
2025-04-29T14:11:37 [I|app|36671ed2]   Parameters: {"id"=>"4-ONE"}
2025-04-29T14:11:37 [I|app|36671ed2]   Rendered auth_source_ldaps/edit.html.erb within layouts/application (Duration: 15.9ms | Allocations: 13636)
2025-04-29T14:11:37 [I|app|36671ed2]   Rendered layouts/base.html.erb (Duration: 9.8ms | Allocations: 11618)
2025-04-29T14:11:37 [I|app|36671ed2]   Rendered layout layouts/application.html.erb (Duration: 26.2ms | Allocations: 25464)
2025-04-29T14:11:37 [I|app|36671ed2] Completed 200 OK in 37ms (Views: 25.2ms | ActiveRecord: 2.9ms | Allocations: 30406)
2025-04-29T14:11:37 [I|app|d4f031c7] Started GET "/notification_recipients" for 10.100.0.22 at 2025-04-29 14:11:37 +0200
2025-04-29T14:11:37 [I|app|d4f031c7] Processing by NotificationRecipientsController#index as JSON
2025-04-29T14:11:37 [I|app|d4f031c7] Completed 200 OK in 5ms (Views: 0.1ms | ActiveRecord: 0.6ms | Allocations: 2213)
2025-04-29T14:11:38 [I|app|bb9d22bd] Started PUT "/auth_source_ldaps/test_connection" for 10.100.0.22 at 2025-04-29 14:11:38 +0200
2025-04-29T14:11:38 [I|app|bb9d22bd] Processing by AuthSourceLdapsController#test_connection as */*
2025-04-29T14:11:38 [I|app|bb9d22bd]   Parameters: {"authenticity_token"=>"<TOKEN>", "auth_source_ldap"=>{"name"=>"ONE", "host"=>"<LDAP NAME>", "tls"=>"1", "port"=>"636", "server_type"=>"active_directory", "account"=>"<ACCOUNT>", "base_dn"=>"<based>", "groups_base"=>"<groups>", "use_netgroups"=>"0", "ldap_filter"=>"", "onthefly_register"=>"0", "usergroup_sync"=>"0", "attr_login"=>"sAMAccountName", "attr_firstname"=>"givenName", "attr_lastname"=>"sn", "attr_mail"=>"mail", "attr_photo"=>"", "location_ids"=>["", "2"], "organization_ids"=>["", "1"]}, "fakepassword"=>"[FILTERED]"}
2025-04-29T14:11:38 [W|app|bb9d22bd] Failed to connect to LDAP server
2025-04-29T14:11:38 [I|app|bb9d22bd] Backtrace for 'Failed to connect to LDAP server' error (Foreman::WrappedException): ERF50-1006 [Foreman::WrappedException]: Unable to connect to LDAP server ([Net::LDAP::Error]: SSL_connect SYSCALL returned=5 errno=0 peeraddr=<IP LDAP>:636 state=error: certificate verify failed)
 bb9d22bd | /usr/share/foreman/app/models/auth_sources/auth_source_ldap.rb:185:in `rescue in test_connection'
 bb9d22bd | /usr/share/foreman/app/models/auth_sources/auth_source_ldap.rb:178:in `test_connection'
 bb9d22bd | /usr/share/foreman/app/controllers/auth_source_ldaps_controller.rb:40:in `test_connection'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/abstract_controller/base.rb:215:in `process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal/rendering.rb:165:in `process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/abstract_controller/callbacks.rb:234:in `block in process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
 bb9d22bd | /usr/share/foreman/app/controllers/concerns/foreman/controller/timezone.rb:10:in `set_timezone'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
 bb9d22bd | /usr/share/foreman/app/models/concerns/foreman/thread_session.rb:32:in `clear_thread'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
 bb9d22bd | /usr/share/foreman/app/controllers/concerns/foreman/controller/topbar_sweeper.rb:12:in `set_topbar_sweeper_controller'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/audited-5.8.0/lib/audited/sweeper.rb:16:in `around'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/audited-5.8.0/lib/audited/sweeper.rb:16:in `around'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:127:in `block in run_callbacks'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:138:in `run_callbacks'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/abstract_controller/callbacks.rb:233:in `process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal/rescue.rb:23:in `process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal/instrumentation.rb:67:in `block in process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/notifications.rb:206:in `block in instrument'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/notifications.rb:206:in `instrument'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal/instrumentation.rb:66:in `process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activerecord-7.0.8.7/lib/active_record/railties/controller_runtime.rb:27:in `process_action'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/abstract_controller/base.rb:151:in `process'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionview-7.0.8.7/lib/action_view/rendering.rb:39:in `process'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal.rb:188:in `dispatch'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_controller/metal.rb:251:in `dispatch'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/routing/route_set.rb:49:in `dispatch'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/routing/route_set.rb:32:in `serve'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/journey/router.rb:50:in `block in serve'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/journey/router.rb:32:in `each'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/journey/router.rb:32:in `serve'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/routing/route_set.rb:852:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/apipie-dsl-2.6.2/lib/apipie_dsl/static_dispatcher.rb:67:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/apipie-rails-1.4.2/lib/apipie/static_dispatcher.rb:74:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/static.rb:23:in `call'
 bb9d22bd | /usr/share/foreman/lib/foreman/middleware/libvirt_connection_cleaner.rb:9:in `call'
 bb9d22bd | /usr/share/foreman/lib/foreman/middleware/telemetry.rb:10:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/apipie-rails-1.4.2/lib/apipie/middleware/checksum_in_headers.rb:27:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/tempfile_reaper.rb:15:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/etag.rb:27:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/conditional_get.rb:40:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/head.rb:12:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/http/permissions_policy.rb:38:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/http/content_security_policy.rb:39:in `call'
 bb9d22bd | /usr/share/foreman/lib/foreman/middleware/logging_context_session.rb:22:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/session/abstract/id.rb:266:in `context'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/session/abstract/id.rb:260:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/cookies.rb:704:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/callbacks.rb:99:in `run_callbacks'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/debug_exceptions.rb:28:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/show_exceptions.rb:29:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/railties-7.0.8.7/lib/rails/rack/logger.rb:40:in `call_app'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/railties-7.0.8.7/lib/rails/rack/logger.rb:27:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/sprockets-rails-3.5.2/lib/sprockets/rails/quiet_assets.rb:17:in `call'
 bb9d22bd | /usr/share/foreman/lib/foreman/middleware/logging_context_request.rb:11:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/remote_ip.rb:93:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/request_id.rb:26:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/method_override.rb:24:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/runtime.rb:22:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/activesupport-7.0.8.7/lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/executor.rb:14:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/sendfile.rb:110:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/ssl.rb:77:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/actionpack-7.0.8.7/lib/action_dispatch/middleware/host_authorization.rb:131:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/secure_headers-6.7.0/lib/secure_headers/middleware.rb:11:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/railties-7.0.8.7/lib/rails/engine.rb:530:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/railties-7.0.8.7/lib/rails/railtie.rb:226:in `public_send'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/railties-7.0.8.7/lib/rails/railtie.rb:226:in `method_missing'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/urlmap.rb:74:in `block in call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/urlmap.rb:58:in `each'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/rack-2.2.13/lib/rack/urlmap.rb:58:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/puma-6.6.0/lib/puma/configuration.rb:279:in `call'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/puma-6.6.0/lib/puma/request.rb:99:in `block in handle_request'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/puma-6.6.0/lib/puma/thread_pool.rb:390:in `with_force_shutdown'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/puma-6.6.0/lib/puma/request.rb:98:in `handle_request'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/puma-6.6.0/lib/puma/server.rb:472:in `process_client'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/puma-6.6.0/lib/puma/server.rb:254:in `block in run'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/puma-6.6.0/lib/puma/thread_pool.rb:167:in `block in spawn_thread'
 bb9d22bd | /usr/share/foreman/vendor/ruby/3.0.0/gems/logging-2.4.0/lib/logging/diagnostic_context.rb:474:in `block in create_with_logging_context'
2025-04-29T14:11:38 [I|app|bb9d22bd] Completed 422 Unprocessable Entity in 34ms (Views: 0.2ms | ActiveRecord: 1.4ms | Allocations: 8188)

Your certificate verification is failing: “peeraddr=:636 state=error: certificate verify failed”

When you said you imported the certificate, where did you import it?

Because I have some wonky certificates that our Active Directory team decided to use, I ended up having to disable TLS Verification for our LDAPS connections, which if you want to do that as well, just edit the auth_source_ldap.rb in /usr/share/foreman/app/models/auth_sources and change “OpenSSL::SSL::VERIFY_PEER” to “OpenSSL::SSL::VERIFY_NONE”.

Keep in mind that after every Foreman update, you have to go back and modify this value.

Hello, Unfortunatly this is not really a solution :confused:

I followed the instructions from here : Foreman :: Manual
I guess that’s why it works with the others methods (curl, openssl, …)

I wonder if ruby has it’s own certificate store like Java ?

It’s really so much easier, if you post the exact commands how you have imported the certs instead of pointing to the manual. The commands are precise. The instructions leave room what you might have done or not.

That only says that it established the TCP connection. It will always connect. It just depends on the verification code at the end. And verification will most likely fail if you connect to the IP because usually certificates don’t contain IP addresses.

If you think you have the right root ca certificate in example.crt (and only the root ca certificate) and followed the instructions, then this should verify ok:

$ openssl s_client -no-CAfile -no-CApath -no-CAstore -CAfile /usr/local/share/ca-certificates/example.crt -connect ldapserver.example.com:636

This too isn’t particularly useful without seeing verbose output with -v. That shows which CA file and paths it actually uses.

Hello,

My bad here are the logs with verbose :

# curl -v -L ldaps://<ldap_fqdn>:636
*   Trying <ldap_ip>:636...
* Connected to <ldap_fqdn> (<ldap_ip>) port 636 (#0)
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Request CERT (13):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
*  subject: [NONE]
*  start date: Feb  3 10:35:38 2025 GMT
*  expire date: Feb  3 10:35:38 2026 GMT
*  subjectAltName: host "<ldap_fqdn>" matched cert's "<ldap_fqdn>"
*  issuer: DC=~~~; DC=~~~; CN=<CA NAME>
*  SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* LDAP local: ldaps://<ldap_fqdn>:636/
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):

...

for openssl

 openssl s_client -no-CAfile -no-CApath -no-CAstore -CAfile /usr/local/share/ca-certificates/ROOT_CA.crt -connect <ldap_fqdn>:636
CONNECTED(00000003)
depth=2 CN = ROOT CA
verify return:1
depth=1 DC = ~~~, DC = ~~~, CN = T0 CA
verify return:1
depth=0 
verify return:1
---
Certificate chain
 0 s:
   i:DC = ~~~, DC = ~~~ , CN =  T0 CA
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA256
   v:NotBefore: Feb  3 10:35:38 2025 GMT; NotAfter: Feb  3 10:35:38 2026 GMT
 1 s:DC = ~~~, DC = ~~~, CN =  T0 CA
   i:CN =  ROOT CA
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA256
   v:NotBefore: Dec 20 11:03:39 2023 GMT; NotAfter: Dec 20 11:13:39 2033 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHDzCCBPegAwIBAgITOQAAAA/oEBD9V5CUHgAAAAAADzANBgkqhkiG9w0BAQsF
ADBIMRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNvbmUx
GjAYBgNVBAMTEVN0b3Jtc2hpZWxkIFQwIENBMB4XDTI1MDIwMzEwMzUzOFoXDTI2
MDIwMzEwMzUzOFowADCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKsv
IT8f5N08HSPJtuCvoTZLb3jkJ+j4kFqibCzwmjT5/gt1ZtjMSera/UhiHZNMzYMy
wNvSTAicn6NgRc6djxwuhHGfDqc3Rxr7Gqbk7dIQeN2/Tvgx9P5XkDLceblhsiuX
wxl6830Wp4vLVyjzMd8X8i/FKmsF5NW7e/nZlRp8crrO+jJ0QauBpGS86k3TCNsU
RQ02mB8ek72mM1DE+NZZut4eXQJFn+V1sIZS0t/wArVgW3Kf9Zr5MwrYw2C/zDGY
hyCutr4xGCwRpMRdFdlAhL9Q4aW4y63xyLklZzWxfuFe0vpyavQGlHZXWabzrhDa
b7GOzaQU92U5IrXY2WUf4/Z9IANuruuZm8ht2hRJrnFfwy1r4rzGLCa1nYq8caT3
cCWK+t7PbLgs+585lnCfaNuPSrJpvNjC8moUp4pqy7RnLinzLqMeU+1rZHguPtKt
z0jlNdMALT0tS06SoLex4SiK8hIAY7dY1sF8/y5MiXIZkClLo6X89F2Tu8iey2g8
AOK/T6tIJafHdUerDZM1yslC16OpsjFTByVVE/k2TaOEoojxDSgbGmXtR9Uxibgu
Xp8UW/VBVWANy2B/CCeaJAaobGKajmFi+Y/VDIU3ewRWLolobL9PsE4zmMgTlHVf
/kTtU4AGwD/UNbrM01JyMpQb7dQyaMNM1JrEzWixAgMBAAGjggI4MIICNDA+Bgkr
BgEEAYI3FQcEMTAvBicrBgEEAYI3FQiFtLRKgqD8MISNiyGGnu8OhdSObIFQhNDM
DoaM1i8CAWQCAQ4wMgYDVR0lBCswKQYHKwYBBQIDBQYKKwYBBAGCNxQCAgYIKwYB
BQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMEAG
CSsGAQQBgjcVCgQzMDEwCQYHKwYBBQIDBTAMBgorBgEEAYI3FAICMAoGCCsGAQUF
BwMBMAoGCCsGAQUFBwMCME8GCSsGAQQBgjcZAgRCMECgPgYKKwYBBAGCNxkCAaAw
BC5TLTEtNS0yMS0zNjg3MjY3NTQ3LTQwMTIwMzU1NzgtMTU0MjE0NTctMTA3NjEz
MDMGA1UdEQEB/wQpMCeCFUlDVERDQ0FEMDAxLm9uZS5sb2NhbIIJb25lLmxvY2Fs
ggNPTkUwHQYDVR0OBBYEFHc+9YlMyJ4I7sGo7wtqJq9xRn19MB8GA1UdIwQYMBaA
FPNtkL4RODDN1VjtbPCWz14M+oKsMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9j
cmwuc3Rvcm1zaGllbGQuZXUvU3Rvcm1zaGllbGQlMjBUMCUyMENBLmNybDBSBggr
BgEFBQcBAQRGMEQwQgYIKwYBBQUHMAKGNmh0dHA6Ly9jcmwuc3Rvcm1zaGllbGQu
ZXUvQ0EvU3Rvcm1zaGllbGQlMjBUMCUyMENBLmNydDANBgkqhkiG9w0BAQsFAAOC
AgEAkRdtfw/Cf0LUVwUT7H0kSUnYRehhNG9kjm2cvys1BKVN14FZ1M7NbB1d2TS/
Ny/Y7E5wAodKUAPwQ99qiRytQr1KNd2e8YF0Xb5/Yhi32JnZYH9b+xznXhHeEb4y
Gs7AcVrfRCv4FwSqqqftBxXdS1pyrcNqNNyDIEW4krtGVP0o2Wrmk7fLTpl5jD3G
DpTbmBDfp4ilPwnZCkNonoxkG/BAmz6pbtHwb+QC7g8Cafhj58mfi8CYXmF8HIEZ
JWDpeFdhBW03FvIXvULGixNNE/FQ/W/DF30uZleF0A4csyOHm6a/Vf19HJBUbj34
e5FNCgzpRTHzhw68o1i8lGAfLXZ3IRMGhhUjWLJNyRaxlr8IriXyQGXwkT5uHBNs
ywWoi6TnEZzeuwaOl4U+Gtnas7cH6Afm2gDNvBEnVDyBTc5gl2KaubHnqRfy0jtc
eu2dS/e2r9tr88XHg5byzqW4IPgirGqMmUsLkAg13QZt+Y0ak8bM0z0TfT3Ql2FU
a+t89wNzYiQG2DhgClmrG5SP3vn1wBcJr31q7FQY+xB14hDpCsyHmzJ6vh/2rt2I
4fLI+/+2KCCKu3CMfTTUP75j8F+Be+kO2CXy/GuMaoYf0SXZXabgI6qDY8CzXhZa
38wf+GohLLCJTRXs4ebiYiGFFBRpCaDxUSyG4cY1hc1Unqs=
-----END CERTIFICATE-----
subject=
issuer=DC = ~~~, DC = ~~~, CN =  T0 CA
---
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: RSA+SHA256:RSA+SHA384:RSA+SHA1:ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA1:DSA+SHA1:RSA+SHA512:ECDSA+SHA512
Shared Requested Signature Algorithms: RSA+SHA256:RSA+SHA384:ECDSA+SHA256:ECDSA+SHA384:RSA+SHA512:ECDSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA
Server Temp Key: ECDH, secp384r1, 384 bits
---
SSL handshake has read 4106 bytes and written 493 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 483B000011907C47017E45D6A4153D78B0A4048F57EF3B1E842089C8776042CE
    Session-ID-ctx: 
    Master-Key: 6AB36988EB82DF796DC2946266255D8A3867D1FB4F705225B731F607C67BD7EFE1059B10D29733CDF2E7BED441DC79F1
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1746535564
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: yes
---

So you have got a symlink

$ ls -la /etc/ssl/certs/ROOT_CA.pem

as well as the hash symlink:

$ openssl x509 -in /etc/ssl/certs/ROOT_CA.pem -noout -hash
abbacbbc
$ ls -la /etc/ssl/certs/abbacbbc.*

Replace abbacbbc with the actual hash of your root ca certificate as shown by openssl x509.

Yes it’s already present :

# ls -l /etc/ssl/certs/ROOT_CA.pem 
lrwxrwxrwx 1 root root 56 Apr 29 10:38 /etc/ssl/certs/ROOT_CA.pem -> /usr/local/share/ca-certificates/ROOT_CA.crt

# openssl x509 -in /etc/ssl/certs/ROOT_CA.pem -noout -hash
7667f84f

# ls -l /etc/ssl/certs/7667f84f.*
lrwxrwxrwx 1 root root 23 Apr 29 10:38 /etc/ssl/certs/7667f84f.0 -> ROOT_CA.pem