You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2019/02/12 22:57:42 UTC

[couchdb] branch master updated: Sync admin password hashes at cluster setup finish

This is an automated email from the ASF dual-hosted git repository.

jaydoane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/master by this push:
     new a6c1988  Sync admin password hashes at cluster setup finish
     new e699fe6  Merge pull request #1803 from cloudant/configurable-auth-salt
a6c1988 is described below

commit a6c1988c5db4993487ea627cc6009e1f5d51d367
Author: Jay Doane <ja...@apache.org>
AuthorDate: Tue Feb 12 11:27:13 2019 -0800

    Sync admin password hashes at cluster setup finish
    
    This ensures that admin password hashes are the same on all nodes when
    passwords are set directly on each node rather than through the
    coordinator node.
---
 src/setup/src/setup.erl | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/src/setup/src/setup.erl b/src/setup/src/setup.erl
index 3ae455f..9437fbc 100644
--- a/src/setup/src/setup.erl
+++ b/src/setup/src/setup.erl
@@ -198,9 +198,75 @@ setup_node(NewCredentials, NewBindAddress, NodeCount, Port) ->
 
 
 finish_cluster(Options) ->
+    ok = wait_connected(),
+    ok = sync_admins(),
     Dbs = proplists:get_value(ensure_dbs_exist, Options, cluster_system_dbs()),
     finish_cluster_int(Dbs, has_cluster_system_dbs(Dbs)).
 
+
+wait_connected() ->
+    Nodes = other_nodes(),
+    Result = test_util:wait(fun() ->
+        case disconnected(Nodes) of
+            [] -> ok;
+            _ -> wait
+        end
+    end),
+    case Result of
+        timeout ->
+            Reason = "Cluster setup timed out waiting for nodes to connect",
+            throw({setup_error, Reason});
+        ok ->
+            ok
+    end.
+
+
+other_nodes() ->
+    mem3:nodes() -- [node()].
+
+
+disconnected(Nodes) ->
+    lists:filter(fun(Node) ->
+        case net_adm:ping(Node) of
+            pong -> false;
+            pang -> true
+        end
+    end, Nodes).
+
+
+sync_admins() ->
+    ok = lists:foreach(fun({User, Pass}) ->
+        sync_admin(User, Pass)
+    end, config:get("admins")).
+
+
+sync_admin(User, Pass) ->
+    {Results, Errors} = rpc:multicall(other_nodes(), config, set,
+        ["admins", User, Pass]),
+    case validate_multicall(Results, Errors) of
+        ok ->
+            ok;
+        error ->
+            log:error("~p sync_admin results ~p errors ~p",
+                [?MODULE, Results, Errors]),
+            Reason = "Cluster setup unable to sync admin passwords",
+            throw({setup_error, Reason})
+    end.
+
+
+validate_multicall(Results, Errors) ->
+    AllOk = lists:all(fun
+        (ok) -> true;
+        (_) -> false
+    end, Results),
+    case AllOk andalso Errors == [] of
+        true ->
+            ok;
+        false ->
+            error
+    end.
+
+
 finish_cluster_int(_Dbs, true) ->
     {error, cluster_finished};
 finish_cluster_int(Dbs, false) ->