From f8a22d0ac03f5ef3d1d17b5fbd3dd3e0a311aa75 Mon Sep 17 00:00:00 2001 From: Esa Korhonen Date: Mon, 8 Apr 2019 17:56:18 +0300 Subject: [PATCH] MXS-2344 Add setting for enabling SSL for replication If the monitor setting "replication_master_ssl" is set to on, any CHANGE MASTER TO-command will have MASTER_SSL=1. If set to off or unset, MASTER_SSL is left unchanged to match existing behaviour. --- Documentation/Monitors/MariaDB-Monitor.md | 15 ++++++++++++++- .../monitor/mariadbmon/cluster_manipulation.cc | 13 ++++++++++--- server/modules/monitor/mariadbmon/mariadbmon.cc | 8 +++++--- server/modules/monitor/mariadbmon/mariadbmon.hh | 1 + .../modules/monitor/mariadbmon/mariadbserver.cc | 4 ++++ server/modules/monitor/mariadbmon/server_utils.cc | 5 +++-- server/modules/monitor/mariadbmon/server_utils.hh | 3 ++- 7 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Documentation/Monitors/MariaDB-Monitor.md b/Documentation/Monitors/MariaDB-Monitor.md index 58a508196..fb541dd50 100644 --- a/Documentation/Monitors/MariaDB-Monitor.md +++ b/Documentation/Monitors/MariaDB-Monitor.md @@ -651,7 +651,7 @@ executed. Both `replication_user` and `replication_password` parameters must be defined if a custom replication user is used. If neither of the parameters is defined, the -`CHANGE MASTER TO` command will use the monitor credentials for the replication +`CHANGE MASTER TO`-command will use the monitor credentials for the replication user. The credentials used for replication must have the `REPLICATION SLAVE` @@ -661,6 +661,19 @@ privilege. parameters. If password encryption is in use, `replication_password` must be encrypted with the same key to avoid erroneous decryption. +#### `replication_master_ssl` + +Type: bool Default: off + +If set to ON, any `CHANGE MASTER TO`-command generated will set `MASTER_SSL=1` to enable +encryption for the replication stream. This setting should only be enabled if the backend +servers are configured for ssl. This typically means setting *ssl_ca*, *ssl_cert* and +*ssl_key* in the server configuration file. Additionally, credentials for the replication +user should require an encrypted connection (`e.g. ALTER USER repl@'%' REQUIRE SSL;`). + +If the setting is left OFF, `MASTER_SSL` is not set at all, which will preserve existing +settings when redirecting a slave connection. + #### `failover_timeout` and `switchover_timeout` Time limit for failover and switchover operations, in seconds. The default diff --git a/server/modules/monitor/mariadbmon/cluster_manipulation.cc b/server/modules/monitor/mariadbmon/cluster_manipulation.cc index 3db3dcd96..ec408f26d 100644 --- a/server/modules/monitor/mariadbmon/cluster_manipulation.cc +++ b/server/modules/monitor/mariadbmon/cluster_manipulation.cc @@ -411,6 +411,10 @@ string MariaDBMonitor::generate_change_master_cmd(const string& master_host, int change_cmd << "CHANGE MASTER TO MASTER_HOST = '" << master_host << "', "; change_cmd << "MASTER_PORT = " << master_port << ", "; change_cmd << "MASTER_USE_GTID = current_pos, "; + if (m_replication_ssl) + { + change_cmd << "MASTER_SSL = 1, "; + } change_cmd << "MASTER_USER = '" << m_replication_user << "', "; const char MASTER_PW[] = "MASTER_PASSWORD = '"; const char END[] = "';"; @@ -630,7 +634,8 @@ uint32_t MariaDBMonitor::do_rejoin(const ServerArray& joinable_servers, json_t** // Rejoin doesn't have its own time limit setting. Use switchover time limit for now since // the first phase of standalone rejoin is similar to switchover. maxbase::Duration time_limit((double)m_switchover_timeout); - GeneralOpData general(m_replication_user, m_replication_password, output, time_limit); + GeneralOpData general(m_replication_user, m_replication_password, m_replication_ssl, + output, time_limit); if (joinable->m_slave_status.empty()) { @@ -1410,7 +1415,8 @@ unique_ptr MariaDBMonitor::failover_prepare(Log ServerOperation promotion(promotion_target, promoting_to_master, m_handle_event_scheduler, m_promote_sql_file, demotion_target->m_slave_status, demotion_target->m_enabled_events); - GeneralOpData general(m_replication_user, m_replication_password, error_out, time_limit); + GeneralOpData general(m_replication_user, m_replication_password, m_replication_ssl, + error_out, time_limit); rval.reset(new FailoverParams(promotion, demotion_target, general)); } } @@ -1703,7 +1709,8 @@ MariaDBMonitor::switchover_prepare(SERVER* promotion_server, SERVER* demotion_se ServerOperation demotion(demotion_target, master_swap, m_handle_event_scheduler, m_demote_sql_file, promotion_target->m_slave_status, EventNameSet() /* unused */); - GeneralOpData general(m_replication_user, m_replication_password, error_out, time_limit); + GeneralOpData general(m_replication_user, m_replication_password, m_replication_ssl, + error_out, time_limit); rval.reset(new SwitchoverParams(promotion, demotion, general)); } return rval; diff --git a/server/modules/monitor/mariadbmon/mariadbmon.cc b/server/modules/monitor/mariadbmon/mariadbmon.cc index d458e0fa7..39ef39b53 100644 --- a/server/modules/monitor/mariadbmon/mariadbmon.cc +++ b/server/modules/monitor/mariadbmon/mariadbmon.cc @@ -54,9 +54,7 @@ static const char CN_MASTER_FAILURE_TIMEOUT[] = "master_failure_timeout"; // Replication credentials parameters for failover/switchover/join static const char CN_REPLICATION_USER[] = "replication_user"; static const char CN_REPLICATION_PASSWORD[] = "replication_password"; - -static const char DIAG_ERROR[] = "Internal error, could not print diagnostics. " - "Check log for more information."; +static const char CN_REPLICATION_MASTER_SSL[] = "replication_master_ssl"; MariaDBMonitor::MariaDBMonitor(MXS_MONITOR* monitor) : maxscale::MonitorInstance(monitor) @@ -227,6 +225,7 @@ bool MariaDBMonitor::configure(const MXS_CONFIG_PARAMETER* params) m_switchover_on_low_disk_space = config_get_bool(params, CN_SWITCHOVER_ON_LOW_DISK_SPACE); m_maintenance_on_low_disk_space = config_get_bool(params, CN_MAINTENANCE_ON_LOW_DISK_SPACE); m_handle_event_scheduler = config_get_bool(params, CN_HANDLE_EVENTS); + m_replication_ssl = config_get_bool(params, CN_REPLICATION_MASTER_SSL); /* Reset all monitored state info. The server dependent values must be reset as servers could have been * added, removed and modified. */ @@ -1067,6 +1066,9 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE() { CN_REPLICATION_PASSWORD, MXS_MODULE_PARAM_STRING }, + { + CN_REPLICATION_MASTER_SSL, MXS_MODULE_PARAM_BOOL, "false" + }, { CN_VERIFY_MASTER_FAILURE, MXS_MODULE_PARAM_BOOL, "true" }, diff --git a/server/modules/monitor/mariadbmon/mariadbmon.hh b/server/modules/monitor/mariadbmon/mariadbmon.hh index 8a40356ce..481c02494 100644 --- a/server/modules/monitor/mariadbmon/mariadbmon.hh +++ b/server/modules/monitor/mariadbmon/mariadbmon.hh @@ -212,6 +212,7 @@ private: // Cluster operations additional settings std::string m_replication_user; /* Replication user for CHANGE MASTER TO-commands */ std::string m_replication_password; /* Replication password for CHANGE MASTER TO-commands */ + bool m_replication_ssl = false; /* Set MASTER_SSL = 1 in CHANGE MASTER TO-commands */ bool m_handle_event_scheduler = true;/* Should failover/switchover enable/disable any scheduled * events on the servers during promote/demote? */ uint32_t m_failover_timeout = 10; /* Time limit in seconds for failover */ diff --git a/server/modules/monitor/mariadbmon/mariadbserver.cc b/server/modules/monitor/mariadbmon/mariadbserver.cc index 83fae9708..297746bbc 100644 --- a/server/modules/monitor/mariadbmon/mariadbserver.cc +++ b/server/modules/monitor/mariadbmon/mariadbserver.cc @@ -2064,6 +2064,10 @@ string MariaDBServer::generate_change_master_cmd(GeneralOpData& op, const SlaveS slave_conn.name.c_str(), slave_conn.master_host.c_str(), slave_conn.master_port); change_cmd += "MASTER_USE_GTID = current_pos, "; + if (op.replication_ssl) + { + change_cmd += "MASTER_SSL = 1, "; + } change_cmd += string_printf("MASTER_USER = '%s', ", op.replication_user.c_str()); const char MASTER_PW[] = "MASTER_PASSWORD = '%s';"; #if defined (SS_DEBUG) diff --git a/server/modules/monitor/mariadbmon/server_utils.cc b/server/modules/monitor/mariadbmon/server_utils.cc index d48533704..22d7349a5 100644 --- a/server/modules/monitor/mariadbmon/server_utils.cc +++ b/server/modules/monitor/mariadbmon/server_utils.cc @@ -174,10 +174,11 @@ ServerOperation::ServerOperation(MariaDBServer* target, bool was_is_master, bool { } -GeneralOpData::GeneralOpData(const string& replication_user, const string& replication_password, - json_t** error, maxbase::Duration time_remaining) +GeneralOpData::GeneralOpData(const std::string& replication_user, const std::string& replication_password, + bool replication_ssl, json_t** error, maxbase::Duration time_remaining) : replication_user(replication_user) , replication_password(replication_password) + , replication_ssl(replication_ssl) , error_out(error) , time_remaining(time_remaining) { diff --git a/server/modules/monitor/mariadbmon/server_utils.hh b/server/modules/monitor/mariadbmon/server_utils.hh index 3f3c4b39c..0aa37e1e9 100644 --- a/server/modules/monitor/mariadbmon/server_utils.hh +++ b/server/modules/monitor/mariadbmon/server_utils.hh @@ -224,11 +224,12 @@ class GeneralOpData public: const std::string replication_user; // User for CHANGE MASTER TO ... const std::string replication_password; // Password for CHANGE MASTER TO ... + const bool replication_ssl; // MASTER_SSL=1 in CHANGE MASTER TO ... json_t** const error_out; // Json error output maxbase::Duration time_remaining; // How much time remains to complete the operation GeneralOpData(const std::string& replication_user, const std::string& replication_password, - json_t** error, maxbase::Duration time_remaining); + bool replication_ssl, json_t** error, maxbase::Duration time_remaining); }; // Operation data which concerns a single server