2010年2月21日日曜日

Secure programming in CouchDB applications - View protection.

I wrote secure programming notes for CouchDB applications. This is written in Japanese, so I've started the translation into English.

--

The first topic is about "View protection" in CouchDB.

For example, we prepare the view as follows.

function(doc){
  emit([doc.owner, doc.created_at], doc.protected);
}

The result of this view will be as follows.

{ "total_rows": 1234, "offset", 0, "rows": [
{"id" : "...", "key": ["user1", "2009/01/01"], value: {...}},
{"id" : "...", "key": ["user1", "2009/01/01"], value: {...}},
{"id" : "...", "key": ["user1", "2009/01/02"], value: {...}},
{"id" : "...", "key": ["user2", "2009/01/02"], value: {...}},
{"id" : "...", "key": ["user2", "2009/01/02"], value: {...}},
...
]}

If we have a security requirment that only document owner can view the doc.protected field, this view should be handled carefully. The current CouchDB view implemetation has no authentication function so that authorization function cannot be implemented.

So how do we solve this requirement?

The answer is:

  • to use a reverse proxy to forbid direct view access.
  • to use _list functions for view result processing.

And we need to check parameters in our list function.

function(head, req){
  // !code vendor/json/json2.js
  var startkey = JSON.parse(req.query.startkey || "[]");
  var endkey   = JSON.parse(req.query.endkey || "[]");
  if(startkey[0] == endkey[0] &&  
     startkey[0] == req.userCtx.name ){
     while(row == getRow()){
        // row.key[0] == req.userCtx.name is always true.
     }
  }else{
     // not authorized     
  }
}

1 件のコメント:

J Chris A さんのコメント...

with 0.11 you could potentially use couchdb vhosts + _rewrite to restrict access to a _list function. this accomplishes the same thing without requiring a proxy.

best docs for all this is currently the test-suite. :)