I had one Connections’ environment that I wanted to switch from OpenLDAP to Active Directory LDAP. The old OpenLDAP environment used LDAPS to connect, and so I assumed that the change was done quickly.
The first step was to make a copy of the tdisol folder I used for OpenLDAP and start changing the configuration files for the new LDAP server.
Now we need to import the certificate used for LDAPS. You can use keytool
, Keystore Explorer or openssl
to get the SSL certificate from the server and store it into a JKS keystore.
openssl s_client -showcerts -connect ad-server-hostname:636 < /dev/null > temp-key.out
openssl x509 -outform DER < temp-key.out > temp-key.der
openssl x509 -inform der -in temp-key.der -out temp-key.pem
/opt/IBM/TDI/V7.0/jvm/jre/bin/keytool -import -alias ldap-certificate -keystore ldapcerts.jks -file temp-key.pem
This asks you for a keystore password and if you want to trust the certificate.
Example
[root@cnx8-db2-db ad_ldaps]# openssl s_client -showcerts -connect dc1.win.stoeps.home:636 < /dev/null > temp-key.out
depth=0 CN = DC1.WIN.STOEPS.HOME
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = DC1.WIN.STOEPS.HOME
verify error:num=21:unable to verify the first certificate
verify return:1
depth=0 CN = DC1.WIN.STOEPS.HOME
verify return:1
DONE
[root@cnx8-db2-db ad_ldaps]# openssl x509 -outform DER < temp-key.out > temp-key.der
[root@cnx8-db2-db ad_ldaps]# openssl x509 -inform der -in temp-key.der -out temp-key.pem
[root@cnx8-db2-db ad_ldaps]# /opt/IBM/TDI/V7.20/jvm/jre/bin/keytool -import -alias ldap-certificate -keystore ldapcerts.jks -file temp-key.pem
Enter keystore password:
Re-enter new password:
Owner: CN=DC1.WIN.STOEPS.HOME
Issuer: CN=WIN-DC1-CA, DC=WIN, DC=STOEPS, DC=HOME
...
Trust this certificate? [no]: yes
Certificate was added to keystore
Now add the new keystore to solution.properties
in the tdisol directory.
The example solution.properties
has the trustStore configuration, which just needs to be uncommented.
...
## server authentication
#javax.net.ssl.trustStore=key.jks
#{protect}-javax.net.ssl.trustStorePassword=
#javax.net.ssl.trustStoreType=jks
# by default the server API is not used.
api.on=false
For my newly created keystore I added the following.
javax.net.ssl.trustStore=ldapcerts.jks
{protect}-javax.net.ssl.trustStorePassword={encr}VK/JddYbHYHDbjQ/jO91wvVJ0howxCge2Ded409WgNRoQq1JHsEMKnZa1OuWSmgnoNwUnRRTQpr9v3lbvwFSULLAUjZTClD5jkgHeHTU/dUE0OXtsSlK+gBaIOBF9IZqybZJF1hlnuWsZx29gshwY2wANrIkgzmpWYs55XwdC9A=
javax.net.ssl.trustStoreType=jks
We will later see that this is the issue here, but these three lines are enough to get a working TDI SSL connection to Domino LDAP or OpenLDAP.
Adjust the server and the bind user
I adjusted profiles_tdi.properties
and ran collect_dns.sh
to check the LDAP connection.
Changed values in profiles_tdi.properties
:
source_ldap_url=ldap://dc1.win.stoeps.home:636
source_ldap_search_base=dc=win,dc=stoeps,dc=home
source_ldap_search_filter=(objectclass=Person)
source_ldap_user_login=CN=Bind LDAP,OU=Stoeps Users,DC=WIN,DC=STOEPS,DC=HOME
{protect}-source_ldap_user_password=<password of the bind user>
Double check that SSL is enabled:
source_ldap_use_ssl=true
Running collect_dns.sh
failed with the message simple bind failed
.
Error message in ibmdi.log
2023-11-02 12:36:34,931 INFO [AssemblyLine.AssemblyLines/_internal_ldap_iterate] - [ldap_iterate] CTGDJQ001I Using LDAP SSL connection. Ensure TCP port number is changed accordingly.
2023-11-02 12:36:35,162 ERROR [AssemblyLine.AssemblyLines/_internal_ldap_iterate] - [ldap_iterate] CTGDIS181E Error while evaluating Hook 'On Error' in the Component 'ldap_iterate' (ldap_iterate.initialize_fail).
javax.naming.CommunicationException: simple bind failed: dc1.win.stoeps.home:636
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:231) ~[?:1.8.0]
My first change was to check if the credentials and server information were valid. So I set:
source_ldap_url=ldap://dc1.win.stoeps.home:389
source_ldap_use_ssl=false
Without SSL, I was able to connect to AD LDAP and synchronize the users, but I wanted to get it working with SSL. Starting with some tracing (after enabling SSL again) in solution.properties
:
...
javax.net.debug=all
Running collect_dns.sh
again produces a lot of debug output. The most important part is:
javax.net.ssl|FINE|1C|Thread-3|2023-11-02 12:36:35.149 UTC|Thread.java:1178|Produced client Certificate handshake message (
"Certificates": [
"certificate" : {
"version" : "v3",
"serial number" : "45 01 B2 CD",
"signature algorithm": "MD5withRSA",
"issuer" : "CN=API Admin, OU=test, O=test, L=test, ST=test, C=US",
"not before" : "2006-09-08 18:13:33.000 UTC",
"not after" : "2010-09-07 18:13:33.000 UTC",
"subject" : "CN=API Admin, OU=test, O=test, L=test, ST=test, C=US",
"subject public key" : "RSA"}
]
I wondered about this user, but after some research and checking serverapi/testadmin.jks
, I found an expired API Admin user, and it seems that TDI tries to send his client certificate to the AD LDAP server. AD does not accept the user (because the user is unknown, expired and uses an old signature algorithm).
When we open the file serverapi/testadmin.jks
we find an expired user CN=API Admin, OU=test, O=test, ST=test, C=US
, but why does TDI try to use this certificate?
Some internet searches later, I found the post from Robert Farstad TDI/SDI - Connect to AD over SSL and Michael Urspringer IBM Connections 4: Connect TDI to Secure LDAP server via SSL .
Both added a keystore and a truststore to their tdisol folder, I did just the trustStore. So the keyStore gets inherited from global.properties
which points to serverapi/testadmin.jks
.
Solution
So I changed my solution.properties to:
...
# Truststore
javax.net.ssl.trustStore=ldapcerts.jks
{protect}-javax.net.ssl.trustStorePassword={encr}VK/JddYbHYHDbjQ/jO9...
javax.net.ssl.trustStoreType=jks
# KeyStore (can use the same key store as the trustStore!)
javax.net.ssl.keyStore=ldapcerts.jks
{protect}-javax.net.ssl.keyStorePassword={encr}VK/JddYbHYHDbjQ/jO9...
javax.net.ssl.keyStoreType=jks
and ran collect_dns.sh
again. Now the collect.dns
gets created and contains users, and the next check with sync_all_dns.sh
is successfully synchronizing the AD users to Connections profilesDB.
I assume that AD asks optionally for a client certificate, and as there is one present in the keystore, TDI tries to send it.