Connect to an LDAP Server Fails With: "Could not find a valid certificate"


Description

Testing an LDAP Server connection on the instance and the connection test fails with the error:

ldaps://xxx.xxx.xxx.xxx:636 Could not find a valid certificate

or

ldap://xxx.xxx.xxx.xxx:636 Could not find a valid certificate

The node logs may show the following error:

2020-12-28 07:49:51 (394) worker.6 worker.6 txid=e7ba8baa1b99 SEVERE *** ERROR *** Cannot recover key
java.security.UnrecoverableKeyException: Cannot recover key
        at sun.security.provider.KeyProtector.recover(KeyProtector.java:315)
        at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:141)
        at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:56)
        at sun.security.provider.KeyStoreDelegator.engineGetKey(KeyStoreDelegator.java:96)
        at sun.security.provider.JavaKeyStore$DualFormatJKS.engineGetKey(JavaKeyStore.java:70)
        at java.security.KeyStore.getKey(KeyStore.java:1023)
        at sun.security.ssl.SunX509KeyManagerImpl.<init>(SunX509KeyManagerImpl.java:133)
        at sun.security.ssl.KeyManagerFactoryImpl$SunX509.engineInit(KeyManagerFactoryImpl.java:70)
        at javax.net.ssl.KeyManagerFactory.init(KeyManagerFactory.java:256)
        at com.glide.certificates.DBKeyStoreSocketFactory.createKeyManagers(DBKeyStoreSocketFactory.java:138)
        at com.glide.certificates.DBKeyStoreSocketFactory.initSSLContext(DBKeyStoreSocketFactory.java:116)
        at com.glide.certificates.DBKeyStoreSocketFactory.init(DBKeyStoreSocketFactory.java:106)
        at com.glide.certificates.DBKeyStoreSocketFactory.init(DBKeyStoreSocketFactory.java:98)
        at com.glide.certificates.DBKeyStoreSocketFactory.<init>(DBKeyStoreSocketFactory.java:78)
        at com.glide.sys.ldap.LDAP.setUseDBKeyStore(LDAP.java:109)
        at com.glide.sys.ldap.LDAP.setup(LDAP.java:97)
        at sun.reflect.GeneratedMethodAccessor710.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:138)
        at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:300)
        at org.mozilla.javascript.ScriptRuntime.doCall(ScriptRuntime.java:2612)
        at org.mozilla.javascript.optimizer.OptRuntime.callProp0(OptRuntime.java:85)
        at org.mozilla.javascript.gen._refname__1064._c_testLDAPServers_1(<refname>:17)
        at org.mozilla.javascript.gen._refname__1064.call(<refname>)
        at org.mozilla.javascript.ScriptRuntime.doCall2(ScriptRuntime.java:2678)
        at org.mozilla.javascript.ScriptRuntime.doCall(ScriptRuntime.java:2617)
        at org.mozilla.javascript.optimizer.OptRuntime.callName0(OptRuntime.java:74)
        at org.mozilla.javascript.gen._refname__1064._c_script_0(<refname>:1)
        at org.mozilla.javascript.gen._refname__1064.call(<refname>)
        at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:563)
        at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3459)
        at org.mozilla.javascript.gen._refname__1064.call(<refname>)
        at org.mozilla.javascript.gen._refname__1064.exec(<refname>)
        at com.glide.script.ScriptEvaluator.execute(ScriptEvaluator.java:279)
        at com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:118)
        at com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:82)
        at com.glide.script.ScriptEvaluator.evaluateString(ScriptEvaluator.java:73)
        at com.glide.script.Evaluator.evaluateString(Evaluator.java:96)
        at com.snc.automation.ScriptJob.executeInSingleDomain(ScriptJob.java:57)
        at com.snc.automation.ScriptJob.execute(ScriptJob.java:41)
        at com.glide.schedule.JobExecutor.lambda$executeJob$0(JobExecutor.java:113)
        at com.glide.schedule.JobExecutor.executeJob(JobExecutor.java:116)
        at com.glide.schedule.JobExecutor.execute(JobExecutor.java:100)
        at com.glide.schedule_v2.SchedulerWorkerThread.executeJob(SchedulerWorkerThread.java:300)
        at com.glide.schedule_v2.SchedulerWorkerThread.lambda$process$0(SchedulerWorkerThread.java:188)
        at com.glide.worker.TransactionalWorkerThread.executeInTransaction(TransactionalWorkerThread.java:35)
        at com.glide.schedule_v2.SchedulerWorkerThread.process(SchedulerWorkerThread.java:188)
        at com.glide.schedule_v2.SchedulerWorkerThread.run(SchedulerWorkerThread.java:102)
