From a6c1988c5db4993487ea627cc6009e1f5d51d367 Mon Sep 17 00:00:00 2001 From: Jay Doane Date: Tue, 12 Feb 2019 11:27:13 -0800 Subject: [PATCH] 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 3ae455f5460..9437fbc073b 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) ->