wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

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 Proxyand 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:
  • 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
The whole magic lies in the Apache configuration (typically to find in /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
As usual YMMV - enjoy
  1. < VirtualHost *: 80>
  2.     ServerAdmin webmaster@localhost
  3.  
  4.     # Removal of eventually spoofed request headers
  5.     RequestHeader unset X -Auth -CouchDB -UserName
  6.     RequestHeader unset X -Auth -CouchDB -Roles
  7.     RequestHeader unset X -Auth -CouchDB -Token
  8.  
  9.     # Needed for CouchDB
  10.     AllowEncodedSlashesOn
  11.  
  12.     # Location of static HTML files
  13.     DocumentRoot /var/www/default
  14.     < Directory />
  15.         OptionsIndexesFollowSymLinks MultiViews
  16.         AllowOverrideNone
  17.         Orderallow, deny
  18.         allow from all
  19.     </ Directory>
  20.  
  21.     # We don't want to be an open relay
  22.     ProxyRequestsOff
  23.     ProxyPreserveHostOn    
  24.     ProxyPass /couchdb http://localhost: 5984 nocanon
  25.     ProxyPassReverse /couchdb http://localhost: 5984
  26.  
  27.     # Role mapping for couch
  28.     RewriteMap role -map dbm:/var/secrets/passwd/rolemapping.map
  29.  
  30.     < Location /couchdb>
  31.         AuthType Basic
  32.         AuthName couchdb
  33.         AuthUserFile /var/secrets/passwd/users
  34.         AuthGroupFile /var/secrets/passwd/groups
  35.         Orderallow, deny
  36.         Allow from all
  37.  
  38.         # THIS WILL PROMPT AUTHENTICATION
  39.         Require valid -user
  40.  
  41.         # Request headers for CouchDB from authenticated user
  42.         RewriteEngineOn
  43.         RewriteCond % {LA -U:REMOTE_USER }(. +)
  44.         RewriteRule . -[E=CUSER:%1 ]
  45.         RewriteCond % {LA -U:REMOTE_USER }(. +)
  46.         RewriteRule . -[E=CROLE:$ {role -map:%1|guest }]
  47.         RequestHeader set X -Auth -CouchDB -UserName "%{CUSER}e" env=CUSER
  48.         RequestHeader set X -Auth -CouchDB -Roles "%{CROLE}e" env=CROLE
  49.     </ Location>
  50. </ VirtualHost>

Posted by on 23 January 2013 | Comments (2) | categories: CouchDB

Comments

  1. posted by Stephan H. Wissel on Friday 25 July 2014 AD:
    The link in the bullet list points to the instructions how to make a mapping file. It is a space separated file with roles

    johndoe admin,family,dev
    janedoe dev

    then you use httx2dbm tool to create the map file. Which part didn't work?
  2. posted by Steven Wagger on Friday 25 July 2014 AD:
    I've been looking for this! Thank you!

    But it would be kind from you to include the instructions to create the rolemapping.map file. I've been trying to make it work without success... :'(