Skip to content

Instantly share code, notes, and snippets.

@jhs
Created September 12, 2011 18:34
Show Gist options
  • Save jhs/1212012 to your computer and use it in GitHub Desktop.
Save jhs/1212012 to your computer and use it in GitHub Desktop.
In-progress write-only DB implementation. (Will be multiple smaller commits when I post to JIRA)
Currently, we can only grant dual read-write access in the _security
object "members" section. A user can either do both (name or role in
.members), or do neither (name and role not in .members). This
prevents a very common requirement for couch apps: sending private
information from less-privileged users to more-privileged users. There
is no (reasonable) way to make an "inbox" where anybody may create a
doc for me, but only I may read it. An inbox database allows
user-to-user, or user-to-admin private messages. (Don't think chat
messages. Think asynchronous notifications. With a per-user inbox,
think service requests and responses.)
There is no reason _security.members (formerly .readers) should
control write access. validate_doc_update() functions do this better.
This patch adds a boolean flag, _security.members.required_to_write.
If it is false, then CouchDB will allow document updates from
non-members, giving validate_doc_update() the final word on accepting
or rejecting the update.
Requirements:
1. Everything about _security stays the same (backward-compatible)
2. If members.required_to_write === false, then PUT and POST queries are allowed to proceed.
3. All updates are still subject to approval by all validate_doc_update functions, same as before.
Tests:
database with no validate_doc_update, members != []
member can write
non-member cannot write
add validate_doc_update which only accepts if .is_ok == true
member can write
For non-member and anonymous:
* cannot write even with .is_ok = true
non-member cannot write even with .is_ok == true
change to .required_to_write = false // BEGIN TESTS OF NEW FUNCTIONALITY
For non-member and anonymous:
* For method in PUT, POST
* cannot update with .is_ok = false (still subject to validator)
* can create with .is_ok = true
* can update with .is_ok = true
* can update via an _update function
* None of these should work:
* POST a temp view
* POST a view with {"keys":["keys", "which", "exist", "and some which don't"]
* POST /db/exist X-HTTP-Method-Override: GET
* POST /db/_all_docs
* POST /db/_changes
* For _show and _list:
* POST
* OPTIONS
* VARIOUS, NONSTANDARD, METHODS (in case Couch allows them later)
* These syntax/semantic errors in _security should all fail:
* .members.required_to_write = null, [missing], "", 0, true, 1, "false", [false], {false:false}
* .required_to_write = false
Notes:
* Known changes to the security model. I consider these all to be
either very unlikely in practice, or worth the trade-off. * If you
write to a write-only DB, you know a subset of its documents (but
that's the point)
* An _update function could reveal a document to the user, with or
without changing it. However, an admin must install such a misguided
update function. * You can launch timing attacks to learn
information about validate_doc_update
* You might discover whether doc IDs exist in the DB or not
* You might discover a well-known open source validation function.
You can look for bugs in its source code.
* Zero or more things which Jason can't think of
* It would be nice
to have _security.readers, _security.writers, and maybe sugar
_security.members which implicitly populates both. A write-only DB
would have _security.readers = {}, security.writers.roles =
["_anonymous"]. However this patch maintains compatibility with the
1.x codebase.
* The patch is not correct since check_is_member returns ok rather
than throwing. The user has *non-member permission* to write but is
not really a member. A patch to implement the correct logic would be
more substantial. * Unit tests:
* I'm a test suite sophomore: lots of copy, paste, modify (which I
call "code reuse"). If one reviews the code, that is the most
important part to review. * Some tests are redundant (confirming
that a member can write a valid document) however since this is
feature is security-related I wore the belt and suspenders.
* I do not like how _security.members.required_to_write must === false
to enable this feature. Existing or legacy _security objects will have
.required_to_write === undefined which is falsy. I welcome suggestions
for this flag name. Points awarded for: * You set it to `true` to
activate the feature
* Self-documenting, says what it means
* Understandable to ESL programmers
* Brief
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment