diff options
author | Jay Doane <jaydoane@apache.org> | 2019-02-12 11:27:13 -0800 |
---|---|---|
committer | Jay Doane <jaydoane@apache.org> | 2019-02-12 11:27:13 -0800 |
commit | a6c1988c5db4993487ea627cc6009e1f5d51d367 (patch) | |
tree | 90a781dfbbd15c19ca1828637babbd23eb69c4fa | |
parent | b46df8c8d3c96eadb07d540b82fcb992e6da2a82 (diff) | |
download | couchdb-a6c1988c5db4993487ea627cc6009e1f5d51d367.tar.gz |
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.
-rw-r--r-- | src/setup/src/setup.erl | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/setup/src/setup.erl b/src/setup/src/setup.erl index 3ae455f54..9437fbc07 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) -> |