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 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
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