From 9a7c3e819666b19adc4b6f31395b11d5e385d73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sun, 18 Feb 2024 12:25:30 +0000 Subject: [PATCH 1/8] Introducing mysql_servers_ssl_params First commit to introduce table mysql_servers_ssl_params . This allows to configure per host SSL parameters. --- include/MySQL_HostGroups_Manager.h | 71 +++++++++++++++++++++++ include/ProxySQL_Cluster.hpp | 5 ++ include/proxysql_admin.h | 3 +- lib/MySQL_HostGroups_Manager.cpp | 86 ++++++++++++++++++++++++++++ lib/ProxySQL_Admin.cpp | 92 +++++++++++++++++++++++++++++- lib/ProxySQL_Cluster.cpp | 72 ++++++++++++++++++++++- lib/mysql_connection.cpp | 30 +++++++--- 7 files changed, 348 insertions(+), 11 deletions(-) diff --git a/include/MySQL_HostGroups_Manager.h b/include/MySQL_HostGroups_Manager.h index 83abc5c05a..8dbf907cb3 100644 --- a/include/MySQL_HostGroups_Manager.h +++ b/include/MySQL_HostGroups_Manager.h @@ -376,6 +376,68 @@ class AWS_Aurora_Info { ~AWS_Aurora_Info(); }; +class MySQLServers_SslParams { + public: + string hostname; + int port; + string username; + string ssl_ca; + string ssl_cert; + string ssl_key; + string ssl_capath; + string ssl_crl; + string ssl_crlpath; + string ssl_cipher; + string tls_version; + string comment; + string MapKey; + MySQLServers_SslParams(string _h, int _p, string _u, + string ca, string cert, string key, string capath, + string crl, string crlpath, string cipher, string tls, + string c) { + hostname = _h; + port = _p; + username = _u; + ssl_ca = ca; + ssl_cert = cert; + ssl_key = key; + ssl_capath = capath; + ssl_crl = crl; + ssl_crlpath = crlpath; + ssl_cipher = cipher; + tls_version = tls; + comment = c; + MapKey = ""; + } + MySQLServers_SslParams(char * _h, int _p, char * _u, + char * ca, char * cert, char * key, char * capath, + char * crl, char * crlpath, char * cipher, char * tls, + char * c) { + hostname = string(_h); + port = _p; + username = string(_u); + ssl_ca = string(ca); + ssl_cert = string(cert); + ssl_key = string(key); + ssl_capath = string(capath); + ssl_crl = string(crl); + ssl_crlpath = string(crlpath); + ssl_cipher = string(cipher); + tls_version = string(tls); + comment = string(c); + MapKey = ""; + } + MySQLServers_SslParams(string _h, int _p, string _u) { + MySQLServers_SslParams(_h, _p, _u, "", "", "", "", "", "", "", "", ""); + } + string getMapKey(const char *del) { + if (MapKey == "") { + MapKey = hostname + string(del) + to_string(port) + string(del) + username; + } + return MapKey; + } +}; + struct p_hg_counter { enum metric { servers_table_version = 0, @@ -527,6 +589,7 @@ class MySQL_HostGroups_Manager { MYSQL_GALERA_HOSTGROUPS, MYSQL_AWS_AURORA_HOSTGROUPS, MYSQL_HOSTGROUP_ATTRIBUTES, + MYSQL_SERVERS_SSL_PARAMS, MYSQL_SERVERS, __HGM_TABLES_SIZE @@ -636,6 +699,9 @@ class MySQL_HostGroups_Manager { PtrArray *MyHostGroups; std::unordered_mapMyHostGroups_map; + std::mutex Servers_SSL_Params_map_mutex; + std::unordered_map Servers_SSL_Params_map; + MyHGC * MyHGC_find(unsigned int); MyHGC * MyHGC_create(unsigned int); @@ -710,6 +776,9 @@ class MySQL_HostGroups_Manager { void generate_mysql_hostgroup_attributes_table(); SQLite3_result *incoming_hostgroup_attributes; + void generate_mysql_servers_ssl_params_table(); + SQLite3_result *incoming_mysql_servers_ssl_params; + SQLite3_result* incoming_mysql_servers_v2; std::thread *HGCU_thread; @@ -1115,6 +1184,8 @@ class MySQL_HostGroups_Manager { void unshun_server_all_hostgroups(const char * address, uint16_t port, time_t t, int max_wait_sec, unsigned int *skip_hid); MySrvC* find_server_in_hg(unsigned int _hid, const std::string& addr, int port); + MySQLServers_SslParams * get_Server_SSL_Params(char *hostname, int port, char *username); + private: void update_hostgroup_manager_mappings(); uint64_t get_mysql_servers_checksum(SQLite3_result* runtime_mysql_servers = nullptr); diff --git a/include/ProxySQL_Cluster.hpp b/include/ProxySQL_Cluster.hpp index 75e2eed0e5..7d725da1be 100644 --- a/include/ProxySQL_Cluster.hpp +++ b/include/ProxySQL_Cluster.hpp @@ -43,6 +43,9 @@ /* @brief Query to be intercepted by 'ProxySQL_Admin' for 'runtime_mysql_hostgroup_attributes'. See top comment for details. */ #define CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES "PROXY_SELECT hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, hostgroup_settings, servers_defaults, comment FROM runtime_mysql_hostgroup_attributes ORDER BY hostgroup_id" +/* @brief Query to be intercepted by 'ProxySQL_Admin' for 'runtime_mysql_servers_ssl_params'. See top comment for details. */ +#define CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS "PROXY_SELECT hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment FROM runtime_mysql_servers_ssl_params ORDER BY hostname, port, username" + /* @brief Query to be intercepted by 'ProxySQL_Admin' for 'runtime_mysql_aws_aurora_hostgroups'. See top comment for details. */ #define CLUSTER_QUERY_MYSQL_AWS_AURORA "PROXY_SELECT writer_hostgroup, reader_hostgroup, active, aurora_port, domain_name, max_lag_ms, check_interval_ms, check_timeout_ms, writer_is_also_reader, new_reader_weight, add_lag_ms, min_lag_ms, lag_num_checks, comment FROM runtime_mysql_aws_aurora_hostgroups ORDER BY writer_hostgroup" @@ -310,6 +313,8 @@ struct p_cluster_counter { pulled_mysql_servers_aws_aurora_hostgroups_failure, pulled_mysql_servers_hostgroup_attributes_success, pulled_mysql_servers_hostgroup_attributes_failure, + pulled_mysql_servers_ssl_params_success, + pulled_mysql_servers_ssl_params_failure, pulled_mysql_servers_runtime_checks_success, pulled_mysql_servers_runtime_checks_failure, diff --git a/include/proxysql_admin.h b/include/proxysql_admin.h index d1a2741863..da1e5cf4ef 100644 --- a/include/proxysql_admin.h +++ b/include/proxysql_admin.h @@ -144,9 +144,10 @@ struct incoming_servers_t { SQLite3_result* incoming_galera_hostgroups = NULL; SQLite3_result* incoming_aurora_hostgroups = NULL; SQLite3_result* incoming_hostgroup_attributes = NULL; + SQLite3_result* incoming_mysql_servers_ssl_params = NULL; incoming_servers_t(); - incoming_servers_t(SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*); + incoming_servers_t(SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*, SQLite3_result*); }; // Separate structs for runtime mysql server and mysql server v2 to avoid human error diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index e957e0f1dd..d5d4d0b1a2 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -1630,6 +1630,7 @@ void MySQL_HostGroups_Manager::commit_update_checksums_from_tables(SpookyHash& m CUCFT1(myhash,init,"mysql_galera_hostgroups","writer_hostgroup", table_resultset_checksum[HGM_TABLES::MYSQL_GALERA_HOSTGROUPS]); CUCFT1(myhash,init,"mysql_aws_aurora_hostgroups","writer_hostgroup", table_resultset_checksum[HGM_TABLES::MYSQL_AWS_AURORA_HOSTGROUPS]); CUCFT1(myhash,init,"mysql_hostgroup_attributes","hostgroup_id", table_resultset_checksum[HGM_TABLES::MYSQL_HOSTGROUP_ATTRIBUTES]); + CUCFT1(myhash,init,"mysql_servers_ssl_params","hostname,port,username", table_resultset_checksum[HGM_TABLES::MYSQL_SERVERS_SSL_PARAMS]); } /** @@ -2145,6 +2146,13 @@ bool MySQL_HostGroups_Manager::commit( generate_mysql_hostgroup_attributes_table(); } + // SSL params + if (incoming_mysql_servers_ssl_params) { + proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "DELETE FROM mysql_servers_ssl_params\n"); + mydb->execute("DELETE FROM mysql_servers_ssl_params"); + generate_mysql_servers_ssl_params_table(); + } + uint64_t new_hash = commit_update_checksum_from_mysql_servers_v2(peer_mysql_servers_v2.resultset); { @@ -2777,6 +2785,8 @@ SQLite3_result * MySQL_HostGroups_Manager::dump_table_mysql(const string& name) query=(char *)"SELECT writer_hostgroup, reader_hostgroup, check_type, comment FROM mysql_replication_hostgroups"; } else if (name == "mysql_hostgroup_attributes") { query=(char *)"SELECT hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, hostgroup_settings, servers_defaults, comment FROM mysql_hostgroup_attributes ORDER BY hostgroup_id"; + } else if (name == "mysql_servers_ssl_params") { + query=(char *)"SELECT hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment FROM mysql_servers_ssl_params ORDER BY hostname, port, username"; } else if (name == "mysql_servers") { query = (char *)MYHGM_GEN_ADMIN_RUNTIME_SERVERS; } else if (name == "cluster_mysql_servers") { @@ -4056,6 +4066,8 @@ void MySQL_HostGroups_Manager::save_incoming_mysql_table(SQLite3_result *s, cons inc = &incoming_replication_hostgroups; } else if (name == "mysql_hostgroup_attributes") { inc = &incoming_hostgroup_attributes; + } else if (name == "mysql_servers_ssl_params") { + inc = &incoming_mysql_servers_ssl_params; } else { assert(0); } @@ -4093,6 +4105,8 @@ SQLite3_result* MySQL_HostGroups_Manager::get_current_mysql_table(const string& return this->incoming_replication_hostgroups; } else if (name == "mysql_hostgroup_attributes") { return this->incoming_hostgroup_attributes; + } else if (name == "mysql_servers_ssl_params") { + return this->incoming_mysql_servers_ssl_params; } else if (name == "cluster_mysql_servers") { return this->runtime_mysql_servers; } else if (name == "mysql_servers_v2") { @@ -7319,6 +7333,60 @@ void MySQL_HostGroups_Manager::generate_mysql_hostgroup_attributes_table() { incoming_hostgroup_attributes=NULL; } +void MySQL_HostGroups_Manager::generate_mysql_servers_ssl_params_table() { + if (incoming_mysql_servers_ssl_params==NULL) { + return; + } + int rc; + sqlite3_stmt *statement=NULL; + + const char * query = (const char *)"INSERT INTO mysql_servers_ssl_params (" + "hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, " + "ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment) VALUES " + "(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"; + + rc = mydb->prepare_v2(query, &statement); + ASSERT_SQLITE_OK(rc, mydb); + proxy_info("New mysql_servers_ssl_params table\n"); + std::lock_guard lock(Servers_SSL_Params_map_mutex); + Servers_SSL_Params_map.clear(); + + for (std::vector::iterator it = incoming_mysql_servers_ssl_params->rows.begin() ; it != incoming_mysql_servers_ssl_params->rows.end(); ++it) { + SQLite3_row *r=*it; + proxy_info("Loading MySQL Server SSL Params for (%s,%s,%s)\n", + r->fields[0], r->fields[1], r->fields[2] + ); + + rc=(*proxy_sqlite3_bind_text)(statement, 1, r->fields[0] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // hostname + rc=(*proxy_sqlite3_bind_int64)(statement, 2, atoi(r->fields[1])); ASSERT_SQLITE_OK(rc, mydb); // port + rc=(*proxy_sqlite3_bind_text)(statement, 3, r->fields[2] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // username + rc=(*proxy_sqlite3_bind_text)(statement, 4, r->fields[3] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // ssl_ca + rc=(*proxy_sqlite3_bind_text)(statement, 5, r->fields[4] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // ssl_cert + rc=(*proxy_sqlite3_bind_text)(statement, 6, r->fields[5] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // ssl_key + rc=(*proxy_sqlite3_bind_text)(statement, 7, r->fields[6] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // ssl_capath + rc=(*proxy_sqlite3_bind_text)(statement, 8, r->fields[7] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // ssl_crl + rc=(*proxy_sqlite3_bind_text)(statement, 9, r->fields[8] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // ssl_crlpath + rc=(*proxy_sqlite3_bind_text)(statement, 10, r->fields[9] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // ssl_cipher + rc=(*proxy_sqlite3_bind_text)(statement, 11, r->fields[10] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // tls_version + rc=(*proxy_sqlite3_bind_text)(statement, 12, r->fields[11] , -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, mydb); // comment + + SAFE_SQLITE3_STEP2(statement); + rc=(*proxy_sqlite3_clear_bindings)(statement); ASSERT_SQLITE_OK(rc, mydb); + rc=(*proxy_sqlite3_reset)(statement); ASSERT_SQLITE_OK(rc, mydb); + + MySQLServers_SslParams MSSP( + r->fields[0], atoi(r->fields[1]), r->fields[2], + r->fields[3], r->fields[4], r->fields[5], + r->fields[6], r->fields[7], r->fields[8], + r->fields[9], r->fields[10], r->fields[11] + ); + string MapKey = MSSP.getMapKey(rand_del); + Servers_SSL_Params_map.emplace(MapKey, MSSP); + } + delete incoming_mysql_servers_ssl_params; + incoming_mysql_servers_ssl_params=NULL; +} + void MySQL_HostGroups_Manager::generate_mysql_aws_aurora_hostgroups_table() { if (incoming_aws_aurora_hostgroups==NULL) { return; @@ -8164,3 +8232,21 @@ void MySQL_HostGroups_Manager::HostGroup_Server_Mapping::remove_HGM(MySrvC* srv) srv->status = MYSQL_SERVER_STATUS_OFFLINE_HARD; srv->ConnectionsFree->drop_all_connections(); } + +MySQLServers_SslParams * MySQL_HostGroups_Manager::get_Server_SSL_Params(char *hostname, int port, char *username) { + string MapKey = string(hostname) + string(rand_del) + to_string(port) + string(rand_del) + string(username); + std::lock_guard lock(Servers_SSL_Params_map_mutex); + auto it = Servers_SSL_Params_map.find(MapKey); + if (it != Servers_SSL_Params_map.end()) { + MySQLServers_SslParams * MSSP = new MySQLServers_SslParams(it->second); + return MSSP; + } else { + MapKey = string(hostname) + string(rand_del) + to_string(port) + string(rand_del) + ""; // search for empty username + it = Servers_SSL_Params_map.find(MapKey); + if (it != Servers_SSL_Params_map.end()) { + MySQLServers_SslParams * MSSP = new MySQLServers_SslParams(it->second); + return MSSP; + } + } + return NULL; +} diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index f3d521776a..ea4f0399dc 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -113,6 +113,7 @@ static const vector mysql_servers_tablenames = { "mysql_galera_hostgroups", "mysql_aws_aurora_hostgroups", "mysql_hostgroup_attributes", + "mysql_servers_ssl_params", }; static const vector mysql_firewall_tablenames = { @@ -400,6 +401,10 @@ MHD_Result http_handler(void *cls, struct MHD_Connection *connection, const char #define ADMIN_SQLITE_TABLE_MYSQL_SERVERS ADMIN_SQLITE_TABLE_MYSQL_SERVERS_V2_0_11 +#define ADMIN_SQLITE_TABLE_MYSQL_SERVERS_SSL_PARAMS_V2_6_0 "CREATE TABLE mysql_servers_ssl_params (hostname VARCHAR NOT NULL , port INT CHECK (port >= 0 AND port <= 65535) NOT NULL DEFAULT 3306 , username VARCHAR NOT NULL DEFAULT '' , ssl_ca VARCHAR NOT NULL DEFAULT '' , ssl_cert VARCHAR NOT NULL DEFAULT '' , ssl_key VARCHAR NOT NULL DEFAULT '' , ssl_capath VARCHAR NOT NULL DEFAULT '' , ssl_crl VARCHAR NOT NULL DEFAULT '' , ssl_crlpath VARCHAR NOT NULL DEFAULT '' , ssl_cipher VARCHAR NOT NULL DEFAULT '' , tls_version VARCHAR NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostname, port, username) )" + +#define ADMIN_SQLITE_TABLE_MYSQL_SERVERS_SSL_PARAMS ADMIN_SQLITE_TABLE_MYSQL_SERVERS_SSL_PARAMS_V2_6_0 + #define ADMIN_SQLITE_TABLE_MYSQL_USERS_V1_3_0 "CREATE TABLE mysql_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0 , default_hostgroup INT NOT NULL DEFAULT 0 , default_schema VARCHAR , schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0 , transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 0 , fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0 , backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1 , frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , PRIMARY KEY (username, backend) , UNIQUE (username, frontend))" #define ADMIN_SQLITE_TABLE_MYSQL_USERS_V1_4_0 "CREATE TABLE mysql_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0 , default_hostgroup INT NOT NULL DEFAULT 0 , default_schema VARCHAR , schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0 , transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 1 , fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0 , backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1 , frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , PRIMARY KEY (username, backend) , UNIQUE (username, frontend))" #define ADMIN_SQLITE_TABLE_MYSQL_USERS_V2_0_0 "CREATE TABLE mysql_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0 , default_hostgroup INT NOT NULL DEFAULT 0 , default_schema VARCHAR , schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0 , transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 1 , fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0 , backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1 , frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (username, backend) , UNIQUE (username, frontend))" @@ -522,6 +527,9 @@ MHD_Result http_handler(void *cls, struct MHD_Connection *connection, const char #define ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_SERVERS "CREATE TABLE runtime_mysql_servers (hostgroup_id INT CHECK (hostgroup_id>=0) NOT NULL DEFAULT 0 , hostname VARCHAR NOT NULL , port INT CHECK (port >= 0 AND port <= 65535) NOT NULL DEFAULT 3306 , gtid_port INT CHECK ((gtid_port <> port OR gtid_port=0) AND gtid_port >= 0 AND gtid_port <= 65535) NOT NULL DEFAULT 0 , status VARCHAR CHECK (UPPER(status) IN ('ONLINE','SHUNNED','OFFLINE_SOFT', 'OFFLINE_HARD')) NOT NULL DEFAULT 'ONLINE' , weight INT CHECK (weight >= 0 AND weight <=10000000) NOT NULL DEFAULT 1 , compression INT CHECK (compression IN(0,1)) NOT NULL DEFAULT 0 , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 1000 , max_replication_lag INT CHECK (max_replication_lag >= 0 AND max_replication_lag <= 126144000) NOT NULL DEFAULT 0 , use_ssl INT CHECK (use_ssl IN(0,1)) NOT NULL DEFAULT 0 , max_latency_ms INT UNSIGNED CHECK (max_latency_ms>=0) NOT NULL DEFAULT 0 , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostgroup_id, hostname, port) )" +#define ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_SERVERS_SSL_PARAMS "CREATE TABLE runtime_mysql_servers_ssl_params (hostname VARCHAR NOT NULL , port INT CHECK (port >= 0 AND port <= 65535) NOT NULL DEFAULT 3306 , username VARCHAR NOT NULL DEFAULT '' , ssl_ca VARCHAR NOT NULL DEFAULT '' , ssl_cert VARCHAR NOT NULL DEFAULT '' , ssl_key VARCHAR NOT NULL DEFAULT '' , ssl_capath VARCHAR NOT NULL DEFAULT '' , ssl_crl VARCHAR NOT NULL DEFAULT '' , ssl_crlpath VARCHAR NOT NULL DEFAULT '' , ssl_cipher VARCHAR NOT NULL DEFAULT '' , tls_version VARCHAR NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostname, port, username) )" + + #define ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_REPLICATION_HOSTGROUPS "CREATE TABLE runtime_mysql_replication_hostgroups (writer_hostgroup INT CHECK (writer_hostgroup>=0) NOT NULL PRIMARY KEY , reader_hostgroup INT NOT NULL CHECK (reader_hostgroup<>writer_hostgroup AND reader_hostgroup>=0) , check_type VARCHAR CHECK (LOWER(check_type) IN ('read_only','innodb_read_only','super_read_only','read_only|innodb_read_only','read_only&innodb_read_only')) NOT NULL DEFAULT 'read_only' , comment VARCHAR NOT NULL DEFAULT '', UNIQUE (reader_hostgroup))" #define ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_QUERY_RULES "CREATE TABLE runtime_mysql_query_rules (rule_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 0 , username VARCHAR , schemaname VARCHAR , flagIN INT CHECK (flagIN >= 0) NOT NULL DEFAULT 0 , client_addr VARCHAR , proxy_addr VARCHAR , proxy_port INT CHECK (proxy_port >= 0 AND proxy_port <= 65535), digest VARCHAR , match_digest VARCHAR , match_pattern VARCHAR , negate_match_pattern INT CHECK (negate_match_pattern IN (0,1)) NOT NULL DEFAULT 0 , re_modifiers VARCHAR DEFAULT 'CASELESS' , flagOUT INT CHECK (flagOUT >= 0), replace_pattern VARCHAR CHECK(CASE WHEN replace_pattern IS NULL THEN 1 WHEN replace_pattern IS NOT NULL AND match_pattern IS NOT NULL THEN 1 ELSE 0 END) , destination_hostgroup INT DEFAULT NULL , cache_ttl INT CHECK(cache_ttl > 0) , cache_empty_result INT CHECK (cache_empty_result IN (0,1)) DEFAULT NULL , cache_timeout INT CHECK(cache_timeout >= 0) , reconnect INT CHECK (reconnect IN (0,1)) DEFAULT NULL , timeout INT UNSIGNED CHECK (timeout >= 0) , retries INT CHECK (retries>=0 AND retries <=1000) , delay INT UNSIGNED CHECK (delay >=0) , next_query_flagIN INT UNSIGNED , mirror_flagOUT INT UNSIGNED , mirror_hostgroup INT UNSIGNED , error_msg VARCHAR , OK_msg VARCHAR , sticky_conn INT CHECK (sticky_conn IN (0,1)) , multiplex INT CHECK (multiplex IN (0,1,2)) , gtid_from_hostgroup INT UNSIGNED , log INT CHECK (log IN (0,1)) , apply INT CHECK(apply IN (0,1)) NOT NULL DEFAULT 0 , attributes VARCHAR CHECK (JSON_VALID(attributes) OR attributes = '') NOT NULL DEFAULT '' , comment VARCHAR)" @@ -1103,6 +1111,7 @@ incoming_servers_t::incoming_servers_t( SQLite3_result* incoming_galera_hostgroups, SQLite3_result* incoming_aurora_hostgroups, SQLite3_result* incoming_hostgroup_attributes, + SQLite3_result* incoming_mysql_servers_ssl_params, SQLite3_result* runtime_mysql_servers ) : incoming_mysql_servers_v2(incoming_mysql_servers_v2), @@ -1111,6 +1120,7 @@ incoming_servers_t::incoming_servers_t( incoming_galera_hostgroups(incoming_galera_hostgroups), incoming_aurora_hostgroups(incoming_aurora_hostgroups), incoming_hostgroup_attributes(incoming_hostgroup_attributes), + incoming_mysql_servers_ssl_params(incoming_mysql_servers_ssl_params), runtime_mysql_servers(runtime_mysql_servers) {} @@ -3320,6 +3330,8 @@ bool ProxySQL_Admin::GenericRefreshStatistics(const char *query_no_space, unsign strstr(query_no_space,"runtime_mysql_aws_aurora_hostgroups") || strstr(query_no_space,"runtime_mysql_hostgroup_attributes") + || + strstr(query_no_space,"runtime_mysql_servers_ssl_params") ) { runtime_mysql_servers=true; refresh=true; } @@ -3814,6 +3826,8 @@ void admin_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *pkt) { tn = "mysql_aws_aurora_hostgroups"; } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES, query_no_space, strlen(CLUSTER_QUERY_MYSQL_HOSTGROUP_ATTRIBUTES))) { tn = "mysql_hostgroup_attributes"; + } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS, query_no_space, strlen(CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS))) { + tn = "mysql_servers_ssl_params"; } else if (!strncasecmp(CLUSTER_QUERY_MYSQL_SERVERS_V2, query_no_space, strlen(CLUSTER_QUERY_MYSQL_SERVERS_V2))) { tn = "mysql_servers_v2"; } @@ -5023,6 +5037,15 @@ void admin_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *pkt) { tablename=(char *)"MYSQL HOSTGROUP ATTRIBUTES"; SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); } + if ((strlen(query_no_space)==strlen("CHECKSUM MEMORY MYSQL SERVERS SSL PARAMS") && !strncasecmp("CHECKSUM MEMORY MYSQL SERVERS SSL PARAMS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MEM MYSQL SERVERS SSL PARAMS") && !strncasecmp("CHECKSUM MEM MYSQL SERVERS SSL PARAMS", query_no_space, strlen(query_no_space))) + || + (strlen(query_no_space)==strlen("CHECKSUM MYSQL SERVERS SSL PARAMS") && !strncasecmp("CHECKSUM MYSQL SERVERS SSL PARAMS", query_no_space, strlen(query_no_space)))){ + char *q=(char *)"SELECT * FROM mysql_servers_ssl_params ORDER BY hostname, port, username"; + tablename=(char *)"MYSQL HOSTGROUP ATTRIBUTES"; + SPA->admindb->execute_statement(q, &error, &cols, &affected_rows, &resultset); + } if (error) { proxy_error("Error: %s\n", error); @@ -6462,6 +6485,8 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) { insert_into_tables_defs(tables_defs_admin,"runtime_mysql_aws_aurora_hostgroups", ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_AWS_AURORA_HOSTGROUPS); insert_into_tables_defs(tables_defs_admin,"mysql_hostgroup_attributes", ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES); insert_into_tables_defs(tables_defs_admin,"runtime_mysql_hostgroup_attributes", ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_HOSTGROUP_ATTRIBUTES); + insert_into_tables_defs(tables_defs_admin,"mysql_servers_ssl_params", ADMIN_SQLITE_TABLE_MYSQL_SERVERS_SSL_PARAMS); + insert_into_tables_defs(tables_defs_admin,"runtime_mysql_servers_ssl_params", ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_SERVERS_SSL_PARAMS); insert_into_tables_defs(tables_defs_admin,"mysql_query_rules", ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES); insert_into_tables_defs(tables_defs_admin,"mysql_query_rules_fast_routing", ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES_FAST_ROUTING); insert_into_tables_defs(tables_defs_admin,"runtime_mysql_query_rules", ADMIN_SQLITE_TABLE_RUNTIME_MYSQL_QUERY_RULES); @@ -6500,6 +6525,7 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) { insert_into_tables_defs(tables_defs_config,"mysql_galera_hostgroups", ADMIN_SQLITE_TABLE_MYSQL_GALERA_HOSTGROUPS); insert_into_tables_defs(tables_defs_config,"mysql_aws_aurora_hostgroups", ADMIN_SQLITE_TABLE_MYSQL_AWS_AURORA_HOSTGROUPS); insert_into_tables_defs(tables_defs_config,"mysql_hostgroup_attributes", ADMIN_SQLITE_TABLE_MYSQL_HOSTGROUP_ATTRIBUTES); + insert_into_tables_defs(tables_defs_config,"mysql_servers_ssl_params", ADMIN_SQLITE_TABLE_MYSQL_SERVERS_SSL_PARAMS); insert_into_tables_defs(tables_defs_config,"mysql_query_rules", ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES); insert_into_tables_defs(tables_defs_config,"mysql_query_rules_fast_routing", ADMIN_SQLITE_TABLE_MYSQL_QUERY_RULES_FAST_ROUTING); insert_into_tables_defs(tables_defs_config,"global_variables", ADMIN_SQLITE_TABLE_GLOBAL_VARIABLES); @@ -12940,7 +12966,6 @@ void ProxySQL_Admin::save_mysql_servers_runtime_to_database(bool _runtime) { StrQuery += "mysql_hostgroup_attributes (hostgroup_id, max_num_online_servers, autocommit, free_connections_pct, init_connect, multiplex, connection_warming, throttle_connections_per_sec, ignore_session_variables, hostgroup_settings, servers_defaults, comment) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"; rc = admindb->prepare_v2(StrQuery.c_str(), &statement); ASSERT_SQLITE_OK(rc, admindb); - //proxy_info("New mysql_aws_aurora_hostgroups table\n"); for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { SQLite3_row *r=*it; rc=(*proxy_sqlite3_bind_int64)(statement, 1, atol(r->fields[0])); ASSERT_SQLITE_OK(rc, admindb); // hostgroup_id @@ -12964,6 +12989,51 @@ void ProxySQL_Admin::save_mysql_servers_runtime_to_database(bool _runtime) { } if(resultset) delete resultset; resultset=NULL; + + // dump mysql_servers_ssl_params + + StrQuery = "DELETE FROM main."; + if (_runtime) + StrQuery += "runtime_"; + StrQuery += "mysql_servers_ssl_params"; + proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", StrQuery.c_str()); + admindb->execute(StrQuery.c_str()); + resultset=MyHGM->dump_table_mysql("mysql_servers_ssl_params"); + if (resultset) { + int rc; + // table definition: + // mysql_servers_ssl_params (hostname VARCHAR NOT NULL , port INT CHECK (port >= 0 AND port <= 65535) NOT NULL DEFAULT 3306 , username VARCHAR NOT NULL DEFAULT '' , ssl_ca VARCHAR NOT NULL DEFAULT '' , ssl_cert VARCHAR NOT NULL DEFAULT '' , ssl_key VARCHAR NOT NULL DEFAULT '' , ssl_capath VARCHAR NOT NULL DEFAULT '' , ssl_crl VARCHAR NOT NULL DEFAULT '' , ssl_crlpath VARCHAR NOT NULL DEFAULT '' , ssl_cipher VARCHAR NOT NULL DEFAULT '' , tls_version VARCHAR NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostname, port, username) ) + sqlite3_stmt *statement=NULL; + StrQuery = "INSERT INTO "; + if (_runtime) + StrQuery += "runtime_"; + StrQuery += "mysql_servers_ssl_params (hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"; + rc = admindb->prepare_v2(StrQuery.c_str(), &statement); + ASSERT_SQLITE_OK(rc, admindb); + //proxy_info("New mysql_servers_ssl_params table\n"); + for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { + SQLite3_row *r=*it; + rc=(*proxy_sqlite3_bind_text)(statement, 1, r->fields[0], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // hostname + rc=(*proxy_sqlite3_bind_int64)(statement, 2, atol(r->fields[1])); ASSERT_SQLITE_OK(rc, admindb); // port + rc=(*proxy_sqlite3_bind_text)(statement, 3, r->fields[2], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // username + rc=(*proxy_sqlite3_bind_text)(statement, 4, r->fields[3], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ssl_ca + rc=(*proxy_sqlite3_bind_text)(statement, 5, r->fields[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ssl_cert + rc=(*proxy_sqlite3_bind_text)(statement, 6, r->fields[5], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ssl_key + rc=(*proxy_sqlite3_bind_text)(statement, 7, r->fields[6], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ssl_capath + rc=(*proxy_sqlite3_bind_text)(statement, 8, r->fields[7], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ssl_crl + rc=(*proxy_sqlite3_bind_text)(statement, 9, r->fields[8], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ssl_crlpath + rc=(*proxy_sqlite3_bind_text)(statement, 10, r->fields[9], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // ssl_cipher + rc=(*proxy_sqlite3_bind_text)(statement, 11, r->fields[10], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // tls_version + rc=(*proxy_sqlite3_bind_text)(statement, 12, r->fields[11], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, admindb); // comment + + SAFE_SQLITE3_STEP2(statement); + rc=(*proxy_sqlite3_clear_bindings)(statement); ASSERT_SQLITE_OK(rc, admindb); + rc=(*proxy_sqlite3_reset)(statement); ASSERT_SQLITE_OK(rc, admindb); + } + (*proxy_sqlite3_finalize)(statement); + } + if(resultset) delete resultset; + resultset=NULL; } @@ -12996,6 +13066,7 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime(const incoming_servers_t& inc SQLite3_result *resultset_galera=NULL; SQLite3_result *resultset_aws_aurora=NULL; SQLite3_result *resultset_hostgroup_attributes=NULL; + SQLite3_result *resultset_mysql_servers_ssl_params=NULL; SQLite3_result* runtime_mysql_servers = incoming_servers.runtime_mysql_servers; SQLite3_result* incoming_replication_hostgroups = incoming_servers.incoming_replication_hostgroups; @@ -13003,6 +13074,7 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime(const incoming_servers_t& inc SQLite3_result* incoming_galera_hostgroups = incoming_servers.incoming_galera_hostgroups; SQLite3_result* incoming_aurora_hostgroups = incoming_servers.incoming_aurora_hostgroups; SQLite3_result* incoming_hostgroup_attributes = incoming_servers.incoming_hostgroup_attributes; + SQLite3_result* incoming_mysql_servers_ssl_params = incoming_servers.incoming_mysql_servers_ssl_params; SQLite3_result* incoming_mysql_servers_v2 = incoming_servers.incoming_mysql_servers_v2; const char *query=(char *)"SELECT hostgroup_id,hostname,port,gtid_port,status,weight,compression,max_connections,max_replication_lag,use_ssl,max_latency_ms,comment FROM main.mysql_servers ORDER BY hostgroup_id, hostname, port"; @@ -13171,6 +13243,21 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime(const incoming_servers_t& inc MyHGM->save_incoming_mysql_table(resultset_hostgroup_attributes, "mysql_hostgroup_attributes"); } + // support for SSL parameters, table mysql_servers_ssl_params + query = (char *)"SELECT * FROM mysql_servers_ssl_params ORDER BY hostname, port, username"; + proxy_debug(PROXY_DEBUG_ADMIN, 4, "%s\n", query); + if (incoming_mysql_servers_ssl_params == nullptr) { + admindb->execute_statement(query, &error , &cols , &affected_rows , &resultset_mysql_servers_ssl_params); + } else { + resultset_mysql_servers_ssl_params = incoming_mysql_servers_ssl_params; + } + if (error) { + proxy_error("Error on %s : %s\n", query, error); + } else { + // Pass the resultset to MyHGM + MyHGM->save_incoming_mysql_table(resultset_mysql_servers_ssl_params, "mysql_servers_ssl_params"); + } + // commit all the changes MyHGM->commit( { runtime_mysql_servers, peer_runtime_mysql_server }, @@ -13203,6 +13290,9 @@ void ProxySQL_Admin::load_mysql_servers_to_runtime(const incoming_servers_t& inc if (resultset_hostgroup_attributes) { resultset_hostgroup_attributes = NULL; } + if (resultset_mysql_servers_ssl_params) { + resultset_mysql_servers_ssl_params = NULL; + } } diff --git a/lib/ProxySQL_Cluster.cpp b/lib/ProxySQL_Cluster.cpp index d06ee5114a..1851ba50ce 100644 --- a/lib/ProxySQL_Cluster.cpp +++ b/lib/ProxySQL_Cluster.cpp @@ -1722,6 +1722,7 @@ incoming_servers_t convert_mysql_servers_resultsets(const std::vector results(7,nullptr); + std::vector results(8,nullptr); // servers messages std::string fetch_servers_done = ""; @@ -1956,6 +1957,12 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch std::string fetch_hostgroup_attributes_err = ""; string_format("Cluster: Fetching 'MySQL Hostgroup Attributes' from peer %s:%d failed: \n", fetch_hostgroup_attributes_err, hostname, port); + // mysql servers ssl params messages + std::string fetch_mysql_servers_ssl_params_start = ""; + string_format("Cluster: Fetching 'MySQL Servers SSL Params' from peer %s:%d\n", fetch_mysql_servers_ssl_params_start, hostname, port); + std::string fetch_mysql_servers_ssl_params_err = ""; + string_format("Cluster: Fetching 'MySQL Servers SSL Params' from peer %s:%d failed: \n", fetch_mysql_servers_ssl_params_err, hostname, port); + // Create fetching queries /** @@ -1998,6 +2005,12 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch p_cluster_counter::pulled_mysql_servers_hostgroup_attributes_success, p_cluster_counter::pulled_mysql_servers_hostgroup_attributes_failure, { fetch_hostgroup_attributes_start, "", fetch_hostgroup_attributes_err } + }, + { + CLUSTER_QUERY_MYSQL_SERVERS_SSL_PARAMS, + p_cluster_counter::pulled_mysql_servers_ssl_params_success, + p_cluster_counter::pulled_mysql_servers_ssl_params_failure, + { fetch_mysql_servers_ssl_params_start, "", fetch_mysql_servers_ssl_params_err } } }; @@ -2278,6 +2291,42 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch resultset->dump_to_stderr(); delete resultset; + // sync mysql_servers_ssl_params + proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Writing mysql_servers_ssl_params table\n"); + proxy_info("Cluster: Writing mysql_servers_ssl_params table\n"); + GloAdmin->admindb->execute("DELETE FROM mysql_servers_ssl_params"); + { + const char* q = (const char*)"INSERT INTO mysql_servers_ssl_params (hostname, port, username, ssl_ca, ssl_cert, ssl_key, ssl_capath, ssl_crl, ssl_crlpath, ssl_cipher, tls_version, comment) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)"; + sqlite3_stmt *statement1 = NULL; + int rc = GloAdmin->admindb->prepare_v2(q, &statement1); + ASSERT_SQLITE_OK(rc, GloAdmin->admindb); + + while ((row = mysql_fetch_row(results[6]))) { + rc=(*proxy_sqlite3_bind_text)(statement1, 1, row[0], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // hostname + rc=(*proxy_sqlite3_bind_int64)(statement1, 2, atol(row[1])); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // port + rc=(*proxy_sqlite3_bind_text)(statement1, 3, row[2], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // username + rc=(*proxy_sqlite3_bind_text)(statement1, 4, row[3], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ssl_ca + rc=(*proxy_sqlite3_bind_text)(statement1, 5, row[4], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ssl_cert + rc=(*proxy_sqlite3_bind_text)(statement1, 6, row[5], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ssl_key + rc=(*proxy_sqlite3_bind_text)(statement1, 7, row[6], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ssl_capath + rc=(*proxy_sqlite3_bind_text)(statement1, 8, row[7], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ssl_crl + rc=(*proxy_sqlite3_bind_text)(statement1, 9, row[8], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ssl_crlpath + rc=(*proxy_sqlite3_bind_text)(statement1, 10, row[9], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // ssl_cipher + rc=(*proxy_sqlite3_bind_text)(statement1, 11, row[10], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // tls_version + rc=(*proxy_sqlite3_bind_text)(statement1, 12, row[11], -1, SQLITE_TRANSIENT); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); // comment + SAFE_SQLITE3_STEP2(statement1); + rc = (*proxy_sqlite3_clear_bindings)(statement1); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); + rc = (*proxy_sqlite3_reset)(statement1); ASSERT_SQLITE_OK(rc, GloAdmin->admindb); + } + (*proxy_sqlite3_finalize)(statement1); + } + + proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Dumping fetched 'mysql_servers_ssl_params'\n"); + proxy_info("Dumping fetched 'mysql_servers_ssl_params'\n"); + GloAdmin->admindb->execute_statement((char*)"SELECT * FROM mysql_servers_ssl_params", &error, &cols, &affected_rows, &resultset); + resultset->dump_to_stderr(); + delete resultset; + proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Loading to runtime MySQL Servers v2 from peer %s:%d\n", hostname, port); proxy_info("Cluster: Loading to runtime MySQL Servers v2 from peer %s:%d\n", hostname, port); GloAdmin->load_mysql_servers_to_runtime(incoming_servers, peer_runtime_mysql_server, peer_mysql_server_v2); @@ -4026,6 +4075,27 @@ cluster_metrics_map = std::make_tuple( ), // ==================================================================== + // ==================================================================== + std::make_tuple ( + p_cluster_counter::pulled_mysql_servers_ssl_params_success, + "proxysql_cluster_pulled_total", + "Number of times a 'module' have been pulled from a peer.", + metric_tags { + { "module_name", "mysql_servers_ssl_params" }, + { "status", "success" } + } + ), + std::make_tuple ( + p_cluster_counter::pulled_mysql_servers_ssl_params_failure, + "proxysql_cluster_pulled_total", + "Number of times a 'module' have been pulled from a peer.", + metric_tags { + { "module_name", "mysql_servers_ssl_params" }, + { "status", "failure" } + } + ), + // ==================================================================== + // ==================================================================== std::make_tuple ( p_cluster_counter::pulled_mysql_servers_runtime_checks_success, diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index 458c581858..e8e8f77e78 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -740,14 +740,28 @@ void MySQL_Connection::connect_start() { mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "mysql_bug_102266", "Avoid MySQL bug https://bugs.mysql.com/bug.php?id=102266 , https://github.com/sysown/proxysql/issues/3276"); } if (parent->use_ssl) { - mysql_ssl_set(mysql, - mysql_thread___ssl_p2s_key, - mysql_thread___ssl_p2s_cert, - mysql_thread___ssl_p2s_ca, - mysql_thread___ssl_p2s_capath, - mysql_thread___ssl_p2s_cipher); - mysql_options(mysql, MYSQL_OPT_SSL_CRL, mysql_thread___ssl_p2s_crl); - mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_thread___ssl_p2s_crlpath); + MySQLServers_SslParams * ssl_params = MyHGM->get_Server_SSL_Params(parent->address, parent->port, userinfo->username); + if (ssl_params == NULL) { + mysql_ssl_set(mysql, + mysql_thread___ssl_p2s_key, + mysql_thread___ssl_p2s_cert, + mysql_thread___ssl_p2s_ca, + mysql_thread___ssl_p2s_capath, + mysql_thread___ssl_p2s_cipher); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, mysql_thread___ssl_p2s_crl); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_thread___ssl_p2s_crlpath); + } else { + mysql_ssl_set(mysql, + ssl_params->ssl_key.c_str(), + ssl_params->ssl_cert.c_str(), + ssl_params->ssl_ca.c_str(), + ssl_params->ssl_capath.c_str(), + ssl_params->ssl_cipher.c_str() + ); + mysql_options(mysql, MYSQL_OPT_SSL_CRL, ssl_params->ssl_crl.c_str()); + mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, ssl_params->ssl_crlpath.c_str()); + delete ssl_params; + } mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback); } unsigned int timeout= 1; From 8e6bd3e9832b029c02415180533ca190a1e77003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sun, 18 Feb 2024 20:44:54 +0000 Subject: [PATCH 2/8] Add mysql_servers_ssl_params to MyHGM --- include/MySQL_HostGroups_Manager.h | 3 +++ lib/MySQL_HostGroups_Manager.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/include/MySQL_HostGroups_Manager.h b/include/MySQL_HostGroups_Manager.h index 8dbf907cb3..4029601fb4 100644 --- a/include/MySQL_HostGroups_Manager.h +++ b/include/MySQL_HostGroups_Manager.h @@ -66,6 +66,9 @@ using json = nlohmann::json; #define MYHGM_MYSQL_HOSTGROUP_ATTRIBUTES "CREATE TABLE mysql_hostgroup_attributes (hostgroup_id INT NOT NULL PRIMARY KEY , max_num_online_servers INT CHECK (max_num_online_servers>=0 AND max_num_online_servers <= 1000000) NOT NULL DEFAULT 1000000 , autocommit INT CHECK (autocommit IN (-1, 0, 1)) NOT NULL DEFAULT -1 , free_connections_pct INT CHECK (free_connections_pct >= 0 AND free_connections_pct <= 100) NOT NULL DEFAULT 10 , init_connect VARCHAR NOT NULL DEFAULT '' , multiplex INT CHECK (multiplex IN (0, 1)) NOT NULL DEFAULT 1 , connection_warming INT CHECK (connection_warming IN (0, 1)) NOT NULL DEFAULT 0 , throttle_connections_per_sec INT CHECK (throttle_connections_per_sec >= 1 AND throttle_connections_per_sec <= 1000000) NOT NULL DEFAULT 1000000 , ignore_session_variables VARCHAR CHECK (JSON_VALID(ignore_session_variables) OR ignore_session_variables = '') NOT NULL DEFAULT '' , hostgroup_settings VARCHAR CHECK (JSON_VALID(hostgroup_settings) OR hostgroup_settings = '') NOT NULL DEFAULT '' , servers_defaults VARCHAR CHECK (JSON_VALID(servers_defaults) OR servers_defaults = '') NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '')" + +#define MYHGM_MYSQL_SERVERS_SSL_PARAMS "CREATE TABLE mysql_servers_ssl_params (hostname VARCHAR NOT NULL , port INT CHECK (port >= 0 AND port <= 65535) NOT NULL DEFAULT 3306 , username VARCHAR NOT NULL DEFAULT '' , ssl_ca VARCHAR NOT NULL DEFAULT '' , ssl_cert VARCHAR NOT NULL DEFAULT '' , ssl_key VARCHAR NOT NULL DEFAULT '' , ssl_capath VARCHAR NOT NULL DEFAULT '' , ssl_crl VARCHAR NOT NULL DEFAULT '' , ssl_crlpath VARCHAR NOT NULL DEFAULT '' , ssl_cipher VARCHAR NOT NULL DEFAULT '' , tls_version VARCHAR NOT NULL DEFAULT '' , comment VARCHAR NOT NULL DEFAULT '' , PRIMARY KEY (hostname, port, username) )" + /* * @brief Generates the 'runtime_mysql_servers' resultset exposed to other ProxySQL cluster members. * @details Makes 'SHUNNED' and 'SHUNNED_REPLICATION_LAG' statuses equivalent to 'ONLINE'. 'SHUNNED' states diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index d5d4d0b1a2..90fcf441b3 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -1352,6 +1352,7 @@ MySQL_HostGroups_Manager::MySQL_HostGroups_Manager() { mydb->execute(MYHGM_MYSQL_GALERA_HOSTGROUPS); mydb->execute(MYHGM_MYSQL_AWS_AURORA_HOSTGROUPS); mydb->execute(MYHGM_MYSQL_HOSTGROUP_ATTRIBUTES); + mydb->execute(MYHGM_MYSQL_SERVERS_SSL_PARAMS); mydb->execute("CREATE INDEX IF NOT EXISTS idx_mysql_servers_hostname_port ON mysql_servers (hostname,port)"); MyHostGroups=new PtrArray(); runtime_mysql_servers=NULL; From 385e10950166f1c937a0ae2ae9afdcf4893fddc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sun, 18 Feb 2024 21:13:50 +0000 Subject: [PATCH 3/8] Initialize incoming_mysql_servers_ssl_params to NULL --- lib/MySQL_HostGroups_Manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/MySQL_HostGroups_Manager.cpp b/lib/MySQL_HostGroups_Manager.cpp index 90fcf441b3..c26c18b6ed 100644 --- a/lib/MySQL_HostGroups_Manager.cpp +++ b/lib/MySQL_HostGroups_Manager.cpp @@ -1361,6 +1361,7 @@ MySQL_HostGroups_Manager::MySQL_HostGroups_Manager() { incoming_galera_hostgroups=NULL; incoming_aws_aurora_hostgroups = NULL; incoming_hostgroup_attributes = NULL; + incoming_mysql_servers_ssl_params = NULL; incoming_mysql_servers_v2 = NULL; pthread_rwlock_init(>id_rwlock, NULL); gtid_missing_nodes = false; From da039d1fd00be97822eb00fd6e3435fd03d86212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Sun, 18 Feb 2024 22:08:50 +0000 Subject: [PATCH 4/8] Fix bug in previous commit --- lib/ProxySQL_Cluster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ProxySQL_Cluster.cpp b/lib/ProxySQL_Cluster.cpp index 1851ba50ce..6185e52e88 100644 --- a/lib/ProxySQL_Cluster.cpp +++ b/lib/ProxySQL_Cluster.cpp @@ -2045,7 +2045,7 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch MYSQL_RES* fetch_res = nullptr; if (fetch_and_store(conn, query, &fetch_res) == 0) { - results[6] = fetch_res; + results[7] = fetch_res; } else { fetching_error = true; } From 0e0db46db3853905db1a8cf4a97015a65f8e4f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 19 Feb 2024 21:35:44 +0000 Subject: [PATCH 5/8] Fixing offset in cluster results --- lib/ProxySQL_Cluster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ProxySQL_Cluster.cpp b/lib/ProxySQL_Cluster.cpp index 6185e52e88..cfb73a459c 100644 --- a/lib/ProxySQL_Cluster.cpp +++ b/lib/ProxySQL_Cluster.cpp @@ -2052,15 +2052,15 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch } if (fetching_error == false) { - const uint64_t servers_hash = compute_servers_tables_raw_checksum(results, 6); // ignore runtime_mysql_servers in checksum calculation + const uint64_t servers_hash = compute_servers_tables_raw_checksum(results, 7); // ignore runtime_mysql_servers in checksum calculation const string computed_checksum{ get_checksum_from_hash(servers_hash) }; proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Computed checksum for MySQL Servers v2 from peer %s:%d : %s\n", hostname, port, computed_checksum.c_str()); proxy_info("Cluster: Computed checksum for MySQL Servers v2 from peer %s:%d : %s\n", hostname, port, computed_checksum.c_str()); bool runtime_checksum_matches = true; - if (results[6]) { - const uint64_t runtime_mysql_server_hash = mysql_raw_checksum(results[6]); + if (results[7]) { + const uint64_t runtime_mysql_server_hash = mysql_raw_checksum(results[7]); const std::string runtime_mysql_server_computed_checksum = get_checksum_from_hash(runtime_mysql_server_hash); proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Computed checksum for MySQL Servers from peer %s:%d : %s\n", hostname, port, runtime_mysql_server_computed_checksum.c_str()); proxy_info("Cluster: Computed checksum for MySQL Servers from peer %s:%d : %s\n", hostname, port, runtime_mysql_server_computed_checksum.c_str()); From 5c42db669627c0beb17cac3f1eecb75d2b7a9780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 19 Feb 2024 21:46:36 +0000 Subject: [PATCH 6/8] If cluster synchnonization fails , wait 1 second This is a simple way to slow down loops --- lib/ProxySQL_Cluster.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/ProxySQL_Cluster.cpp b/lib/ProxySQL_Cluster.cpp index cfb73a459c..c1b6dc471c 100644 --- a/lib/ProxySQL_Cluster.cpp +++ b/lib/ProxySQL_Cluster.cpp @@ -1162,6 +1162,7 @@ void ProxySQL_Cluster::pull_mysql_query_rules_from_peer(const string& expected_c char * hostname = NULL; char * ip_address = NULL; uint16_t port = 0; + bool fetch_failed = false; pthread_mutex_lock(&GloProxyCluster->update_mysql_query_rules_mutex); nodes.get_peer_to_sync_mysql_query_rules(&hostname, &port, &ip_address); if (hostname) { @@ -1340,16 +1341,19 @@ void ProxySQL_Cluster::pull_mysql_query_rules_from_peer(const string& expected_c hostname, port, expected_checksum.c_str(), computed_checksum.c_str() ); metrics.p_counter_array[p_cluster_counter::pulled_mysql_query_rules_failure]->Increment(); + fetch_failed = true; } } else { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching MySQL Query Rules from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching MySQL Query Rules from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_query_rules_failure]->Increment(); + fetch_failed = true; } } else { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching MySQL Query Rules from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching MySQL Query Rules from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_query_rules_failure]->Increment(); + fetch_failed = true; } if (result1) { mysql_free_result(result1); @@ -1361,6 +1365,7 @@ void ProxySQL_Cluster::pull_mysql_query_rules_from_peer(const string& expected_c proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching MySQL Query Rules from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching MySQL Query Rules from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_query_rules_failure]->Increment(); + fetch_failed = true; } } __exit_pull_mysql_query_rules_from_peer: @@ -1377,6 +1382,7 @@ void ProxySQL_Cluster::pull_mysql_query_rules_from_peer(const string& expected_c proxy_info("No hostname found\n"); } pthread_mutex_unlock(&GloProxyCluster->update_mysql_query_rules_mutex); + if (fetch_failed == true) sleep(1); } uint64_t get_mysql_users_checksum( @@ -1450,6 +1456,7 @@ void ProxySQL_Cluster::pull_mysql_users_from_peer(const string& expected_checksu char * hostname = NULL; char * ip_address = NULL; uint16_t port = 0; + bool fetch_failed = false; pthread_mutex_lock(&GloProxyCluster->update_mysql_users_mutex); nodes.get_peer_to_sync_mysql_users(&hostname, &port, &ip_address); if (hostname) { @@ -1481,11 +1488,13 @@ void ProxySQL_Cluster::pull_mysql_users_from_peer(const string& expected_checksu proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching MySQL Users from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching MySQL Users from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_users_failure]->Increment(); + fetch_failed = true; if (GloMyLdapAuth) { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching LDAP Mappings from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching LDAP Mappings from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_ldap_mapping_failure]->Increment(); + fetch_failed = true; } goto __exit_pull_mysql_users_from_peer; @@ -1517,6 +1526,7 @@ void ProxySQL_Cluster::pull_mysql_users_from_peer(const string& expected_checksu proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching LDAP Mappings from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching LDAP Mappings from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_ldap_mapping_failure]->Increment(); + fetch_failed = true; } } @@ -1582,6 +1592,7 @@ void ProxySQL_Cluster::pull_mysql_users_from_peer(const string& expected_checksu hostname, port, expected_checksum.c_str(), computed_checksum.c_str() ); metrics.p_counter_array[p_cluster_counter::pulled_mysql_users_failure]->Increment(); + fetch_failed = true; if (GloMyLdapAuth) { metrics.p_counter_array[p_cluster_counter::pulled_mysql_ldap_mapping_failure]->Increment(); @@ -1591,6 +1602,7 @@ void ProxySQL_Cluster::pull_mysql_users_from_peer(const string& expected_checksu proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching MySQL Users from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching MySQL Users from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_users_failure]->Increment(); + fetch_failed = true; if (GloMyLdapAuth) { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching LDAP Mappings from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); @@ -1617,6 +1629,7 @@ void ProxySQL_Cluster::pull_mysql_users_from_peer(const string& expected_checksu free(ip_address); } pthread_mutex_unlock(&GloProxyCluster->update_mysql_users_mutex); + if (fetch_failed == true) sleep(1); } /** @@ -1744,7 +1757,7 @@ void ProxySQL_Cluster::pull_runtime_mysql_servers_from_peer(const runtime_mysql_ char * ip_address = NULL; uint16_t port = 0; char * peer_checksum = NULL; - + bool fetch_failed = false; pthread_mutex_lock(&GloProxyCluster->update_runtime_mysql_servers_mutex); nodes.get_peer_to_sync_runtime_mysql_servers(&hostname, &port, &peer_checksum, &ip_address); if (hostname) { @@ -1830,6 +1843,7 @@ void ProxySQL_Cluster::pull_runtime_mysql_servers_from_peer(const runtime_mysql_ proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching MySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching MySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_servers_failure]->Increment(); + fetch_failed = true; } } if (username) { @@ -1853,6 +1867,7 @@ void ProxySQL_Cluster::pull_runtime_mysql_servers_from_peer(const runtime_mysql_ free(ip_address); } pthread_mutex_unlock(&GloProxyCluster->update_runtime_mysql_servers_mutex); + if (fetch_failed == true) sleep(1); } /** @@ -1894,7 +1909,7 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch uint16_t port = 0; char* peer_mysql_servers_v2_checksum = NULL; char* peer_runtime_mysql_servers_checksum = NULL; - + bool fetch_failed = false; pthread_mutex_lock(&GloProxyCluster->update_mysql_servers_v2_mutex); nodes.get_peer_to_sync_mysql_servers_v2(&hostname, &port, &peer_mysql_servers_v2_checksum, &peer_runtime_mysql_servers_checksum, &ip_address); @@ -2023,6 +2038,7 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch results[i] = fetch_res; } else { fetching_error = true; + fetch_failed = true; break; } } @@ -2352,6 +2368,7 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch hostname, port, peer_mysql_servers_v2_checksum, computed_checksum.c_str() ); metrics.p_counter_array[p_cluster_counter::pulled_mysql_variables_failure]->Increment(); + fetch_failed = true; } // free results @@ -2365,6 +2382,7 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching MySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching MySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_mysql_servers_failure]->Increment(); + fetch_failed = true; } } if (username) { @@ -2391,6 +2409,7 @@ void ProxySQL_Cluster::pull_mysql_servers_v2_from_peer(const mysql_servers_v2_ch free(peer_runtime_mysql_servers_checksum); } pthread_mutex_unlock(&GloProxyCluster->update_mysql_servers_v2_mutex); + if (fetch_failed == true) sleep(1); } void ProxySQL_Cluster::pull_global_variables_from_peer(const string& var_type, const string& expected_checksum, const time_t epoch) { @@ -2418,6 +2437,7 @@ void ProxySQL_Cluster::pull_global_variables_from_peer(const string& var_type, c assert(0); } + bool fetch_failed = false; pthread_mutex_lock(&GloProxyCluster->update_mysql_variables_mutex); if (var_type == "mysql") { nodes.get_peer_to_sync_mysql_variables(&hostname, &port, &ip_address); @@ -2559,16 +2579,19 @@ void ProxySQL_Cluster::pull_global_variables_from_peer(const string& var_type, c vars_type_str, hostname, port, expected_checksum.c_str(), computed_checksum.c_str() ); metrics.p_counter_array[p_cluster_counter::pulled_mysql_variables_failure]->Increment(); + fetch_failed = true; } } else { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching %s Variables from peer %s:%d failed: %s\n", vars_type_str, hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching %s Variables from peer %s:%d failed: %s\n", vars_type_str, hostname, port, mysql_error(conn)); metrics.p_counter_array[failure_metric]->Increment(); + fetch_failed = true; } } else { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching %s Variables from peer %s:%d failed: %s\n", vars_type_str, hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching %s Variables from peer %s:%d failed: %s\n", vars_type_str, hostname, port, mysql_error(conn)); metrics.p_counter_array[failure_metric]->Increment(); + fetch_failed = true; } } if (username) { @@ -2589,12 +2612,14 @@ void ProxySQL_Cluster::pull_global_variables_from_peer(const string& var_type, c free(ip_address); } pthread_mutex_unlock(&GloProxyCluster->update_mysql_variables_mutex); + if (fetch_failed == true) sleep(1); } void ProxySQL_Cluster::pull_proxysql_servers_from_peer(const std::string& expected_checksum, const time_t epoch) { char * hostname = NULL; char * ip_address = NULL; uint16_t port = 0; + bool fetch_failed = false; pthread_mutex_lock(&GloProxyCluster->update_proxysql_servers_mutex); nodes.get_peer_to_sync_proxysql_servers(&hostname, &port, &ip_address); if (hostname) { @@ -2687,17 +2712,20 @@ void ProxySQL_Cluster::pull_proxysql_servers_from_peer(const std::string& expect hostname, port, expected_checksum.c_str(), computed_cks.c_str() ); metrics.p_counter_array[p_cluster_counter::pulled_proxysql_servers_failure]->Increment(); + fetch_failed = true; } mysql_free_result(result); } else { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching ProxySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching ProxySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_proxysql_servers_failure]->Increment(); + fetch_failed = true; } } else { proxy_debug(PROXY_DEBUG_CLUSTER, 5, "Fetching ProxySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); proxy_info("Cluster: Fetching ProxySQL Servers from peer %s:%d failed: %s\n", hostname, port, mysql_error(conn)); metrics.p_counter_array[p_cluster_counter::pulled_proxysql_servers_failure]->Increment(); + fetch_failed = true; } } if (username) { @@ -2718,6 +2746,7 @@ void ProxySQL_Cluster::pull_proxysql_servers_from_peer(const std::string& expect free(ip_address); } pthread_mutex_unlock(&GloProxyCluster->update_proxysql_servers_mutex); + if (fetch_failed == true) sleep(1); } void ProxySQL_Node_Entry::set_metrics(MYSQL_RES *_r, unsigned long long _response_time) { From fdd800a217cee6a9a32784d5fbf7876d0cc462df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Thu, 22 Feb 2024 23:10:56 +0000 Subject: [PATCH 7/8] Avoid fast retry on cluster --- lib/ProxySQL_Cluster.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ProxySQL_Cluster.cpp b/lib/ProxySQL_Cluster.cpp index c1b6dc471c..60581b714f 100644 --- a/lib/ProxySQL_Cluster.cpp +++ b/lib/ProxySQL_Cluster.cpp @@ -275,6 +275,7 @@ void * ProxySQL_Cluster_Monitor_thread(void *args) { conn = mysql_init(NULL); int ci = __sync_fetch_and_add(&GloProxyCluster->cluster_check_interval_ms,0); usleep((ci)*1000); // remember, usleep is in us + sleep(1); // sleep for longer } } else { sleep(1); // do not monitor if the username is empty From 548ededd4f4cd511d7ff1794e0247692c492e298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Thu, 22 Feb 2024 23:55:28 +0000 Subject: [PATCH 8/8] Include MySQLServers_SslParams in MySQL_Connection This allows to preserve the parameters, and output in the error log if needed --- include/mysql_connection.h | 5 +++++ lib/mysql_connection.cpp | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/include/mysql_connection.h b/include/mysql_connection.h index 5b90881517..ae7dbeffe6 100644 --- a/include/mysql_connection.h +++ b/include/mysql_connection.h @@ -21,6 +21,8 @@ using json = nlohmann::json; #define STATUS_MYSQL_CONNECTION_HAS_SAVEPOINT 0x00000800 #define STATUS_MYSQL_CONNECTION_HAS_WARNINGS 0x00001000 +class MySQLServers_SslParams; + class Variable { public: char *value = (char*)""; @@ -151,6 +153,9 @@ class MySQL_Connection { bool unknown_transaction_status; void compute_unknown_transaction_status(); char gtid_uuid[128]; + + MySQLServers_SslParams * ssl_params = NULL; + MySQL_Connection(); ~MySQL_Connection(); bool set_autocommit(bool); diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index e8e8f77e78..e3430b02a7 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -514,6 +514,11 @@ MySQL_Connection::~MySQL_Connection() { if (connected_host_details.ip) free(connected_host_details.ip); + + if (ssl_params != NULL) { + delete ssl_params; + ssl_params = NULL; + } }; bool MySQL_Connection::set_autocommit(bool _ac) { @@ -740,7 +745,11 @@ void MySQL_Connection::connect_start() { mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "mysql_bug_102266", "Avoid MySQL bug https://bugs.mysql.com/bug.php?id=102266 , https://github.com/sysown/proxysql/issues/3276"); } if (parent->use_ssl) { - MySQLServers_SslParams * ssl_params = MyHGM->get_Server_SSL_Params(parent->address, parent->port, userinfo->username); + if (ssl_params != NULL) { + delete ssl_params; + ssl_params = NULL; + } + ssl_params = MyHGM->get_Server_SSL_Params(parent->address, parent->port, userinfo->username); if (ssl_params == NULL) { mysql_ssl_set(mysql, mysql_thread___ssl_p2s_key, @@ -760,7 +769,6 @@ void MySQL_Connection::connect_start() { ); mysql_options(mysql, MYSQL_OPT_SSL_CRL, ssl_params->ssl_crl.c_str()); mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, ssl_params->ssl_crlpath.c_str()); - delete ssl_params; } mysql_options(mysql, MARIADB_OPT_SSL_KEYLOG_CALLBACK, (void*)proxysql_keylog_write_line_callback); } @@ -1151,13 +1159,29 @@ MDB_ASYNC_ST MySQL_Connection::handler(short event) { } } if (!ret_mysql) { - // always increase the counter - proxy_error("Failed to mysql_real_connect() on %u:%s:%d , FD (Conn:%d , MyDS:%d) , %d: %s.\n", parent->myhgc->hid, parent->address, parent->port, mysql->net.fd , myds->fd, mysql_errno(mysql), mysql_error(mysql)); - NEXT_IMMEDIATE(ASYNC_CONNECT_FAILED); + int myerr = mysql_errno(mysql); + if (ssl_params != NULL && myerr == 2026) { + proxy_error("Failed to mysql_real_connect() on %u:%s:%d , FD (Conn:%d , MyDS:%d) , %d: %s. SSL Params: %s , %s , %s , %s , %s , %s , %s , %s\n", + parent->myhgc->hid, parent->address, parent->port, mysql->net.fd , myds->fd, mysql_errno(mysql), mysql_error(mysql), + ssl_params->ssl_ca.c_str() , ssl_params->ssl_cert.c_str() , ssl_params->ssl_key.c_str() , ssl_params->ssl_capath.c_str() , + ssl_params->ssl_crl.c_str() , ssl_params->ssl_crlpath.c_str() , ssl_params->ssl_cipher.c_str() , ssl_params->tls_version.c_str() + ); + } else { + proxy_error("Failed to mysql_real_connect() on %u:%s:%d , FD (Conn:%d , MyDS:%d) , %d: %s.\n", parent->myhgc->hid, parent->address, parent->port, mysql->net.fd , myds->fd, mysql_errno(mysql), mysql_error(mysql)); + } + if (ssl_params != NULL) { + delete ssl_params; + ssl_params = NULL; + } + NEXT_IMMEDIATE(ASYNC_CONNECT_FAILED); } else { - NEXT_IMMEDIATE(ASYNC_CONNECT_SUCCESSFUL); + if (ssl_params != NULL) { + delete ssl_params; + ssl_params = NULL; + } + NEXT_IMMEDIATE(ASYNC_CONNECT_SUCCESSFUL); } - break; + break; case ASYNC_CONNECT_SUCCESSFUL: if (mysql && ret_mysql) { // PMC-10005