Python 3 LDAPS with self-signed certificate

One9twO
2 min readOct 19, 2021

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:

  1. Trust the certificate in the Python/Django
  2. 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:

--

--