Authentication and CouchDB

I needed to expose an internal “CouchDB”:http://couchdb.apache.org/ server to the outside world. When it was only accessible behind a firewall, it was not a big deal to throw an “Admin Party”:http://guide.couchdb.org/editions/1/en/security.html#party. But opening it up to the outside world meant having to figure out how to lock down the CouchDB server. This post collects some of the articles and code snippets I tracked down while researching how to secure a CouchDB server.

For my particular use case I needed to end the Admin Party and ensure that only an authenticated user could modify my application database.

I came across a “Securing CouchDB”:http://lizconlan.github.com/sandbox/securing-couchdb.html post that got me pointed in the right direction. I followed the steps outlined in that post: applying the security settings to both the _users database and my application database. At this point you needed to be authenticated as a server admin in order to make server changes. Furthermore, you also needed to be authenticated as a user with the “admin” role in order to make updates to the application database. However, none of the steps in that post talked about creating a regular user (non-server admin), so one more user still needed to be created.

I clicked around the Futon interface looking for a way to add some _regular_ users, as apposed to the _server admin_ user I had already created by clicking the “Fix this” link (as described in the “Securing CouchDB” post). I found nothing. It appears that you just have to create new entries in the _users database manually.

After doing some searching a page turned up on the CouchDB wiki about “Security Features”:http://wiki.apache.org/couchdb/Security_Features_Overview#Authentication_database that described what an entry for a regular user should look like. I used the Futon interface to create a “batch” user with the following attributes:

  {
    "_id"          : "org.couchdb.user:client",
    "type"         : "user",
    "name"         : "batch",
    "roles"        : ["admin"],
    "password_sha" : "fe95df1ca59a9b567bdca5cbaf8412abd6e06121",
    "salt"         : "4e170ffeb6f34daecfd814dfb4001a73"
  }

You need to generate the password_sha and salt manually as well. There are some snippets on the “Security Features” page that show how to do this in a number of programming languages. Here is a Python script from some of the example code on that page:

  import hashlib
  import os
  import sys

  if len(sys.argv) < 2:
    sys.exit('Usage: %s password' % sys.argv[0])

  salt = os.urandom(16).encode('hex')
  h=hashlib.sha1()
  h.update(sys.argv[1])
  h.update(salt)
  h.digest()
  print "passhword_sha: " + h.hexdigest()
  print "salt: " + salt

At this point my server was locked down so that only an authenticated server admin could make server changes and only the "batch" user could make updates to my application database. I tested this out in IRB using the CouchRest gem and specifying the username/password in the URL:

  CouchRest.database!("http://batch:[email protected]/mydb")

One thing to note is reading the contents of the application database is still possible without any form of authentication. This was not an issue for my particular application, but it should be possible to further restrict the service by adding a required username or role to the "readers" permissions.