Introduction to CouchDB with .NET part 23: role-based security in CouchDB
July 5, 2017 1 Comment
Introduction
In the previous post we continued our exploration of security in CouchDB. In particular we looked at database members who have read and write access to a database. There’s no database user specifically tailored for read-only access. A more fine-grained solution is provided by update design functions where can specifically block users from modifying database documents thereby making them read-only users. This process can be difficult to manage since the update function must potentially be updated with new database members added to the list of users.
An important aspect of security in CouchDB is gradual restrictions. A CouchDB server start off its life as open to the public with no restrictions on the access rights whatsoever. We have to create a server admin and other users and then define the database admins and members for each database. Until then each database is still open to the default CouchDB user.
This is where database roles can be a better solution. That is also the main topic of this post.
Preparation
For this demo we’ll create a couple of new users in CouchDB. We do this so that the previous examples and demos remain untouched for later reference. Log in as a server admin to the Fauxton UI and create the following 5 users:
{ "_id": "org.couchdb.user:sophia", "name": "sophia", "password": "secret", "roles": ["database-admin"], "type": "user" } { "_id": "org.couchdb.user:james", "name": "james", "password": "secret", "roles": ["database-read-write"], "type": "user" } { "_id": "org.couchdb.user:olivia", "name": "olivia", "password": "secret", "roles": ["database-read-write"], "type": "user" } { "_id": "org.couchdb.user:kevin", "name": "kevin", "password": "secret", "roles": ["database-read"], "type": "user" } { "_id": "org.couchdb.user:daniel", "name": "daniel", "password": "secret", "roles": ["database-read"], "type": "user" }
Note how we assigned database roles to them in the roles array. These role names are arbitrary and are up to us to define, they are not provided by CouchDB. They are descriptive enough for you to guess what these roles will entail.
Database users by role
For the demo I’ve picked the restaurants database that we used for the Mango queries. However, it’s up to you to pick a different one or create a brand new one. We’ll now add role-based permissions to the restaurants database. Click the Permissions menu for the database and add the following roles:
Now log in as one of the users we created in the previous post such as Peter. They won’t be able to load the restaurants database since they don’t belong to any of the groups we defined above.
Next log in as Olivia who belongs to the read-write group. She will be able to see the restaurants database and modify its documents. However, she’ll fail to enter a new design document:
That should be no surprise, we saw that before when we added specific users as database members. Here we see the same thing but on the database role level.
Read-only roles
Log in as Sophia who is the database admin of the restaurants database. Add the following design document:
{ "_id": "_design/auth", "validate_doc_update": "function(newDocument, oldDocument, userContext){ if ( userContext.roles.indexOf('database-admin') > -1 && userContext.roles.indexOf('database-read-write') > -1) throw ({forbidden: 'You have no write access to this database'});}" }
That’s very similar to the code that checks for the username in the previous code. Here we’re checking the presence of a role in an array instead of checking whether the usernames match.
Log in as Kevin or Daniel and try to add a new document to the restaurants database. It should fail with the following message:
Save failed: You have no write access to this database
However, James, Olivia and Sophia will be able to read and write documents. I think you agree that role-based authorisation makes the creation of read-only access easier to maintain than the username equivalent solution.
We’ll look at how to use cookie-based authentication for the CouchDB HTTP API in the next post.
You can view all posts related to data storage on this blog here.
Pingback: CouchDB Weekly News, July 6, 2017 – CouchDB Blog