In Python 2 with the python-ldap library, it worked fine over LDAPs installed with a self-signed certificate (by setting ldap.OPT_X_TLS_NEVER). When the application was upgraded to Python 3, the LDAPs integration ceased to work with the following error:
ldap.SERVER_DOWN: {'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': []}
To look into the error in detail, I have turned the library to debug mode:
ldap.set_option(ldap.OPT_DEBUG_LEVEL, 255)
With debug mode on, I found the client hello and server hello were successful. But after key exchange, the connection suddenly closed without much information:
alert write:warning:close notify
A simple curl test shows the following error:
> curl ldaps://fqdn:636
curl: (60) Peer's certificate issuer has been marked as not trusted by the user.
There are two ways to trust the self-signed certificate:
- Trust the certificate in the Python/Django
- Trust the certificate in the OS
First, you need to ‘download’ the self-signed certificate.
Take a look at what’s installed on the server:
> openssl s_client -connect your-ldap-fqdn:636 -showcerts -verify 5
To download,
> keytool -printcert -sslserver your-ldap-fqdn:636 > mycert.pem
Trust the certificate in the Python/Django
In Python
import ldap
ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
cert_file = '/path/to/mycert.pem'
ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, cert_file)
In Django (django-auth-ldap)
AUTH_LDAP_CONNECTION_OPTIONS:
ldap.OPT_X_TLS_REQUIRE_CERT: ldap.OPT_X_TLS_ALLOW,
ldap.OPT_X_TLS_CACERTFILE: '/path/to/mycert.pem',
ldap.OPT_X_TLS_NEWCTX: 0
}
Trust the certificate in the OS
In RedHat/CentOS, as root, copy the downloaded cert
> cp mycert.pem /etc/pki/ca-trust/source/anchors/
Then update CA trust
> update-ca-trust
For other OS (Ubuntu, Mac, Windows etc) refer to this article: