diff --git a/include/proxysql_admin.h b/include/proxysql_admin.h index d1a2741863..e15826abcf 100644 --- a/include/proxysql_admin.h +++ b/include/proxysql_admin.h @@ -634,6 +634,7 @@ class ProxySQL_Admin { #ifdef DEBUG unsigned long long ProxySQL_Test___MySQL_HostGroups_Manager_HG_lookup(); unsigned long long ProxySQL_Test___MySQL_HostGroups_Manager_Balancing_HG5211(); + bool ProxySQL_Test___CA_Certificate_Load_And_Verify(uint64_t* duration, int cnt, const char* cacert, const char* capath); #endif friend void admin_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *pkt); }; diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index f3d521776a..81012b9504 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "MySQL_HostGroups_Manager.h" #include "mysql.h" #include "proxysql_admin.h" @@ -4343,6 +4345,29 @@ void admin_session_handler(MySQL_Session *sess, void *_pa, PtrSize_t *pkt) { run_query = false; } break; + case 54: + { + run_query = false; + if (test_arg1 == 0) { + test_arg1 = 1000; + } + if (GloMTH->variables.ssl_p2s_ca == NULL && + GloMTH->variables.ssl_p2s_capath == NULL) { + SPA->send_MySQL_ERR(&sess->client_myds->myprot, "'mysql-ssl_p2s_ca' and 'mysql-ssl_p2s_capath' have not been configured"); + break; + } + char msg[256]; + uint64_t duration = 0ULL; + if (SPA->ProxySQL_Test___CA_Certificate_Load_And_Verify(&duration, test_arg1, GloMTH->variables.ssl_p2s_ca, + GloMTH->variables.ssl_p2s_capath)) { + sprintf(msg, "Took %llums in loading and verifying CA Certificate for %d times\n", duration, test_arg1); + SPA->send_MySQL_OK(&sess->client_myds->myprot, msg); + } + else { + SPA->send_MySQL_ERR(&sess->client_myds->myprot, "Unable to verify CA Certificate"); + } + } + break; #endif // DEBUG default: SPA->send_MySQL_ERR(&sess->client_myds->myprot, (char *)"Invalid test"); @@ -14898,4 +14923,23 @@ unsigned long long ProxySQL_Admin::ProxySQL_Test___MySQL_HostGroups_Manager_Bala unsigned long long d = t2-t1; return d; } + +bool ProxySQL_Admin::ProxySQL_Test___CA_Certificate_Load_And_Verify(uint64_t* duration, int cnt, const char* cacert, const char* capath) +{ + assert(duration); + assert(cacert || capath); + SSL_CTX* ctx = SSL_CTX_new(TLS_client_method()); + uint64_t t1 = monotonic_time(); + for (int i = 0; i < cnt; i++) { + if (0 == SSL_CTX_load_verify_locations(ctx, cacert, capath)) { + proxy_error("Unable to load CA Certificate: %s\n", ERR_error_string(ERR_get_error(), NULL)); + return false; + } + } + uint64_t t2 = monotonic_time(); + SSL_CTX_free(ctx); + *duration = ((t2/1000) - (t1/1000)); + proxy_info("Duration: %llums\n", *duration); + return true; +} #endif //DEBUG diff --git a/test/tap/tests/test_cacert_load_and_verify_duration-t.cpp b/test/tap/tests/test_cacert_load_and_verify_duration-t.cpp new file mode 100644 index 0000000000..46fbde802e --- /dev/null +++ b/test/tap/tests/test_cacert_load_and_verify_duration-t.cpp @@ -0,0 +1,65 @@ +#include +#include +#include "mysql.h" +#include "mysqld_error.h" +#include "tap.h" +#include "command_line.h" +#include "utils.h" + +CommandLine cl; + +int main() { + if (cl.getEnv()) { + diag("Failed to get the required environmental variables."); + return -1; + } + + const char* p_infra_datadir = std::getenv("REGULAR_INFRA_DATADIR"); + if (p_infra_datadir == NULL) { + // quick exit + plan(1); + ok(0, "REGULAR_INFRA_DATADIR not defined"); + return exit_status(); + } + + plan(1); + + MYSQL* proxysql_admin = mysql_init(NULL); + + // Initialize connection + if (!proxysql_admin) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return -1; + } + + if (!mysql_real_connect(proxysql_admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxysql_admin)); + return -1; + } + + const std::string& ca_full_path = std::string(p_infra_datadir) + "/cert-bundle-rnd.pem"; + diag("Setting mysql-ssl_p2s_ca to '%s'", ca_full_path.c_str()); + const std::string& set_ssl_p2s_ca = "SET mysql-ssl_p2s_ca='" + ca_full_path + "'"; + MYSQL_QUERY(proxysql_admin, set_ssl_p2s_ca.c_str()); + MYSQL_QUERY(proxysql_admin, "LOAD MYSQL VARIABLES TO RUNTIME"); + diag("Running ProxySQL Test..."); + if (mysql_query(proxysql_admin, "PROXYSQLTEST 54 1000")) { + const std::string& error_msg = mysql_error(proxysql_admin); + if (error_msg.find("Invalid test") != std::string::npos) { + ok(true, "ProxySQL is not compiled in Debug mode. Skipping test"); + } else { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, error_msg); + } + } else { + const std::string& msg = mysql_info(proxysql_admin); + const std::size_t start_pos = msg.find("Took "); + const std::size_t end_pos = msg.find("ms "); + if (start_pos != std::string::npos && + end_pos != std::string::npos) { + uint64_t time = std::stoull(msg.substr(start_pos + 5, end_pos - (start_pos + 5))); + ok(time < 20000, "Total duration is '%llu ms' should be less than 20 Seconds", time); + } + } + mysql_close(proxysql_admin); + return exit_status(); +}