Merge pull request #5085 from wazir-ahmed/intercept-ssl-version

Handle `SHOW STATUS LIKE 'Ssl_version'` in ProxySQL without any backend
pull/5090/head
René Cannaò 6 months ago committed by GitHub
commit 9c7111d9e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -56,6 +56,8 @@ using json = nlohmann::json;
#define SELECT_VARIABLE_IDENTITY_LEN 17
#define SELECT_VARIABLE_IDENTITY_LIMIT1 "SELECT @@IDENTITY LIMIT 1"
#define SELECT_VARIABLE_IDENTITY_LIMIT1_LEN 25
#define SHOW_STATUS_LIKE_SSL_VERSION "SHOW STATUS LIKE 'Ssl_version"
#define SHOW_STATUS_LIKE_SSL_VERSION_LEN 29
#define EXPMARIA
@ -1394,6 +1396,34 @@ bool MySQL_Session::handler_special_queries(PtrSize_t *pkt) {
l_free(pkt->size, pkt->ptr);
return true;
}
// Handle SHOW STATUS LIKE 'Ssl_version%'
if ((pkt->size >= SHOW_STATUS_LIKE_SSL_VERSION_LEN + 5) && (strncasecmp(SHOW_STATUS_LIKE_SSL_VERSION, (char*)pkt->ptr + 5, SHOW_STATUS_LIKE_SSL_VERSION_LEN) == 0)) {
SQLite3_result* resultset = new SQLite3_result(2);
resultset->add_column_definition(SQLITE_TEXT, "Variable_name");
resultset->add_column_definition(SQLITE_TEXT, "Value");
const char* ssl_version = "";
if (client_myds->encrypted && client_myds->ssl) {
ssl_version = SSL_get_version(client_myds->ssl);
}
char* pta[2];
pta[0] = (char*)"Ssl_version";
pta[1] = (char*)ssl_version;
resultset->add_row(pta);
bool deprecate_eof_active = client_myds->myconn->options.client_flag & CLIENT_DEPRECATE_EOF;
SQLite3_to_MySQL(resultset, NULL, 0, &client_myds->myprot, false, deprecate_eof_active);
delete resultset;
if (mirror == false) {
RequestEnd(NULL);
}
l_free(pkt->size, pkt->ptr);
return true;
}
// 'LOAD DATA LOCAL INFILE' is unsupported. We report an specific error to inform clients about this fact. For more context see #833.
if ( (pkt->size >= 22 + 5) && (strncasecmp((char *)"LOAD DATA LOCAL INFILE",(char *)pkt->ptr+5, 22)==0) ) {
if (mysql_thread___enable_load_data_local_infile == false) {

@ -2168,11 +2168,14 @@ void check_conn_count(MYSQL* admin, const string& conn_type, uint32_t conn_num,
void check_query_count(MYSQL* admin, uint32_t queries, uint32_t hg) {
const string queries_s { to_string(queries) };
const string hg_s { to_string(hg) };
const string select_hg_queries {
"SELECT Queries FROM stats_mysql_connection_pool WHERE hostgroup=" + to_string(hg)
};
string select_hg_queries;
if (hg == -1) {
select_hg_queries = "SELECT SUM(Queries) FROM stats_mysql_connection_pool";
} else {
select_hg_queries = "SELECT Queries FROM stats_mysql_connection_pool WHERE hostgroup=" + to_string(hg);
}
const string check_queries {
"SELECT IIF((" + select_hg_queries + ")=" + queries_s + ",'TRUE','FALSE')"
};
@ -2193,11 +2196,14 @@ void check_query_count(MYSQL* admin, vector<uint32_t> queries, uint32_t hg) {
}
)
};
const string hg_s { to_string(hg) };
const string select_hg_queries {
"SELECT Queries FROM stats_mysql_connection_pool WHERE hostgroup=" + to_string(hg)
};
string select_hg_queries;
if (hg == -1) {
select_hg_queries = "SELECT SUM(Queries) FROM stats_mysql_connection_pool";
} else {
select_hg_queries = "SELECT Queries FROM stats_mysql_connection_pool WHERE hostgroup=" + to_string(hg);
}
const string check_queries {
"SELECT IIF((" + select_hg_queries + ") IN (" + queries_s + "),'TRUE','FALSE')"
};
@ -2316,3 +2322,38 @@ bool get_env_bool(const char* envname, bool envdefault) {
return (bool) res;
};
MYSQL* init_mysql_conn(char* host, int port, char* user, char* pass, bool ssl, bool cmp) {
diag("Creating MySQL conn host=\"%s\" port=\"%d\" user=\"%s\" ssl=\"%d\" cmp=\"%d\"", host, port, user, ssl, cmp);
MYSQL* mysql = mysql_init(NULL);
if (!mysql) {
return nullptr;
}
if (cmp) {
if (mysql_options(mysql, MYSQL_OPT_COMPRESS, nullptr)) {
return nullptr;
}
}
int cflags = 0;
if (ssl) {
if (mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL)) {
return nullptr;
}
cflags |= CLIENT_SSL;
}
if (!mysql_real_connect(mysql, host, user, pass, NULL, port, NULL, cflags)) {
return nullptr;
}
return mysql;
}
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY_T(mysql,q);
return 0;
}

