LDAP, Certificates and Buildout, oh my!

by Ross Patterson last modified 2009-07-19T04:41:51+02:00
Bringing LDAP and SSL/SASL/TLS certificates into the buildout fold

I hate modified dependencies. I'm none to fond of python-ldap/buildout issues either. So when a client had a patch to modify the various Plone LDAP eggs just to get SSL/SASL/TLS certificates working, I'd had it. I decided it was time to make everythign reproducible and bring LDAP fully into the buildout fold.

The modifications were used to get the python-ldap package to properly authenticate/verify certificates when connecting via SSL/SASL/TLS. I found a Plone setup list post that provides most of the solution.

The right way to get certificates working is to have the underlying openldap installation properly configured to use the certificates. If that's configured properly, python-ldap will just work and no modifications are required to the Plone LDAP eggs.

The post contains the basic buildout configuration layout required to get things working which includes building openldap using CMMI and using a template to install an ldap.conf that tells the openldap build where to find the certificates. I ran into one issue during the openldap build for which some quick googling pointed me to an environment variable workaround. The post uses a buildout part to install the certificates into the buildout configuration, but since the ldap.conf template has to say where the certificates are anyways, I just point to them in the ldap.conf template at etc/ldap.conf.in:

TLS_CACERTDIR /usr/local/ssl/certs

Then we build python-ldap telling it to use the openldap build from the buildout. The final key is to make sure that the custom python-ldap egg is used and not one retrieved by buildout prior to building the custom egg. The way to achieve this is to make sure that the instance(s) eggs option does a valiable substitution from the python-ldap buildout part, thus forcing the right dependency ordering.

The end result is my ldap.cfg file:

extends = base.cfg
parts +=

eggs += ${python-ldap:egg}

recipe = zc.recipe.cmmi
url = ftp://ftp.openldap.org/pub/OpenLDAP/openldap-stable/openldap-stable-20090411.tgz
environment =
# Workaround for "error: storage size of ‘peercred’ isn’t known"
# http://www.openldap.org/lists/openldap-bugs/200808/msg00130.html
extra_options =
    --with-sasl --with-tls --enable-slapd=no

recipe = collective.recipe.template
depends = ${openldap-build:location}
input = etc/ldap.conf.in
output = ${openldap-build:location}/etc/openldap/ldap.conf

recipe = zc.recipe.egg:custom
egg = python-ldap
include-dirs = ${openldap-build:location}/include
library-dirs = ${openldap-build:location}/lib
rpath = ${openldap-build:location}/lib