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
 including Apache's own wiki. 
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 chicken string and duct tape  combination of Apache modules, but works surprisingly well. 
The participants:
 
					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>
 
Posted by Stephan H Wissel on 23 January 2013 | Comments (2) | categories: CouchDB