FAQ
Repository: couchdb
Updated Branches:
   refs/heads/2452-users-db-security-on-clustered-interface [created] ed4a4a9e2


Teach dev/run to clear nodes DB

This commit makes dev/run replace the nodes DB with an empty DB
before adding the nodes doc. This changes the previous behaviour
which was to just try adding the docs and ignore conflicts.

The change makes it possible for a developer to run `dev/run -n 1`
(to spawn a single node cluster) having previously run `dev/run`
(which spawns a three node cluster). Without replacing the nodes
DB the `dev/run -n 1` single-node cluster would still have two
other nodes in the nodes DB and therefore not work correctly.

Note that we explicitly delete each node doc rather than deleting
the whole database because the cluster membership layer gets upset
when the nodes database itself is deleted/recreated.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/49f03e2b
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/49f03e2b
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/49f03e2b

Branch: refs/heads/2452-users-db-security-on-clustered-interface
Commit: 49f03e2be48dac56c27b220b11cd70676df50f99
Parents: 126ec76
Author: Mike Wallace <mikewallace@apache.org>
Authored: Wed Nov 26 23:17:04 2014 +0000
Committer: Mike Wallace <mikewallace@apache.org>
Committed: Wed Dec 3 19:11:09 2014 +0000

----------------------------------------------------------------------
  dev/run | 23 +++++++++++++++++++++++
  1 file changed, 23 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/49f03e2b/dev/run
----------------------------------------------------------------------
diff --git a/dev/run b/dev/run
index ada5492..bce55f1 100755
--- a/dev/run
+++ b/dev/run
@@ -17,6 +17,7 @@ import contextlib
  import functools
  import glob
  import inspect
+import json
  import optparse
  import os
  import re
@@ -230,6 +231,7 @@ def hashify(pwd, salt=COMMON_SALT, iterations=10, keylen=20):
  def startup(ctx):
      atexit.register(kill_processes, ctx)
      boot_nodes(ctx)
+ reset_nodes_db(ctx, "127.0.0.1")
      join_nodes(ctx, "127.0.0.1", 15986)


@@ -295,6 +297,27 @@ def boot_node(ctx, node):
      return sp.Popen(cmd, stdin=sp.PIPE, stdout=log, stderr=sp.STDOUT, env=env)


+@log('Reset nodes DB')
+def reset_nodes_db(ctx, host):
+ _, port = get_ports(1)
+ conn = httpclient.HTTPConnection(host, port)
+ conn.request('GET', '/nodes/_all_docs')
+ resp = conn.getresponse()
+ if not resp.status == 200:
+ print('Could not read nodes DB documents', resp.reason)
+ exit(1)
+ nodes = json.loads(resp.read())['rows']
+ for node in nodes:
+ node_id = node['id']
+ rev = node['value']['rev']
+ conn = httpclient.HTTPConnection(host, port)
+ conn.request('DELETE', '/nodes/{0}?rev={1}'.format(node_id, rev))
+ resp = conn.getresponse()
+ if not resp.status == 200:
+ print('Failed to reset nodes DB', resp.reason)
+ exit(1)
+
+
  @log('Join nodes into cluster')
  def join_nodes(ctx, host, port):
      for node in ctx['nodes']:

