This post originated from an RSS feed registered with Ruby Buzz
by Jonathan Weiss.
Original Post: Apache 2.2 authentication with mod_authnz_external
Feed Title: BlogFish
Feed URL: http://blog.innerewut.de/feed/atom.xml
Feed Description: Weblog by Jonathan Weiss about Unix, BSD, security, Programming in Ruby, Ruby on Rails and Agile Development.
The last couple of hours I've been fighting with Apache 2.2 authentication. I must say, it is really a mess, hard to debug, and very frustrating. Many times I wished for Lighttpd to have SVN/DAV and authentication modules.
The scenario is simple, you have a server that hosts your subversion repository and you with to serve it through HTTPS for security and access control. Subversion repositories can be served through the svn+ssh access method but this is inflexible (you can not control access to certain branches of the repository) and not properly encrypted (AFAIK svn+ssh only encrypts the login/authentification but not the actual data stream). So there is only the HTTPS access method left. And only Apache 2 as a server.
Because you need authentication for the subversion access the simplest thing to do is to create UNIX accounts on the server and let Apache authenticate with HTTPAuth over SSL against this database. You would think that the most common UNIX web server would be able to do this out of the box or at least with just one or two configuration knobs. But this is not the case, configuring Apache 2.2 to authenticate against UNIX shadow accounts is a major pain. Quite surprising if you look how easily dovecot (a POP/IMAP mail server, very young in comparison to Apache) does this out of the box.
There are are two recommended ways to do this, PAM (mod_auth_pam2) and using an external provider (mod_authnz_external). Both modules are not core modules and have their problems.
First there is PAM, the Pluggable Authentification Modules. The nice thing about PAM is that (apart from not being under active development any longer) it is itself a pain to configure and debug. Further in order to make mod_auth_pam(2) access to the shadow files you need to either run Apache as root (BIG MISTAKE!) or give the Apache user read access to the shadow files (also not a very good idea!). So after fighting with PAM for some time, I choose to try the second auth module, mod_authnz_external.
Mod_authnz_external hooks into the Apache auth systems and allows you to define external programs that get the username/password combination and return a status code. This way Apache can outsource the authentication process to an external program that has extra privileges and Apache can keep its low security profile. The author of mod_authnz_external ships such an external program, pwauth. Pwauth authenticates against UNIX shadow files or PAM (yea!). Pwauth runs as setuid root in order to do this but this is much better than running Apache as root or give Apache access to the shadow files.
At compile time you tell pwauth which users are allowed to use it (in my case the user www) and which auth backend to use (shadow or PAM). This can be tested like this (in (t)csh):
(I thought that the same configuration would work for Apache, but it didn't.)
When this is working for you, the fun part starts. Telling Apache how to use mod_authnz_external. In theory you just need to load it and explicitly use it in a <Directory > part. But in reality it depends on other authz/authn modules and conflicts with others. Again not fun to debug. After a long period of trail and error I got it working. Comment out ALL authn/authz modules and load only these:
Now you can use it in your virtual host definitions. An important fact is that you need to redefine the external provider in every virtual host entry as it will not be inherited from the root node.
The important entries are the external provides definition with name of "pwauth" just before the closing VirtualHost and the "AuthBasicProvider external && AuthExternal pwauth" inside the Location.
This finally works as wanted. I still can not believe that UNIX auth is so hard with Apache 2.2.
With SSL and mod_dav_svn the virtual host looks like this: