Apache Hack

August 20, 2008

A few times now there has been discussion about how when authenticating web users with Cosign it would be nice to have access to the related user information that is stored in LDAP, for example the email address and full name. This is something which happened automatically with the kx509 module but Cosign only sets the REMOTE_USER environment variable. Up to now this hasn’t been crucial but whilst looking into moving the bugzilla service from fc5 to sl5 it became clear that this is a requirement. bugzilla uses the email address not the username to identify users.

To solve the problem I’ve come up with a Perl module, named Apache2::LDAPUserInfo, it’s a bit hacky but it does the job. It does mean that mod_perl is required, I think that’s reasonably acceptable and it certainly made developing the module a lot quicker than doing it in C.

Here’s an example configuration:

           <Location />
              CosignProtected On
              AuthType Cosign
              Require valid-user

              PerlSetVar LDAPURL   ldap://127.0.0.1:389
              PerlSetVar LDAPBase  ou=People,dc=inf,dc=ed,dc=ac,dc=uk
              PerlSetVar LDAPAttrs "cn mail"

              PerlFixupHandler Apache2::LDAPUserInfo

              AddHandler cgi-script .cgi
              Options +Indexes +ExecCGI +FollowSymLinks
              DirectoryIndex index.cgi

           </Location>

The trick is that the module runs as a “fixup” handler, that happens after authentication and authorization but before the response delivery so it will work with CGI scripts or mod_perl handlers or anything else.

This takes the authenticated username and does a lookup using Net::LDAP. To reduce the load on the LDAP server the result is cached for 15 minutes in the apache handler using Cache::Simple::TimedExpiry. This seems to be sufficient for something like our bugzilla server but I’m not sure how well it could cope on a heavily loaded web service.

Any LDAP attributes for the user can be extracted, they just need to be specified in the LDAPAttrs variable. The values are put into environment variables prefixed with USER_INFO_. The cn, for example, would be stored in USER_INFO_CN and the mail attribute would be in USER_INFO_MAIL.