2010/11/29

CouchDB: How to use a reverse proxy server with authentication_db

Japanese edition is here.

A reverse proxy server as a front-end of couchdb seems to be useful for authentication and SSL because there are many examples, such as Apache_As_a_Reverse_Proxy.

According to the couchdb reference, however, it suggests to use the null_authentication_handler and the user=%{LA-U:REMOTE_USER} rewrite rule, it means that an local user will get the admin privilege.

A new authentication handler was developed working with an authentication_db to solve this issue.

If the reverse proxy server and couchdb are placed at different servers, this kind of handler might be useful.

The following patch is for the couchdb-1.0.1, but just added new codes. I think that it should work with another version.

This authentication handler was tested on alix with debian lenny. Some stuffs, especially erlang-R14B and couchdb-1.0.1, were manually compiled.

Setup Procedures

The diff file, 20101127.1.couchdb101.webproxy.diff, are placed at ~/, then move to the couchdb directory and apply it.

$ cd apache-couchdb-1.0.1
$ patch -p1 < ~/20101127.1.couchdb101.webproxy.diff
$ cd src/couchdb
$ make
$ sudo cp couch_httpd_auth.beam /usr/local/lib/couchdb/erlang/lib/couch-1.0.1/ebin/

To use this handler, please modify the local.ini file as following;

authentication_handers setting at local.ini

[httpd]
authentication_handlers = {couch_httpd_auth, webproxy_authentication_handler}

This handler will take two options;

  • require_authentication_db_entry (default: true) - if it's true and the authenticated user name is not on the authentication_db, then the authorization at couchdb will be failed.
  • webproxy_use_secret (default:false) - if it's true and there is no proper X-Auth-CouchDB-Token header, then the access will be denied.

The authentication_db entry is just used to get the user's role. It means just user, type and roles entries are reqruied to each document.

To enable the authentication, you need more configurations usually. Following is an typical example of the local.ini file.

Example of the local.ini file

[httpd]
WWW-Authenticate = Basic realm="administrator"
authentication_handlers = {couch_httpd_auth, webproxy_authentication_handler}

[couch_httpd_auth]
require_valid_user = true
require_authentication_db_entry = true
webproxy_use_secret = false
secret = 329435e5e66be809a656af105f42401e

Set up Apache as A Reverse Proxy

These configurations are just an example. Please modify for your environment.

To setup apache on debian lenny, we need to create setup files on /etc/apache2/sites-enabled directory.

For port 80: /etc/apache2/sites-available/couch

<VirtualHost couch.example.org:80>
	ServerAdmin webmaster@example.org
	DocumentRoot /var/www/
	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>
	ErrorLog /var/log/apache2/error.log
	LogLevel warn
	CustomLog /var/log/apache2/access.log combined
<IfModule mod_alias.c>
        Redirect permanent / https://couch.example.org/
</IfModule>
</VirtualHost>

For port 443: /etc/apache2/sites-available/couch-ssl

<IfModule mod_ssl.c>
<VirtualHost couch.example.org:443>
	ServerAdmin webmaster@example.org
	DocumentRoot /var/www/
	<Directory />
		Options FollowSymLinks
		AllowOverride None
	</Directory>
	ErrorLog /var/log/apache2/error.log
	LogLevel warn
	CustomLog /var/log/apache2/ssl_access.log combined
	SSLEngine on
	SSLCertificateFile    /etc/ssl/certs/ssl-cert-couch.pem
	SSLCertificateKeyFile /etc/ssl/private/ssl-key-couch.pem
	BrowserMatch ".*MSIE.*" \
		nokeepalive ssl-unclean-shutdown \
		downgrade-1.0 force-response-1.0
        <Location />
           AuthType Digest
           AuthName "CouchDB"
           AuthDigestDomain /
           AuthDigestProvider file
           AuthUserFile /etc/apache2/htdigest.db
           Require valid-user
        </Location>
        <IfModule mod_proxy.c>
           ProxyPass / http://127.0.0.1:5984/
           ProxyPassReverse / http://127.0.0.1:5984/
        </IfModule>
</VirtualHost>
</IfModule>

To use above settings, please change that following values and files for your environment.

  • VirtualHost couch.example.org:80
  • Redirect permanent / https://couch.example.org/
  • VirtualHost couch.example.org:443
  • SSLCertificateFile /etc/ssl/certs/ssl-cert-couch.pem
  • SSLCertificateKeyFile /etc/ssl/private/ssl-key-couch.pem
  • AuthUserFile /etc/apache2/htdigest.db

To enable changes, create symbolic-links and restart apache.

$ sudo a2ensite couch
$ sudo a2ensite couch-ssl
$ sudo /etc/init.d/apache2 restart

Set up CouchDB

Possible parameters and settings are explained at the top of this document. This section explains much more details.

require_authentication_db_entry

If it's true, the authenticated username should be described on the authentication_db, such as /_users/org.couchdb.user:username.

If it's the default value, false, the authenticated user can access to the couchdb without an authentication_db entry. In this case, the role of the user set to empty, []. To enable the role, user's authentication_db entry is essential.

webproxy_use_secret

If it's true and there is no X-Auth-CouchDB-Token line at the http request header, then the authorization will be failed.

To add the X-Auth-CouchDB-Token to the request header, the following settings are required.

Modified /etc/apache2/sites-available/couch-ssl

<IfModule mod_proxy.c>
        <IfModule mod_headers.c>
            RequestHeader add X-Auth-CouchDB-Token "c21ec459f6a650dcf6907f2b52e611a069a7aeee"
        </IfModule>
        ProxyPass / http://127.0.0.1:5984/
        ProxyPassReverse / http://127.0.0.1:5984/
</IfModule>

The value of X-Auth-CouchDB-Token can be calculated by SHA1 HMAC as following;

$ erl -pa /usr/local/lib/couchdb/erlang/lib/couch-1.0.1/ebin
1> nl(couch_util).
2> nl(crypto).
3> crypto:start().
4> Secret = <<"329435e5e66be809a656af105f42401e">>.
5> couch_util:to_hex(crypto:sha_mac(Secret,Secret)).
"c21ec459f6a650dcf6907f2b52e611a069a7aeee"

The value of 'Secret' is the value of the secret key on the .ini file.

Security considerations

The default value of the webproxy_use_secret is false.

In this case, if an user connects to couchdb's port directly, such as curl http://127.0.0.1:5984/, with a dummy header, like 'Authorization: Digest username="admin"', then the user will get the admin user's priviledge.

$ curl -H 'Authorization: Digest username="admin"' http://localhost:5984/_session

Please consider the webproxy_use_secret to be enable, but it's a little bit difficult, I guess. So that the default value is false to relax.

Example of a curl command line

If the ssl cert file was confirmed by the self-signed CA, then the cacert.pem file should be append to the curl command line.

$ curl --digest --cacert cacert.pem -u admin:xxxxxx https://couch.example.org/_session

Enjoy!

0 件のコメント: