How to Secure CouchDB
CouchDB access as a rest service seems insecure. Anyone can hit the database and delete/add documents once it is exposed.
What strategies are the开发者_如何转开发re to secure the CouchDB?
A lot has changed since 2009, so I'm going to throw an answer in here. This answer is drawn from this page on the wiki.
CouchDB has a _users
database that serves the purpose of defining users. Here's the gist straight from the wiki:
- An anonymous user can only create a new document.
- An authenticated user can only update their own document.
- A server or database admin can access and update all documents.
- Only server or database admins can create design documents and access views and _all_docs and _changes.
Then, for any given database you can define permissions by name or by role. The way authentication is implemented is through a _session
Database. Sending a valid username and password to the _session DB returns an authentication cookie. This is one of several option for CouchDB Authentication. There're a few more options:
- This option is a little old 1.0 was a few months back, we're on 1.2 as of today. But it's still very well outlined.
- And this one from "The Definitive Guide"
Also, depending on which hosting service you might be using, you'll have the option to restrict access to couch over SSL.
Between Node, Couch, and a variety of other technologies that effectively scale horizontally (adding more servers) there's an interesting kind of pressure or incentive being put on developers to make applications that scale well in that manner. But that's a separate issue all together.
The only thing which really works currently security wise is something like this in your CouchDB configuration.
[couch_httpd_auth]
require_valid_user=true
[admins]
admin = sekrit
This puts basic HTTP auth on all of CouchDB. Even this is not well supportet in client libraries. For python e.g. you need a patched library.
The second approach is to put a proxy in front of CouchDB and let the proxy do the authentication and authorization work. Due to CouchDB's RESTful design this is quite easy.
All other approaches must be considered up to now highly experimental.
This may be a little different from your original question. If your couchdb is only a back-end store for a full server app, you can make a special account for the server app to use and require those credentials for access to couchdb.
On the other hand, a pure couch app that people hit directly through a javascript client needs a lot of care to be secure.
Using rewrites is not optional. You need a vhosts config that forces requests to your domain through your rewrites.
Rewrite routes */_all_docs and /*/_design/* to a 404 page. Otherwise users can list every document or get your whole app.
Rewrite generic object access, ie /dbname/:id to a show that can deny access if the user is not allowed to see the document. Unfortunately there is no equivalent workaround for doc-based access control of attachments.
We used haproxy to filter GET requests on _users. There is no legit reason for someone from outside to get a user record or list all your users. We want users to be able to register so we need write access. Currently couch cannot block read access to a db and simultaneously allow writes. It's a bug. Filtering with something like haproxy is our best workaround for now.
Use your own database to keep contact information that is in addition to what is provided by _users. This allows more control over access.
validate_doc_update should carefully reject any writes that should not be allowed.
In every case you need to imagine what someone who understood the system could do to subvert it and lock down those avenues of attack.
CouchDB does cookies, SSL, oauth, and multi-users just fine:
Here's some actual code in python:
from couchdb import Server
s = Server("https://user:password@example.com:6984")
Request the cookie: url encoded above and below, of course
You have to put the credentials twice to get started with the first cookie Both in the Server() constructor as well as the _session POST body
code, message, obj = s.resource.post('_session',headers={'Content-Type' : 'application/x-www-form-urlencoded'}, body="name=user&password=password")
assert(code == 200)
Now you have received a cookie, extract it
cookie = message["Set-Cookie"].split(";", 1)[0].strip()
Now, exit python and restart
Next, Request a server object, but without the username and password this time
s = Server("https://example.com:6984")
s.resource.headers["Cookie"] = cookie
Yay, no password, try to access the database:
db = s["database"]
Optionally set the "persistent" cookie option on the server side to make the cookie last longer.
Have you read CouchDB documentation http://couchdb.apache.org/docs/overview.html? It has a "Security and Validation" section that addresses some of your concerns.
精彩评论