@ -976,8 +976,8 @@ struct srv_addr_t {
// Helpers using 'wait_for_cond' on 'stats_mysql_connection'
void check_conn_count(MYSQL* admin, const std::string& conn_type, uint32_t conn_num, int32_t hg=-1);
void check_query_count(MYSQL* admin, uint32_t queries, uint32_t hg);
void check_query_count(MYSQL* admin, std::vector<uint32_t> queries, uint32_t hg);
void check_query_count(MYSQL* admin, uint32_t queries, uint32_t hg=-1);
void check_query_count(MYSQL* admin, std::vector<uint32_t> queries, uint32_t hg=-1);
/**
* @brief Fetches the ProxySQL nodes configured in the supplied instance.
@ -1009,4 +1009,7 @@ const char* get_env_str(const char* envname, const char* envdefault);
int get_env_int(const char* envname, int envdefault);
bool get_env_bool(const char* envname, bool envdefault);
MYSQL* init_mysql_conn(char* host, int port, char* user, char* pass, bool ssl=false, bool cmp=false);
int run_q(MYSQL *mysql, const char *q);
#endif // #define UTILS_H

@ -103,10 +103,6 @@ void add_commands_set1(std::vector<std::string>& queries, std::string m, bool wi
}
}
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
int main() {
CommandLine cl;

@ -37,10 +37,6 @@ std::vector<unsigned int> vals = { 100, 345, 800 };
std::vector<std::string> queries = {};
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
int main() {
CommandLine cl;

@ -51,10 +51,6 @@ std::vector<std::string> queries = {
"LOAD MYSQL FIREWALL TO RUNTIME",
};
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
int main() {
CommandLine cl;

@ -22,10 +22,6 @@ This test verifies a variety of things:
const int NUM_CONNS = 5;
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
int main(int argc, char** argv) {
CommandLine cl;

@ -18,10 +18,6 @@ This test verifies that client connections are dropped because of:
const int NUM_CONNS = 5;
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
MYSQL * conns[NUM_CONNS];
unsigned long mythreadid[NUM_CONNS];

@ -18,10 +18,6 @@ This test verifies that client connections are dropped because of:
const int NUM_CONNS = 35;
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
MYSQL * conns[NUM_CONNS];
unsigned long mythreadid[NUM_CONNS];

@ -18,10 +18,6 @@ This test verifies that client connections are dropped because of:
const int NUM_CONNS = 35;
const int RPI = 50;
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
MYSQL * conns[NUM_CONNS];
unsigned long mythreadid[NUM_CONNS];

@ -24,11 +24,6 @@ This test also triggers:
const int NUM_CONNS = 15;
const int RPI = 20; // rows per insert
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
MYSQL * conns[NUM_CONNS];
unsigned long mythreadid[NUM_CONNS];

@ -88,25 +88,6 @@ uint64_t measure_avg_query_time(
return avg;
}
MYSQL* init_mysql_conn(char* host, char* user, char* pass, int port, bool cmp=false) {
diag("Creating MySQL conn host=\"%s\" port=\"%d\" cmp=\"%d\"", user, port, cmp);
MYSQL* mysql = mysql_init(NULL);
if (!mysql) {
return nullptr;
}
if (cmp) {
if (mysql_options(mysql, MYSQL_OPT_COMPRESS, nullptr)) {
return nullptr;
}
}
if (!mysql_real_connect(mysql, host, user, pass, NULL, port, NULL, 0)) {
return nullptr;
}
return mysql;
}
const char version_comment_query[] { "select @@version_comment limit 1" };
@ -140,13 +121,13 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
MYSQL* admin = init_mysql_conn(cl.host, cl.admin_username, cl.admin_password, cl.admin_port);
MYSQL* admin = init_mysql_conn(cl.host, cl.admin_port, cl.admin_username, cl.admin_password);
if (!admin) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(admin));
return EXIT_FAILURE;
}
MYSQL* proxy = init_mysql_conn(cl.host, cl.username, cl.password, cl.port);
MYSQL* proxy = init_mysql_conn(cl.host, cl.port, cl.username, cl.password);
if (!proxy) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(admin));
return EXIT_FAILURE;
@ -185,17 +166,17 @@ int main(int argc, char** argv) {
" (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) as u4;"
);
MYSQL* proxy_cmp = init_mysql_conn(cl.host, cl.username, cl.password, cl.port, true);
MYSQL* proxy_cmp = init_mysql_conn(cl.host, cl.port, cl.username, cl.password, false, true);
if (!proxy_cmp) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy_cmp));
return EXIT_FAILURE;
}
MYSQL* mysql = init_mysql_conn(cl.host, cl.username, cl.password, cl.mysql_port, false);
MYSQL* mysql = init_mysql_conn(cl.host, cl.mysql_port, cl.username, cl.password, false, false);
if (!mysql) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql));
return EXIT_FAILURE;
}
MYSQL* mysql_cmp = init_mysql_conn(cl.host, cl.username, cl.password, cl.mysql_port, true);
MYSQL* mysql_cmp = init_mysql_conn(cl.host, cl.mysql_port, cl.username, cl.password, false, true);
if (!mysql_cmp) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql_cmp));
return EXIT_FAILURE;

@ -0,0 +1,88 @@
/**
* @file mysql-show_ssl_version-t.cpp
* @brief This TAP test verifies that 'SHOW STATUS LIKE 'Ssl_version'' is handled by ProxySQL
* without backend connection and returns appropriate SSL version information.
*/
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <string>
#include "mysql.h"
#include "tap.h"
#include "command_line.h"
#include "utils.h"
using std::string;
int main(int argc, char** argv) {
CommandLine cl;
if (cl.getEnv()) {
diag("Failed to get the required environmental variables.");
return exit_status();
}
std::vector<string> ssl_version_queries = {
"SHOW STATUS LIKE 'Ssl_version'",
"SHOW STATUS LIKE 'ssl_version'",
"SHOW STATUS LIKE 'Ssl_version%'",
"show status LIKE 'Ssl_version'",
"show status LIKE 'ssl_version'",
"show status LIKE 'Ssl_version%'",
"show status like 'Ssl_version'",
"show status like 'ssl_version'",
"show status like 'Ssl_version%'",
};
int num_plans = ssl_version_queries.size() + 1; // +1 for query count check
plan(num_plans);
MYSQL* admin = init_mysql_conn(cl.host, cl.admin_port, cl.admin_username, cl.admin_password);
if (!admin) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(admin));
return exit_status();
}
MYSQL_QUERY_T(admin, "SELECT 1 FROM stats.stats_mysql_connection_pool_reset");
MYSQL_RES* reset_result = mysql_store_result(admin);
mysql_free_result(reset_result);
MYSQL* proxy = init_mysql_conn(cl.host, cl.port, cl.username, cl.password, true);
if (!proxy) {
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy));
return exit_status();
}
if (!mysql_get_ssl_cipher(proxy)) {
diag("Connection is not SSL");
return exit_status();
}
for (auto& query : ssl_version_queries) {
int rc = run_q(proxy, query.c_str());
if (rc == 0) {
string var_name;
string var_value;
MYSQL_RES* result = mysql_store_result(proxy);
MYSQL_ROW row = mysql_fetch_row(result);
if (row) {
var_name = row[0];
var_value = row[1];
}
ok((var_name == "Ssl_version" && var_value.find("TLS") == 0), "Ssl_version returned by ProxySQL: %s", var_value.c_str());
mysql_free_result(result);
}
}
check_query_count(admin, 0);
mysql_close(proxy);
mysql_close(admin);
return exit_status();
}

@ -26,11 +26,6 @@
* 127.0.0.1:26009 : satellite node6
*/
int run_q(MYSQL *mysql, const char *q) {
MYSQL_QUERY(mysql,q);
return 0;
}
void get_time(std::string& s) {
time_t __timer;
char __buffer[30];

Loading…
Cancel
Save