Search Discussions

  • Mikewallace at Dec 4, 2014 at 10:52 am
    Make users_db_security.js use N=1 clusters only

    The users_db_security.js test will not work against a multi-node
    cluster because it relies on config settings being made by the
    test code. Because there is no generic way of discovering the
    locations of the other nodes on a dev cluster (they may be on
    unexpected ports for one reason or another) it is only possible
    to guarantee those settings are made on a single node.

    This commit therefore forces the users_db_security.js test to run
    against a single node cluster by:

      - setting the cluster variables to N=Q=R=W=1
      - excluding the test in the Makefile and running it explicitly
        with `dev/run -n 1`
      - teaching run_on_modified_server to correctly preserve the old
        config settings when nested run_on_modified_server calls are
        made

    COUCHDB-2452


    Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
    Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/ed4a4a9e
    Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/ed4a4a9e
    Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/ed4a4a9e

    Branch: refs/heads/2452-users-db-security-on-clustered-interface
    Commit: ed4a4a9e2bfbc906bc2339007fe7ef13137eba88
    Parents: 23d79b3
    Author: Mike Wallace <mikewallace@apache.org>
    Authored: Mon Dec 1 13:22:46 2014 +0000
    Committer: Mike Wallace <mikewallace@apache.org>
    Committed: Wed Dec 3 19:11:13 2014 +0000

    ----------------------------------------------------------------------
      Makefile | 1 +
      share/www/script/couch_test_runner.js | 8 +++++
      share/www/script/test/users_db_security.js | 43 ++++++++++++++++++++-----
      test/javascript/run | 7 +++-
      4 files changed, 50 insertions(+), 9 deletions(-)
    ----------------------------------------------------------------------


    http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed4a4a9e/Makefile
    ----------------------------------------------------------------------
    diff --git a/Makefile b/Makefile
    index 986d2dc..7f57830 100644
    --- a/Makefile
    +++ b/Makefile
    @@ -69,3 +69,4 @@ eunit: compile

      javascript: compile
       @dev/run -q test/javascript/run
    + @dev/run -n 1 -q test/javascript/run share/www/script/test/users_db_security.js

    http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed4a4a9e/share/www/script/couch_test_runner.js
    ----------------------------------------------------------------------
    diff --git a/share/www/script/couch_test_runner.js b/share/www/script/couch_test_runner.js
    index efc4dc2..0617efd 100644
    --- a/share/www/script/couch_test_runner.js
    +++ b/share/www/script/couch_test_runner.js
    @@ -363,6 +363,14 @@ function makeDocs(start, end, templateDoc) {
      }

      function run_on_modified_server(settings, fun) {
    + // Clone settings so we don't overwrite oldValue when making nested run_on_modified_server calls
    + var settings = settings.map(function(s) {
    + return {
    + section: s.section,
    + key: s.key,
    + value: s.value
    + };
    + });
        try {
          // set the settings
          for(var i=0; i < settings.length; i++) {

    http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed4a4a9e/share/www/script/test/users_db_security.js
    ----------------------------------------------------------------------
    diff --git a/share/www/script/test/users_db_security.js b/share/www/script/test/users_db_security.js
    index ae13950..3eb446c 100644
    --- a/share/www/script/test/users_db_security.js
    +++ b/share/www/script/test/users_db_security.js
    @@ -10,7 +10,34 @@
      // License for the specific language governing permissions and limitations under
      // the License.
      couchTests.users_db_security = function(debug) {
    + var clusterVars = [{
    + section: "cluster",
    + key: "q",
    + value: "1"
    + },
    + {
    + section: "cluster",
    + key: "n",
    + value: "1"
    + },
    + {
    + section: "cluster",
    + key: "w",
    + value: "1"
    + },
    + {
    + section: "cluster",
    + key: "r",
    + value: "1"
    + }
    + ];
        function run_test_against_url(url) {
    + // Ensure users DB is created with desired Q/N
    + run_on_modified_server(clusterVars, function() {
    + CouchDB.urlPrefix = url;
    + new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"});
    + });
    +
          CouchDB.urlPrefix = url;
          var usersDb = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"});
          if (debug) debugger;
    @@ -113,7 +140,7 @@ couchTests.users_db_security = function(debug) {

            CouchDB.urlPrefix = '';
            // create server admin
    - run_on_modified_server([
    + run_on_modified_server(clusterVars.concat([
              {
                section: "couch_httpd_auth",
                key: "iterations",
    @@ -124,7 +151,7 @@ couchTests.users_db_security = function(debug) {
                key: "jan",
                value: "apple"
              }
    - ], function() {
    + ]), function() {

              CouchDB.urlPrefix = url;
              // anonymous should not be able to read an existing user's user document
    @@ -327,7 +354,7 @@ couchTests.users_db_security = function(debug) {
              TEquals(true, CouchDB.login("jan", "apple").ok);
            });

    - run_on_modified_server([
    + run_on_modified_server(clusterVars.concat([
              {
                section: "couch_httpd_auth",
                key: "iterations",
    @@ -363,7 +390,7 @@ couchTests.users_db_security = function(debug) {
                key: "jan",
                value: "apple"
              }
    - ], function() {
    + ]), function() {
              var res = usersDb.open("org.couchdb.user:jchris");
              TEquals("jchris", res.name);
              TEquals("user", res.type);
    @@ -396,7 +423,7 @@ couchTests.users_db_security = function(debug) {
              TEquals(true, CouchDB.login("jan", "apple").ok);
            });

    - run_on_modified_server([
    + run_on_modified_server(clusterVars.concat([
              {
                section: "couch_httpd_auth",
                key: "iterations",
    @@ -432,7 +459,7 @@ couchTests.users_db_security = function(debug) {
                key: "jan",
                value: "apple"
              }
    - ], function() {
    + ]), function() {
              TEquals(true, CouchDB.login("jchris", "couch").ok);

              try {
    @@ -455,13 +482,13 @@ couchTests.users_db_security = function(debug) {
          };

          usersDb.deleteDb();
    - run_on_modified_server(
    + run_on_modified_server(clusterVars.concat(
            [{section: "couch_httpd_auth",
              key: "iterations", value: "1"},
             {section: "couch_httpd_auth",
              key: "authentication_db", value: usersDb.name},
             {section: "chttpd_auth",
    - key: "authentication_db", value: usersDb.name}],
    + key: "authentication_db", value: usersDb.name}]),
            testFun
          );
          usersDb.deleteDb(); // cleanup

    http://git-wip-us.apache.org/repos/asf/couchdb/blob/ed4a4a9e/test/javascript/run
    ----------------------------------------------------------------------
    diff --git a/test/javascript/run b/test/javascript/run
    index ab145b1..4b272ba 100755
    --- a/test/javascript/run
    +++ b/test/javascript/run
    @@ -37,6 +37,10 @@ SCRIPTS = """
          test/javascript/test_setup.js
      """.split()

    +EXCLUDE = """
    + share/www/script/test/users_db_security.js
    +""".split()
    +
      RUNNER = "test/javascript/cli_runner.js"


    @@ -109,7 +113,8 @@ def main():
              args = ["share/www/script/test"]
          for name in args:
              if os.path.isdir(name):
    - tests.extend(glob.glob(os.path.join(name, "*.js")))
    + tests_in_dir = glob.glob(os.path.join(name, "*.js"))
    + tests.extend([t for t in tests_in_dir if not t in EXCLUDE])
              elif os.path.isfile(name):
                  tests.append(name)
              else:
  • Mikewallace at Dec 4, 2014 at 10:52 am
    Test _users security on the cluster and admin port

    This commit modifies the _users DB security test so that it tests
    the authentication DB against the clustered interface in addition
    to the admin interface.

    Previously this test was only being run against the admin port.

    COUCHDB-2452


    Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
    Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/23d79b3f
    Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/23d79b3f
    Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/23d79b3f

    Branch: refs/heads/2452-users-db-security-on-clustered-interface
    Commit: 23d79b3f606245ab657900fe7b1bc6ef77ace16e
    Parents: 49f03e2
    Author: Mike Wallace <mikewallace@apache.org>
    Authored: Thu Nov 27 15:13:44 2014 +0000
    Committer: Mike Wallace <mikewallace@apache.org>
    Committed: Wed Dec 3 19:11:12 2014 +0000

    ----------------------------------------------------------------------
      share/www/script/test/users_db_security.js | 687 +++++++++++++-----------
      1 file changed, 369 insertions(+), 318 deletions(-)
    ----------------------------------------------------------------------


    http://git-wip-us.apache.org/repos/asf/couchdb/blob/23d79b3f/share/www/script/test/users_db_security.js
    ----------------------------------------------------------------------
    diff --git a/share/www/script/test/users_db_security.js b/share/www/script/test/users_db_security.js
    index f2ca8bc..ae13950 100644
    --- a/share/www/script/test/users_db_security.js
    +++ b/share/www/script/test/users_db_security.js
    @@ -9,100 +9,111 @@
      // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
      // License for the specific language governing permissions and limitations under
      // the License.
    -
      couchTests.users_db_security = function(debug) {
    - var usersDb = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"});
    - if (debug) debugger;
    -
    - function wait(ms) {
    - var t0 = new Date(), t1;
    - do {
    - CouchDB.request("GET", "/");
    - t1 = new Date();
    - } while ((t1 - t0) <= ms);
    - }
    + function run_test_against_url(url) {
    + CouchDB.urlPrefix = url;
    + var usersDb = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"});
    + if (debug) debugger;
    +
    + function wait(ms) {
    + var t0 = new Date(), t1;
    + do {
    + CouchDB.request("GET", "/");
    + t1 = new Date();
    + } while ((t1 - t0) <= ms);
    + }

    - var loginUser = function(username) {
    - var pws = {
    - jan: "apple",
    - jchris: "mp3",
    - jchris1: "couch",
    - fdmanana: "foobar",
    - benoitc: "test"
    + var loginUser = function(username) {
    + var pws = {
    + jan: "apple",
    + jchris: "mp3",
    + jchris1: "couch",
    + fdmanana: "foobar",
    + benoitc: "test"
    + };
    + var username1 = username.replace(/[0-9]$/, "");
    + var password = pws[username];
    + T(CouchDB.login(username1, pws[username]).ok);
          };
    - var username1 = username.replace(/[0-9]$/, "");
    - var password = pws[username];
    - T(CouchDB.login(username1, pws[username]).ok);
    - };
    -
    - var open_as = function(db, docId, username) {
    - loginUser(username);
    - try {
    - return db.open(docId, {"anti-cache": Math.round(Math.random() * 100000)});
    - } finally {
    - CouchDB.logout();
    - }
    - };
    -
    - var view_as = function(db, viewname, username) {
    - loginUser(username);
    - try {
    - return db.view(viewname);
    - } finally {
    - CouchDB.logout();
    - }
    - };
    -
    - var save_as = function(db, doc, username)
    - {
    - loginUser(username);
    - try {
    - return db.save(doc);
    - } catch (ex) {
    - return ex;
    - } finally {
    - CouchDB.logout();
    - }
    - };
    -
    - var changes_as = function(db, username)
    - {
    - loginUser(username);
    - try {
    - return db.changes();
    - } catch(ex) {
    - return ex;
    - } finally {
    - CouchDB.logout();
    - }
    - };
    -
    - var testFun = function()
    - {
    -
    - // _users db
    - // a doc with a field 'password' should be hashed to 'derived_key'
    - // with salt and salt stored in 'salt', 'password' is set to null.
    - // Exising 'derived_key' and 'salt' fields are overwritten with new values
    - // when a non-null 'password' field exists.
    - // anonymous should be able to create a user document
    - var userDoc = {
    - _id: "org.couchdb.user:jchris",
    - type: "user",
    - name: "jchris",
    - password: "mp3",
    - roles: []
    +
    + var open_as = function(db, docId, username) {
    + loginUser(username);
    + try {
    + return db.open(docId, {"anti-cache": Math.round(Math.random() * 100000)});
    + } finally {
    + CouchDB.logout();
    + }
    + };
    +
    + var view_as = function(db, viewname, username) {
    + loginUser(username);
    + try {
    + return db.view(viewname);
    + } finally {
    + CouchDB.logout();
    + }
          };

    - // jan's gonna be admin as he's the first user
    - TEquals(true, usersDb.save(userDoc).ok, "should save document");
    - userDoc = usersDb.open("org.couchdb.user:jchris");
    - TEquals(undefined, userDoc.password, "password field should be null 1");
    - TEquals(40, userDoc.derived_key.length, "derived_key should exist");
    - TEquals(32, userDoc.salt.length, "salt should exist");
    + var save_as = function(db, doc, username)
    + {
    + loginUser(username);
    + try {
    + return db.save(doc);
    + } catch (ex) {
    + return ex;
    + } finally {
    + CouchDB.logout();
    + }
    + };
    +
    + var changes_as = function(db, username)
    + {
    + loginUser(username);
    + try {
    + return db.changes();
    + } catch(ex) {
    + return ex;
    + } finally {
    + CouchDB.logout();
    + }
    + };

    - // create server admin
    - run_on_modified_server([
    + var testFun = function()
    + {
    +
    + // _users db
    + // a doc with a field 'password' should be hashed to 'derived_key'
    + // with salt and salt stored in 'salt', 'password' is set to null.
    + // Exising 'derived_key' and 'salt' fields are overwritten with new values
    + // when a non-null 'password' field exists.
    + // anonymous should be able to create a user document
    + var userDoc = {
    + _id: "org.couchdb.user:jchris",
    + type: "user",
    + name: "jchris",
    + password: "mp3",
    + roles: []
    + };
    +
    + CouchDB.urlPrefix = url;
    + // The users DB may or may not exist at this point depending on whether
    + // the test is being run against the cluster or admin port so use allDocs
    + // to check
    + try {
    + usersDb.allDocs();
    + } catch(e) {
    + usersDb.createDb();
    + }
    + // jan's gonna be admin as he's the first user
    + TEquals(true, usersDb.save(userDoc).ok, "should save document");
    + userDoc = usersDb.open("org.couchdb.user:jchris");
    + TEquals(undefined, userDoc.password, "password field should be null 1");
    + TEquals(40, userDoc.derived_key.length, "derived_key should exist");
    + TEquals(32, userDoc.salt.length, "salt should exist");
    +
    + CouchDB.urlPrefix = '';
    + // create server admin
    + run_on_modified_server([
              {
                section: "couch_httpd_auth",
                key: "iterations",
    @@ -115,205 +126,208 @@ couchTests.users_db_security = function(debug) {
              }
            ], function() {

    - // anonymous should not be able to read an existing user's user document
    - var res = usersDb.open("org.couchdb.user:jchris");
    - TEquals(null, res, "anonymous user doc read should be not found");
    -
    - // anonymous should not be able to read /_users/_changes
    - try {
    - var ch = usersDb.changes();
    - T(false, "anonymous can read _changes");
    - } catch(e) {
    - TEquals("unauthorized", e.error, "anoymous can't read _changes");
    - }
    -
    - // user should be able to read their own document
    - var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris");
    - TEquals("org.couchdb.user:jchris", jchrisDoc._id);
    -
    - // user should not be able to read /_users/_changes
    - var changes = changes_as(usersDb, "jchris");
    - TEquals("unauthorized", changes.error, "user can't read _changes");
    -
    - // new 'password' fields should trigger new hashing routine
    - jchrisDoc.password = "couch";
    -
    - TEquals(true, save_as(usersDb, jchrisDoc, "jchris").ok);
    - wait(100);
    - var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris1");
    -
    - TEquals(undefined, jchrisDoc.password, "password field should be null 2");
    - TEquals(40, jchrisDoc.derived_key.length, "derived_key should exist");
    - TEquals(32, jchrisDoc.salt.length, "salt should exist");
    -
    - TEquals(true, userDoc.salt != jchrisDoc.salt, "should have new salt");
    - TEquals(true, userDoc.derived_key != jchrisDoc.derived_key,
    - "should have new derived_key");
    -
    - // SHA-1 password hashes are upgraded to PBKDF2 on successful
    - // authentication
    - var rnewsonDoc = {
    - _id: "org.couchdb.user:rnewson",
    - type: "user",
    - name: "rnewson",
    - // password: "plaintext_password",
    - password_sha: "e29dc3aeed5abf43185c33e479f8998558c59474",
    - salt: "24f1e0a87c2e374212bda1073107e8ae",
    - roles: []
    - };
    + CouchDB.urlPrefix = url;
    + // anonymous should not be able to read an existing user's user document
    + var res = usersDb.open("org.couchdb.user:jchris");
    + TEquals(null, res, "anonymous user doc read should be not found");
    +
    + // anonymous should not be able to read /_users/_changes
    + try {
    + var ch = usersDb.changes();
    + T(false, "anonymous can read _changes");
    + } catch(e) {
    + TEquals("unauthorized", e.error, "anoymous can't read _changes");
    + }

    - var password_sha = rnewsonDoc.password_sha,
    + // user should be able to read their own document
    + var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris");
    + TEquals("org.couchdb.user:jchris", jchrisDoc._id);
    +
    + // user should not be able to read /_users/_changes
    + var changes = changes_as(usersDb, "jchris");
    + TEquals("unauthorized", changes.error, "user can't read _changes");
    +
    + // new 'password' fields should trigger new hashing routine
    + jchrisDoc.password = "couch";
    +
    + TEquals(true, save_as(usersDb, jchrisDoc, "jchris").ok);
    + wait(5000); // chttpd_auth_cache may not have started listening for changes
    + var jchrisDoc = open_as(usersDb, "org.couchdb.user:jchris", "jchris1");
    +
    + TEquals(undefined, jchrisDoc.password, "password field should be null 2");
    + TEquals(40, jchrisDoc.derived_key.length, "derived_key should exist");
    + TEquals(32, jchrisDoc.salt.length, "salt should exist");
    +
    + TEquals(true, userDoc.salt != jchrisDoc.salt, "should have new salt");
    + TEquals(true, userDoc.derived_key != jchrisDoc.derived_key,
    + "should have new derived_key");
    +
    + // SHA-1 password hashes are upgraded to PBKDF2 on successful
    + // authentication
    + var rnewsonDoc = {
    + _id: "org.couchdb.user:rnewson",
    + type: "user",
    + name: "rnewson",
    + // password: "plaintext_password",
    + password_sha: "e29dc3aeed5abf43185c33e479f8998558c59474",
    + salt: "24f1e0a87c2e374212bda1073107e8ae",
    + roles: []
    + };
    +
    + var password_sha = rnewsonDoc.password_sha,
              salt = rnewsonDoc.salt,
              derived_key,
              iterations;

    - usersDb.save(rnewsonDoc);
    - rnewsonDoc = open_as(usersDb, rnewsonDoc._id, "jan");
    - T(!rnewsonDoc.password_scheme);
    - T(!rnewsonDoc.derived_key);
    - T(!rnewsonDoc.iterations);
    -
    - // check that we don't upgrade when the password is wrong
    - TEquals("unauthorized", CouchDB.login("rnewson", "wrong_password").error);
    - rnewsonDoc = open_as(usersDb, rnewsonDoc._id, "jan");
    - TEquals(salt, rnewsonDoc.salt);
    - TEquals(password_sha, rnewsonDoc.password_sha);
    - T(!rnewsonDoc.password_scheme);
    - T(!rnewsonDoc.derived_key);
    - T(!rnewsonDoc.iterations);
    -
    - TEquals(true, CouchDB.login("rnewson", "plaintext_password").ok);
    - rnewsonDoc = usersDb.open(rnewsonDoc._id);
    - TEquals("pbkdf2", rnewsonDoc.password_scheme);
    - T(rnewsonDoc.salt != salt);
    - T(!rnewsonDoc.password_sha);
    - T(rnewsonDoc.derived_key);
    - T(rnewsonDoc.iterations);
    -
    - salt = rnewsonDoc.salt,
    - derived_key = rnewsonDoc.derived_key,
    - iterations = rnewsonDoc.iterations;
    -
    - // check that authentication is still working
    - // and everything is staying the same now
    - CouchDB.logout();
    - TEquals(true, CouchDB.login("rnewson", "plaintext_password").ok);
    - rnewsonDoc = usersDb.open(rnewsonDoc._id);
    - TEquals("pbkdf2", rnewsonDoc.password_scheme);
    - TEquals(salt, rnewsonDoc.salt);
    - T(!rnewsonDoc.password_sha);
    - TEquals(derived_key, rnewsonDoc.derived_key);
    - TEquals(iterations, rnewsonDoc.iterations);
    -
    - CouchDB.logout();
    -
    - // user should not be able to read another user's user document
    - var fdmananaDoc = {
    - _id: "org.couchdb.user:fdmanana",
    - type: "user",
    - name: "fdmanana",
    - password: "foobar",
    - roles: []
    - };
    -
    - usersDb.save(fdmananaDoc);
    -
    - var fdmananaDocAsReadByjchris =
    - open_as(usersDb, "org.couchdb.user:fdmanana", "jchris1");
    - TEquals(null, fdmananaDocAsReadByjchris,
    - "should not_found opening another user's user doc");
    + usersDb.save(rnewsonDoc);
    + rnewsonDoc = open_as(usersDb, rnewsonDoc._id, "jan");
    + T(!rnewsonDoc.password_scheme);
    + T(!rnewsonDoc.derived_key);
    + T(!rnewsonDoc.iterations);
    +
    + // check that we don't upgrade when the password is wrong
    + TEquals("unauthorized", CouchDB.login("rnewson", "wrong_password").error);
    + rnewsonDoc = open_as(usersDb, rnewsonDoc._id, "jan");
    + TEquals(salt, rnewsonDoc.salt);
    + TEquals(password_sha, rnewsonDoc.password_sha);
    + T(!rnewsonDoc.password_scheme);
    + T(!rnewsonDoc.derived_key);
    + T(!rnewsonDoc.iterations);
    +
    + TEquals(true, CouchDB.login("rnewson", "plaintext_password").ok);
    + rnewsonDoc = usersDb.open(rnewsonDoc._id);
    + TEquals("pbkdf2", rnewsonDoc.password_scheme);
    + T(rnewsonDoc.salt != salt);
    + T(!rnewsonDoc.password_sha);
    + T(rnewsonDoc.derived_key);
    + T(rnewsonDoc.iterations);

    + salt = rnewsonDoc.salt,
    + derived_key = rnewsonDoc.derived_key,
    + iterations = rnewsonDoc.iterations;
    +
    + // check that authentication is still working
    + // and everything is staying the same now
    + CouchDB.logout();
    + wait(5000); // Increased because change seems to take a while to propagate to auth cache
    + TEquals(true, CouchDB.login("rnewson", "plaintext_password").ok);
    + rnewsonDoc = usersDb.open(rnewsonDoc._id);
    + TEquals("pbkdf2", rnewsonDoc.password_scheme);
    + TEquals(salt, rnewsonDoc.salt);
    + T(!rnewsonDoc.password_sha);
    + TEquals(derived_key, rnewsonDoc.derived_key);
    + TEquals(iterations, rnewsonDoc.iterations);
    +
    + CouchDB.logout();
    +
    + // user should not be able to read another user's user document
    + var fdmananaDoc = {
    + _id: "org.couchdb.user:fdmanana",
    + type: "user",
    + name: "fdmanana",
    + password: "foobar",
    + roles: []
    + };
    +
    + usersDb.save(fdmananaDoc);
    +
    + var fdmananaDocAsReadByjchris =
    + open_as(usersDb, "org.couchdb.user:fdmanana", "jchris1");
    + TEquals(null, fdmananaDocAsReadByjchris,
    + "should not_found opening another user's user doc");
    +
    +
    + // save a db admin
    + var benoitcDoc = {
    + _id: "org.couchdb.user:benoitc",
    + type: "user",
    + name: "benoitc",
    + password: "test",
    + roles: ["user_admin"]
    + };
    + save_as(usersDb, benoitcDoc, "jan");
    +
    + TEquals(true, CouchDB.login("jan", "apple").ok);
    + T(usersDb.setSecObj({
    + "admins" : {
    + roles : [],
    + names : ["benoitc"]
    + }
    + }).ok);
    + CouchDB.logout();
    +
    + // user should not be able to read from any view
    + var ddoc = {
    + _id: "_design/user_db_auth",
    + views: {
    + test: {
    + map: "function(doc) { emit(doc._id, null); }"
    + }
    + }
    + };

    - // save a db admin
    - var benoitcDoc = {
    - _id: "org.couchdb.user:benoitc",
    - type: "user",
    - name: "benoitc",
    - password: "test",
    - roles: ["user_admin"]
    - };
    - save_as(usersDb, benoitcDoc, "jan");
    + save_as(usersDb, ddoc, "jan");

    - TEquals(true, CouchDB.login("jan", "apple").ok);
    - T(usersDb.setSecObj({
    - "admins" : {
    - roles : [],
    - names : ["benoitc"]
    + try {
    + usersDb.view("user_db_auth/test");
    + T(false, "user had access to view in admin db");
    + } catch(e) {
    + TEquals("forbidden", e.error,
    + "non-admins should not be able to read a view");
              }
    - }).ok);
    - CouchDB.logout();
    -
    - // user should not be able to read from any view
    - var ddoc = {
    - _id: "_design/user_db_auth",
    - views: {
    - test: {
    - map: "function(doc) { emit(doc._id, null); }"
    - }
    - }
    - };

    - save_as(usersDb, ddoc, "jan");
    + // admin should be able to read from any view
    + var result = view_as(usersDb, "user_db_auth/test", "jan");
    + TEquals(4, result.total_rows, "should allow access and list four users to admin");

    - try {
    - usersDb.view("user_db_auth/test");
    - T(false, "user had access to view in admin db");
    - } catch(e) {
    - TEquals("forbidden", e.error,
    - "non-admins should not be able to read a view");
    - }
    + // db admin should be able to read from any view
    + var result = view_as(usersDb, "user_db_auth/test", "benoitc");
    + TEquals(4, result.total_rows, "should allow access and list four users to db admin");

    - // admin should be able to read from any view
    - var result = view_as(usersDb, "user_db_auth/test", "jan");
    - TEquals(4, result.total_rows, "should allow access and list four users to admin");

    - // db admin should be able to read from any view
    - var result = view_as(usersDb, "user_db_auth/test", "benoitc");
    - TEquals(4, result.total_rows, "should allow access and list four users to db admin");
    + // non-admins can't read design docs
    + try {
    + open_as(usersDb, "_design/user_db_auth", "jchris1");
    + T(false, "non-admin read design doc, should not happen");
    + } catch(e) {
    + TEquals("forbidden", e.error, "non-admins can't read design docs");
    + }

    + // admin should be able to read and edit any user doc
    + fdmananaDoc.password = "mobile";

    - // non-admins can't read design docs
    - try {
    - open_as(usersDb, "_design/user_db_auth", "jchris1");
    - T(false, "non-admin read design doc, should not happen");
    - } catch(e) {
    - TEquals("forbidden", e.error, "non-admins can't read design docs");
    - }
    + var result = save_as(usersDb, fdmananaDoc, "jan");
    + TEquals(true, result.ok, "admin should be able to update any user doc");

    - // admin should be able to read and edit any user doc
    - fdmananaDoc.password = "mobile";
    - var result = save_as(usersDb, fdmananaDoc, "jan");
    - TEquals(true, result.ok, "admin should be able to update any user doc");
    -
    - // admin should be able to read and edit any user doc
    - fdmananaDoc.password = "mobile1";
    - var result = save_as(usersDb, fdmananaDoc, "benoitc");
    - TEquals(true, result.ok, "db admin by role should be able to update any user doc");
    -
    - TEquals(true, CouchDB.login("jan", "apple").ok);
    - T(usersDb.setSecObj({
    - "admins" : {
    - roles : ["user_admin"],
    - names : []
    - }
    - }).ok);
    - CouchDB.logout();
    + // admin should be able to read and edit any user doc
    + fdmananaDoc.password = "mobile1";
    + var result = save_as(usersDb, fdmananaDoc, "benoitc");
    + TEquals(true, result.ok, "db admin by role should be able to update any user doc");

    - // db admin should be able to read and edit any user doc
    - fdmananaDoc.password = "mobile2";
    - var result = save_as(usersDb, fdmananaDoc, "benoitc");
    - TEquals(true, result.ok, "db admin should be able to update any user doc");
    + TEquals(true, CouchDB.login("jan", "apple").ok);
    + T(usersDb.setSecObj({
    + "admins" : {
    + roles : ["user_admin"],
    + names : []
    + }
    + }).ok);
    + CouchDB.logout();

    - // ensure creation of old-style docs still works
    - var robertDoc = CouchDB.prepareUserDoc({ name: "robert" }, "anchovy");
    - var result = usersDb.save(robertDoc);
    - TEquals(true, result.ok, "old-style user docs should still be accepted");
    + // db admin should be able to read and edit any user doc
    + fdmananaDoc.password = "mobile2";
    + var result = save_as(usersDb, fdmananaDoc, "benoitc");
    + TEquals(true, result.ok, "db admin should be able to update any user doc");

    - // log in one last time so run_on_modified_server can clean up the admin account
    - TEquals(true, CouchDB.login("jan", "apple").ok);
    - });
    + // ensure creation of old-style docs still works
    + var robertDoc = CouchDB.prepareUserDoc({ name: "robert" }, "anchovy");
    + var result = usersDb.save(robertDoc);
    + TEquals(true, result.ok, "old-style user docs should still be accepted");

    - run_on_modified_server([
    + // log in one last time so run_on_modified_server can clean up the admin account
    + TEquals(true, CouchDB.login("jan", "apple").ok);
    + });
    +
    + run_on_modified_server([
              {
                section: "couch_httpd_auth",
                key: "iterations",
    @@ -330,6 +344,21 @@ couchTests.users_db_security = function(debug) {
                value: "true"
              },
              {
    + section: "chttpd_auth",
    + key: "iterations",
    + value: "1"
    + },
    + {
    + section: "chttpd_auth",
    + key: "public_fields",
    + value: "name,type"
    + },
    + {
    + section: "chttpd_auth",
    + key: "users_db_public",
    + value: "true"
    + },
    + {
                section: "admins",
                key: "jan",
                value: "apple"
    @@ -363,61 +392,83 @@ couchTests.users_db_security = function(debug) {
                  }
                }));
              }
    - // log in one last time so run_on_modified_server can clean up the admin account
    - TEquals(true, CouchDB.login("jan", "apple").ok);
    - });
    -
    - run_on_modified_server([
    - {
    - section: "couch_httpd_auth",
    - key: "iterations",
    - value: "1"
    - },
    - {
    - section: "couch_httpd_auth",
    - key: "public_fields",
    - value: "name"
    - },
    - {
    - section: "couch_httpd_auth",
    - key: "users_db_public",
    - value: "false"
    - },
    - {
    - section: "admins",
    - key: "jan",
    - value: "apple"
    - }
    - ], function() {
    - TEquals(true, CouchDB.login("jchris", "couch").ok);
    + // log in one last time so run_on_modified_server can clean up the admin account
    + TEquals(true, CouchDB.login("jan", "apple").ok);
    + });

    - try {
    - var all = usersDb.allDocs({ include_docs: true });
    - T(false); // should never hit
    - } catch(e) {
    - TEquals("forbidden", e.error, "should throw");
    - }
    + run_on_modified_server([
    + {
    + section: "couch_httpd_auth",
    + key: "iterations",
    + value: "1"
    + },
    + {
    + section: "couch_httpd_auth",
    + key: "public_fields",
    + value: "name"
    + },
    + {
    + section: "couch_httpd_auth",
    + key: "users_db_public",
    + value: "false"
    + },
    + {
    + section: "chttpd_auth",
    + key: "iterations",
    + value: "1"
    + },
    + {
    + section: "chttpd_auth",
    + key: "public_fields",
    + value: "name"
    + },
    + {
    + section: "chttpd_auth",
    + key: "users_db_public",
    + value: "false"
    + },
    + {
    + section: "admins",
    + key: "jan",
    + value: "apple"
    + }
    + ], function() {
    + TEquals(true, CouchDB.login("jchris", "couch").ok);

    - // COUCHDB-1888 make sure admins always get all fields
    - TEquals(true, CouchDB.login("jan", "apple").ok);
    - var all_admin = usersDb.allDocs({ include_docs: "true" });
    - TEquals("user", all_admin.rows[2].doc.type,
    - "should return type");
    + try {
    + var all = usersDb.allDocs({ include_docs: true });
    + T(false); // should never hit
    + } catch(e) {
    + TEquals("forbidden", e.error, "should throw");
    + }

    + // COUCHDB-1888 make sure admins always get all fields
    + TEquals(true, CouchDB.login("jan", "apple").ok);
    + var all_admin = usersDb.allDocs({ include_docs: "true" });
    + TEquals("user", all_admin.rows[2].doc.type,
    + "should return type");

    - // log in one last time so run_on_modified_server can clean up the admin account
    - TEquals(true, CouchDB.login("jan", "apple").ok);
    - });
    - };

    - usersDb.deleteDb();
    - run_on_modified_server(
    - [{section: "couch_httpd_auth",
    - key: "iterations", value: "1"},
    - {section: "couch_httpd_auth",
    - key: "authentication_db", value: usersDb.name}],
    - testFun
    - );
    - usersDb.deleteDb(); // cleanup
    + // log in one last time so run_on_modified_server can clean up the admin account
    + TEquals(true, CouchDB.login("jan", "apple").ok);
    + });
    + };
    +
    + usersDb.deleteDb();
    + run_on_modified_server(
    + [{section: "couch_httpd_auth",
    + key: "iterations", value: "1"},
    + {section: "couch_httpd_auth",
    + key: "authentication_db", value: usersDb.name},
    + {section: "chttpd_auth",
    + key: "authentication_db", value: usersDb.name}],
    + testFun
    + );
    + usersDb.deleteDb(); // cleanup
    + }

    + // Run the test suite against the admin port
    + run_test_against_url("http://127.0.0.1:15986");
    + // Run the test suite against the cluster port
    + run_test_against_url("http://127.0.0.1:15984");
      };

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcommits @
categoriescouchdb
postedDec 4, '14 at 10:52a
activeDec 4, '14 at 10:52a
posts3
users1
websitecouchdb.apache.org
irc#couchdb

1 user in discussion

Mikewallace: 3 posts

People

Translate

site design / logo © 2021 Grokbase