2020-12-28 07:49:51 (396) worker.6 worker.6 txid=e7ba8baa1b99 WARNING *** WARNING *** LDAP API - LDAPLogger : Unable to load certificates from DB
2020-12-28 07:49:51 (396) worker.6 worker.6 txid=e7ba8baa1b99 WARNING *** WARNING *** LDAP: Unable to load certificates from DB
[...]
2020-12-28 07:49:51 (544) worker.6 worker.6 txid=e7ba8baa1b99 LDAP API - LDAPLogger : xxx.xxx.xxx.xxx:636
2020-12-28 07:49:51 (544) worker.6 worker.6 txid=e7ba8baa1b99 LDAP API - LDAPLogger : Communication error: xxx.xxx.xxx.xxx:636
2020-12-28 07:49:51 (544) worker.6 worker.6 txid=e7ba8baa1b99 LDAP API - LDAPLogger : javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
2020-12-28 07:49:51 (549) worker.6 worker.6 txid=e7ba8baa1b99 SEVERE *** ERROR *** LDAP: LDAP Server: LDAP Server URL: ldap://xxx.xxx.xxx.xxx:636/ failed scheduled connection test. ErrorCode: 10402. ErrorMessage: Could not find a valid certificate.

Cause

There are two known causes for this issue.

Cause #1

How to set up certificates for LDAPS connections is discussed in this documentation: Certificates

Under Certificate trust:

By default, the instance trusts the Certificate Authority, or CA, for a certificate. This ensures the instance accepts self-issued certificates. If you do not want to trust all certificates by default, set the following general security property to false:

com.glide.communications.trustmanager_trust_all.

You may have already set com.glide.communications.trustmanager_trust_all to true, but are still seeing the Could not find a valid certificate error.

The cause may be the activation of the High Security Settings Plugin, or com.glide.high_security, which sets the following system property to true:

com.glide.communications.httpclient.verify_hostname

The description of this property is:

Verify hostname and certificate chain presented by remote SSL hosts. Set to true to protect against MITM attacks. Overrides the com.glide.communications.trustmanager_trust_all property.

Cause #2:

There is an invalid certificate defined in the x509 Certificate module (sys_certificate list view).  The LDAP server record has a Related Link called "Certificate List", when that is selected you are taken to the x509 Certificate module (sys_certificate list view). This means the system will check all of the certificates in that list to find a valid one for the LDAP SSL connection.  While checking the list of certificates, if the system comes across an invalid certificate before it gets to one that is valid for the SSL connection the error will occur.

Resolution

There are two ways to resolve this issue for Cause #1:

  1. Set the system property com.glide.communications.httpclient.verify_hostname to false, while keeping the com.glide.communications.trustmanager_trust_all property set to true. In this configuration, the system again makes the instance trust the Certificate Authority CA for a certificate. This ensures the instance accepts self-issued certificates.
  2. Upload the SSL certificate to the instance for the LDAP Server that has been issued by a trusted third party Certificate Authority, for example, a non-self-issued certificate, again following the documentation on Certificates referenced above: Certificates

If there is a trusted third-party signed certificate installed on the instance, it is possible to set both system properties to not accept self-issued certificates:

com.glide.communications.trustmanager_trust_all = false

and

com.glide.communications.httpclient.verify_hostname = true

Since com.glide.communications.httpclient.verify_hostname overrides com.glide.communications.trustmanager_trust_all, just setting com.glide.communications.httpclient.verify_hostname to true is actually sufficient. It does not matter if com.glide.communications.trustmanager_trust_all is set to true, if com.glide.communications.httpclient.verify_hostname is set to true, the instance does not accept self-issued certificates.

If the same error persists go to the LDAP Server record and check the "SSL" box if not already checked and save the change then try the "Test Connection" again.

 Note: In versions London and above the setting for property com.glide.communications.httpclient.verify_revoked_certificate may also come into play. See KB0727750 - From London release onwards, Instance is not available to make any outbound webservice call if the webservice consumer uses the certificate chain

For Cause #2:

  1. Go to the x509 Certificate module (sys_certificate list view)
  2. Open each certificate in the list and select the Related Link "Validate Stores/Certificates", if the certificate does not validate set it to Active = false and check the LDAP connection again.  Deactivate each certificate until the one or ones causing the issue are found.
  3. Once the offending certificate(s) are found leave them inactive or correct the issue to make them valid, e.g. entering the correct password for a keystore or adding a keystore attachment or updating the PEM Certificate value to a valid value, e.g. to one that is not expired.  Once the certificate passes validation it can be made active again.
  4. Once the certificate manipulation is complete check the LDAP connection again to make sure it still connects successfully.