3

I’m currently working on a docker-compose setup that can be used to deploy a cluster of CouchDB 2 nodes. I’ve finally got the nodes working and the data syncing across nodes, but unless I am mistaken, it appears that CouchDB does not sync user sessions.

My setup has 3 nodes and uses an haproxy setup almost identical to haproxy.cfg. As per my configuration, haproxy routes incoming traffic on port 5984 to port 5984 on all 3 nodes.

Assume an admin username of root and password of password.

I first log in with:

curl -vX POST http://localhost:5984/_session -H 'Content-Type: application/x-www-form-urlencoded' -d 'name=root&password=password'

Note the returned AuthSession is used below as AUTHSESSION.

Then, I issue the following:

curl -X PUT http://localhost:5984/mydb --cookie AuthSession=AUTHSESSION -H "X-CouchDB-WWW-Authenticate: Cookie" -H "Content-Type: application/x-www-form-urlencoded"

This usually fails with “You are not a server admin.” I can continue to issue the same PUT and it will eventually succeed as I assume that haproxy eventually routes the request to the single node with which I am authenticated. As haproxy is using round robin there is a 1 in 3 chance that I will hit the target node.

I would think that CouchDB 2 could handle syncing user sessions across nodes. Am I making a silly assumption here?

(Please see run cluster via docker-compose to replicate my setup)

Update with specific solution for my docker-compose setup

As per @lossleader, you need to set the secret in the [couch_httpd_auth] section so that it is identical across nodes. Moreover, you need to set the same admin username and password in the [admins] section. The detail I missed here is that all nodes must have the exact same password hash in the .ini file. Having the same cleartext password is not enough, as otherwise, each node will generate its own salt and generate a different hash.

See run cluster via docker-compose for my complete setup.

redgeoff
  • 2,675
  • 1
  • 20
  • 38
  • have you set the same secret on each node? http://docs.couchdb.org/en/2.0.0/config/auth.html#couch_httpd_auth/secret – lossleader May 13 '17 at 23:25
  • @lossleader, just tried setting it in local.ini and unfortunately, it doesn't seem to make a difference. – redgeoff May 14 '17 at 01:40
  • If the secret is now the same, I think the difference is that the nodes were probably allowed to salt/encrypt the admin users separately, I copy one node's admin lines into my config after it has run. – lossleader May 14 '17 at 10:52
  • 1
    @lossleader, you are absolutely correct! I modified my config so that the subsequent nodes pull the exact password has from the first node and it works: https://github.com/redgeoff/couchdb-docker/commit/f4952a7cadd7169c154f69edaa844b97f809e73a – redgeoff May 15 '17 at 14:32

2 Answers2

7

Short answer: yes.

Long answer:

As others have commented, couchdb doesn't know the sessions its made, so it's true there's no mechanism to sync sessions themselves, but there are two non-session things that you need to sync yourself before a session cookie made on one node of a cluster will be valid on any other.

[couch_httpd_auth] secret = foo

This is the secret value used to sign session cookies. If not present when a session cookie is requested, it is set to a random value. Each node of a cluster will, naturally, generate a different value.

So, before startup, arrange for this value to be set to a large, random value but the same on all nodes of your cluster.

[admins] foo = -pbkdf2-2cbae77dc3d2dadb43ad477d312931c617e2a726,cd135ad4d6eb4d2f916cba75935c3ce7,10

This section contains the salted password hashes of each admin user. The salt is included in the signature in the session cookies. On password change, the salt is re-randomized, so the effect of including salt is that it invalidates the session cookies from before the password change.

You also need this section to be the same on all nodes. Each node will generate a random salt when hashing the admin password.

Better to generate this section externally as part of your node provisioning automation.

I hope that gets you started. We would like to improve this situation in a future release, it obviously reflects the pre-clustering versions of couchdb.

Robert Newson
  • 4,541
  • 16
  • 18
4

CouchDB session tokens are just an HMAC hash of the user's password salt, the server secret, and the time. Sessions aren't stored in CouchDB at all, even on a single-node system. So there is nothing to sync.

You can, and many people do, generate sessions entirely programatically, external to CouchDB.

Flimzy
  • 60,850
  • 13
  • 104
  • 147