From cda952f1e46ac18d724cc897c64cccc63b765d0c Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Thu, 12 Apr 2018 15:03:46 +0900 Subject: [PATCH] Add "dbname=replication" to all replication connection strings Previously repmgr was attempting to make replication connections with "dbname" set to the repmgr database name. While this works if e.g. the repmgr user also has replication permissions, it will fail if a dedicated replication user is specified, who only has permission to access the virtual "replication" database. Change this to use "dbname=replication" if the replication connection user is different to the normal repmgr database user. (We could just always set it to "replication", but that might break existing installations e.g. where a .pgpass file is in use and there's no "replication" entry for the normal repmgr database user). Addresses GitHub #421. --- repmgr-action-node.c | 7 ++++++- repmgr-action-standby.c | 25 +++++++++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/repmgr-action-node.c b/repmgr-action-node.c index 6bf93a5e..d9fd1e92 100644 --- a/repmgr-action-node.c +++ b/repmgr-action-node.c @@ -940,6 +940,7 @@ do_node_check_replication_connection(void) return; } + /* retrieve remote node record from local database */ local_conn = establish_db_connection(config_file_options.conninfo, true); record_status = get_node_record(local_conn, runtime_options.remote_node_id, &node_record); @@ -956,8 +957,12 @@ do_node_check_replication_connection(void) initialize_conninfo_params(&remote_conninfo, false); parse_conninfo_string(node_record.conninfo, &remote_conninfo, NULL, false); + if (strcmp(param_get(&remote_conninfo, "user"), node_record.repluser) != 0) + { + param_set(&remote_conninfo, "user", node_record.repluser); + param_set(&remote_conninfo, "dbname", "replication"); + } param_set(&remote_conninfo, "replication", "1"); - param_set(&remote_conninfo, "user", node_record.repluser); repl_conn = establish_db_connection_by_params(&remote_conninfo, false); diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c index b2e166bb..a1bbc1c9 100644 --- a/repmgr-action-standby.c +++ b/repmgr-action-standby.c @@ -60,6 +60,7 @@ static char upstream_data_directory[MAXPGPATH]; static t_conninfo_param_list recovery_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER; static char recovery_conninfo_str[MAXLEN] = ""; static char upstream_repluser[NAMEDATALEN] = ""; +static char upstream_user[NAMEDATALEN] = ""; static int source_server_version_num = UNKNOWN_SERVER_VERSION_NUM; @@ -282,7 +283,7 @@ do_standby_clone(void) { /* * This connects to the source node and performs sanity checks, also - * sets "recovery_conninfo_str", "upstream_repluser" and + * sets "recovery_conninfo_str", "upstream_repluser", "upstream_user" and * "upstream_node_id". * * Will error out if source connection not possible and not in @@ -2245,8 +2246,12 @@ do_standby_follow(void) conn_to_param_list(primary_conn, &repl_conninfo); + if (strcmp(param_get(&repl_conninfo, "user"), primary_node_record.repluser) != 0) + { + param_set(&repl_conninfo, "user", primary_node_record.repluser); + param_set(&repl_conninfo, "dbname", "replication"); + } param_set(&repl_conninfo, "replication", "1"); - param_set(&repl_conninfo, "user", primary_node_record.repluser); repl_conn = establish_db_connection_by_params(&repl_conninfo, false); if (PQstatus(repl_conn) != CONNECTION_OK) @@ -2997,7 +3002,7 @@ do_standby_switchover(void) exit(ERR_BAD_CONFIG); break; default: - log_error(_("unable to deterimine whether candidate is able to make replication connection to promotion candidate")); + log_error(_("unable to determine whether demotion candidate is able to make replication connection to promotion candidate")); exit(ERR_BAD_CONFIG); break; } @@ -4066,9 +4071,16 @@ check_source_server() record_status = get_node_record(source_conn, upstream_node_id, &node_record); if (record_status == RECORD_FOUND) { - upstream_conninfo_found = true; + t_conninfo_param_list upstream_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER; + + initialize_conninfo_params(&upstream_conninfo, false); + parse_conninfo_string(node_record.conninfo, &upstream_conninfo, NULL, false); + strncpy(recovery_conninfo_str, node_record.conninfo, MAXLEN); strncpy(upstream_repluser, node_record.repluser, NAMEDATALEN); + strncpy(upstream_user, param_get(&upstream_conninfo, "user"), NAMEDATALEN); + + upstream_conninfo_found = true; } /* @@ -4500,6 +4512,11 @@ check_upstream_config(PGconn *conn, int server_version_num, t_node_info *node_in param_set(&repl_conninfo, "user", node_info->repluser); } + if (strcmp(param_get(&repl_conninfo, "user"), upstream_user) != 0) + { + param_set(&repl_conninfo, "dbname", "replication"); + } + /* * work out how many replication connections are required (1 or 2) */