Running a CouchDB with the authenticated Apache HTTP user
Apache CouchDB shares the same Stallgeruch with Domino thanks to sharing a warden at some time. So during the festive season I gave it a spin.There is ample literature around to get you started with CouchDB
So I was looking for something more sporty.
Since Domino 9.0 ships with IBM's version of the Apache HTTP server I was wondering if I could setup couchDB behind an Apache reverse Proxy and make couchDB recognize the authenticated user accessing the couchDB as kind of a poor man's single sign on.
I used Apache's basic authentication (only via HTTPs please), but it, in theory, would work with any authentication scheme that provides a username as outcome.
The whole solution required a bit of
The participants:
- proxy_authentification_handler (note the unconventional spelling): a couchDB module that accepts authentication information in the request header. You have to add that to the httpd section for the key authentication handlers. My entry looks like this:
{couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, proxy_authentification_handler}, {couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler} - mod_headers: Create, remove, alter headers. Anything coming in gets stripped of eventually fake headers and then the couchDB headers reapplied.
- mod_proxy: The core proxy capability
- mod_rewrite: The dark magic of Apache. Used here mainly to lookup roles
- mod_auth_basic: Used for authentication here, any other mechanis should work too
/etc/apache2/sites-enabled. Here is what worked for me:
- In line 5-7 I remove any header that might be in the original request to prevent identity spoofing
- Line 10 allows slashes to be transmitted encoded. I found it wouldn't work without that
- Line 13-19 are standard Apache static files
- Line 22-25 establish the regular reverse proxy pattern with the forward proxying switched off, nothing special there
- Line 28 defines a simple lookup map which in a production system probably would be a LDAP or database query
- Line 31-36 establish the authentication mechanism. For a production system you would use something more sophisticated to run
- Line 39 is essential: it simply states: only authenticated users here please
- The dark magic happens in lines 42-48
- Line 43 and 45 extract the identified user for use in a RewriteRule. It seems you can use the extracted variable only once, hence the duplicate lines (I might also simply not be skilled enough
) - Line 44 assigns the current user to the variable
CUSER - Line 46 looks up the roles the user has into
CROLE. Make sure your admin user has the role_admin. Multiple entries separated by comma and no spaces. If a user has no roles, (s)he is assigned the guest role - Lines 47/48 finally add them to the header
- I didn't use the Token in this example
- <VirtualHost *:80>
- ServerAdmin webmaster@localhost
- # Removal of eventually spoofed request headers
- RequestHeader unset X-Auth-CouchDB-UserName
- RequestHeader unset X-Auth-CouchDB-Roles
- RequestHeader unset X-Auth-CouchDB-Token
- # Needed for CouchDB
- AllowEncodedSlashes On
- # Location of static HTML files
- DocumentRoot /var/www/default
- <Directory />
- Options Indexes FollowSymLinks MultiViews
- AllowOverride None
- Order allow,deny
- allow from all
- </Directory>
- # We don't want to be an open relay
- ProxyRequests Off
- ProxyPreserveHost On
- ProxyPass /couchdb http://localhost:5984 nocanon
- ProxyPassReverse /couchdb http://localhost:5984
- # Role mapping for couch
- RewriteMap role-map dbm:/var/secrets/passwd/rolemapping.map
- <Location /couchdb>
- AuthType Basic
- AuthName couchdb
- AuthUserFile /var/secrets/passwd/users
- AuthGroupFile /var/secrets/passwd/groups
- Order allow,deny
- Allow from all
- # THIS WILL PROMPT AUTHENTICATION
- Require valid-user
- # Request headers for CouchDB from authenticated user
- RewriteEngine On
- RewriteCond %{LA-U:REMOTE_USER} (.+)
- RewriteRule . - [E=CUSER:%1]
- RewriteCond %{LA-U:REMOTE_USER} (.+)
- RewriteRule . - [E=CROLE:${role-map:%1|guest}]
- RequestHeader set X-Auth-CouchDB-UserName "%{CUSER}e" env=CUSER
- RequestHeader set X-Auth-CouchDB-Roles "%{CROLE}e" env=CROLE
- </Location>
- </VirtualHost>





