Skip to content

Commit 3b4369b

Browse files
authored
Merge pull request #5113 from wazir-ahmed/load-from-config-validation
Add validation for `LOAD * FROM CONFIG`
2 parents 9c7111d + ec7383d commit 3b4369b

File tree

7 files changed

+678
-87
lines changed

7 files changed

+678
-87
lines changed

include/proxysql_config.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,35 @@
22
#define __PROXYSQL_CONFIG_H__
33

44
#include <string>
5+
#include <libconfig.h++>
56

67
class SQLite3DB;
78
extern const char* config_header;
89

10+
enum proxysql_config_type {
11+
PROXYSQL_CONFIG_MYSQL_USERS,
12+
PROXYSQL_CONFIG_PGSQL_USERS,
13+
PROXYSQL_CONFIG_MYSQL_SERVERS,
14+
PROXYSQL_CONFIG_PGSQL_SERVERS,
15+
PROXYSQL_CONFIG_PROXY_SERVERS,
16+
};
17+
918
class ProxySQL_Config {
1019
public:
1120
SQLite3DB* admindb;
1221
ProxySQL_Config(SQLite3DB* db);
1322
virtual ~ProxySQL_Config();
1423

1524
int Read_Global_Variables_from_configfile(const char *prefix);
16-
int Read_MySQL_Users_from_configfile();
25+
int Read_MySQL_Users_from_configfile(std::string& error);
1726
int Read_MySQL_Query_Rules_from_configfile();
18-
int Read_MySQL_Servers_from_configfile();
19-
int Read_PgSQL_Servers_from_configfile();
20-
int Read_PgSQL_Users_from_configfile();
27+
int Read_MySQL_Servers_from_configfile(std::string& error);
28+
int Read_PgSQL_Servers_from_configfile(std::string& error);
29+
int Read_PgSQL_Users_from_configfile(std::string& error);
2130
int Read_PgSQL_Query_Rules_from_configfile();
2231
int Read_Scheduler_from_configfile();
2332
int Read_Restapi_from_configfile();
24-
int Read_ProxySQL_Servers_from_configfile();
33+
int Read_ProxySQL_Servers_from_configfile(std::string& error);
2534

2635
void addField(std::string& data, const char* name, const char* value, const char* dq="\"");
2736
int Write_Global_Variables_to_configfile(std::string& data);
@@ -34,6 +43,11 @@ class ProxySQL_Config {
3443
int Write_Scheduler_to_configfile(std::string& data);
3544
int Write_Restapi_to_configfile(std::string& data);
3645
int Write_ProxySQL_Servers_to_configfile(std::string& data);
46+
47+
private:
48+
bool validate_backend_users(proxysql_config_type type, const libconfig::Setting& config, std::string& error);
49+
bool validate_backend_servers(proxysql_config_type type, const libconfig::Setting& config, std::string& error);
50+
bool validate_proxysql_servers(const libconfig::Setting& config, std::string& error);
3751
};
3852

3953
#endif

lib/Admin_Bootstrap.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -813,20 +813,23 @@ bool ProxySQL_Admin::init(const bootstrap_info_t& bootstrap_info) {
813813

814814
if (GloVars.__cmd_proxysql_reload || GloVars.__cmd_proxysql_initial || admindb_file_exists==false) { // see #617
815815
if (GloVars.configfile_open) {
816-
proxysql_config().Read_MySQL_Servers_from_configfile();
817-
proxysql_config().Read_MySQL_Users_from_configfile();
816+
// ignore validation errors during init
817+
std::string e;
818+
819+
proxysql_config().Read_MySQL_Servers_from_configfile(e);
820+
proxysql_config().Read_MySQL_Users_from_configfile(e);
818821
proxysql_config().Read_MySQL_Query_Rules_from_configfile();
819822
proxysql_config().Read_Global_Variables_from_configfile("admin");
820823
proxysql_config().Read_Global_Variables_from_configfile("mysql");
821824

822-
proxysql_config().Read_PgSQL_Servers_from_configfile();
823-
proxysql_config().Read_PgSQL_Users_from_configfile();
825+
proxysql_config().Read_PgSQL_Servers_from_configfile(e);
826+
proxysql_config().Read_PgSQL_Users_from_configfile(e);
824827
proxysql_config().Read_PgSQL_Query_Rules_from_configfile();
825828
proxysql_config().Read_Global_Variables_from_configfile("pgsql");
826829

827830
proxysql_config().Read_Scheduler_from_configfile();
828831
proxysql_config().Read_Restapi_from_configfile();
829-
proxysql_config().Read_ProxySQL_Servers_from_configfile();
832+
proxysql_config().Read_ProxySQL_Servers_from_configfile(e);
830833
__insert_or_replace_disktable_select_maintable();
831834
}
832835
}

lib/Admin_Handler.cpp

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,28 @@ bool admin_handler_command_proxysql(char *query_no_space, unsigned int query_no_
735735
return false;
736736
}
737737

738+
if (strncasecmp("PROXYSQL SET CONFIG FILE ", query_no_space, 25) == 0) {
739+
proxy_info("Received %s command\n", query_no_space);
740+
ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa;
741+
742+
char *file_path = trim_spaces_and_quotes_in_place(query_no_space + 25);
743+
744+
if (GloVars.configfile_open) {
745+
GloVars.confFile->CloseFile();
746+
}
747+
free(GloVars.config_file);
748+
749+
GloVars.config_file = strdup(file_path);
750+
if (GloVars.confFile->OpenFile(GloVars.config_file)) {
751+
GloVars.configfile_open = true;
752+
SPA->send_ok_msg_to_client(sess, NULL, 0, query_no_space);
753+
} else {
754+
SPA->send_error_msg_to_client(sess, "Invalid config file");
755+
}
756+
757+
return false;
758+
}
759+
738760
#ifndef NOJEM
739761
if (query_no_space_length==strlen("PROXYSQL MEMPROFILE START") && !strncasecmp("PROXYSQL MEMPROFILE START",query_no_space, query_no_space_length)) {
740762
bool en=true;
@@ -1306,14 +1328,28 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query
13061328
if (GloVars.confFile->OpenFile(NULL)==true) {
13071329
ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa;
13081330
int rows=0;
1331+
std::string msg, validation_err;
13091332
if (query_no_space[5] == 'P' || query_no_space[5] == 'p') {
1310-
rows=SPA->proxysql_config().Read_PgSQL_Users_from_configfile();
1311-
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded pgsql users from CONFIG\n");
1333+
rows = SPA->proxysql_config().Read_PgSQL_Users_from_configfile(validation_err);
1334+
if (rows < 0) {
1335+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Failed to load pgsql users from CONFIG due to validation error\n");
1336+
msg = "Configuration validation failed - " + validation_err;
1337+
SPA->send_error_msg_to_client(sess, msg.c_str());
1338+
} else {
1339+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded pgsql users from CONFIG\n");
1340+
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
1341+
}
13121342
} else {
1313-
rows=SPA->proxysql_config().Read_MySQL_Users_from_configfile();
1314-
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded mysql users from CONFIG\n");
1343+
rows = SPA->proxysql_config().Read_MySQL_Users_from_configfile(validation_err);
1344+
if (rows < 0) {
1345+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Failed to load mysql users from CONFIG due to validation error\n");
1346+
msg = "Configuration validation failed - " + validation_err;
1347+
SPA->send_error_msg_to_client(sess, msg.c_str());
1348+
} else {
1349+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded mysql users from CONFIG\n");
1350+
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
1351+
}
13151352
}
1316-
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
13171353
GloVars.confFile->CloseFile();
13181354
} else {
13191355
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Unable to open or parse config file %s\n", GloVars.config_file);
@@ -1707,14 +1743,28 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query
17071743
if (GloVars.confFile->OpenFile(NULL)==true) {
17081744
ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa;
17091745
int rows=0;
1746+
std::string msg, validation_err;
17101747
if (is_pgsql) {
1711-
rows=SPA->proxysql_config().Read_PgSQL_Servers_from_configfile();
1712-
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded pgsql servers from CONFIG\n");
1748+
rows = SPA->proxysql_config().Read_PgSQL_Servers_from_configfile(validation_err);
1749+
if (rows < 0) {
1750+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Failed to load pgsql servers from CONFIG due to validation error\n");
1751+
msg = "Configuration validation failed - " + validation_err;
1752+
SPA->send_error_msg_to_client(sess, msg.c_str());
1753+
} else {
1754+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded pgsql servers from CONFIG\n");
1755+
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
1756+
}
17131757
} else {
1714-
rows=SPA->proxysql_config().Read_MySQL_Servers_from_configfile();
1715-
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded mysql servers from CONFIG\n");
1758+
rows = SPA->proxysql_config().Read_MySQL_Servers_from_configfile(validation_err);
1759+
if (rows < 0) {
1760+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Failed to load mysql servers from CONFIG due to validation error\n");
1761+
msg = "Configuration validation failed - " + validation_err;
1762+
SPA->send_error_msg_to_client(sess, msg.c_str());
1763+
} else {
1764+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded mysql servers from CONFIG\n");
1765+
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
1766+
}
17161767
}
1717-
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
17181768
GloVars.confFile->CloseFile();
17191769
} else {
17201770
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Unable to open or parse config file %s\n", GloVars.config_file);
@@ -1829,9 +1879,16 @@ bool admin_handler_command_load_or_save(char *query_no_space, unsigned int query
18291879
if (GloVars.confFile->OpenFile(NULL)==true) {
18301880
ProxySQL_Admin *SPA=(ProxySQL_Admin *)pa;
18311881
int rows=0;
1832-
rows=SPA->proxysql_config().Read_ProxySQL_Servers_from_configfile();
1833-
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded ProxySQL servers from CONFIG\n");
1834-
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
1882+
std::string msg, validation_err;
1883+
rows = SPA->proxysql_config().Read_ProxySQL_Servers_from_configfile(validation_err);
1884+
if (rows < 0) {
1885+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Failed to load ProxySQL servers from CONFIG due to validation error\n");
1886+
msg = "Configuration validation failed - " + validation_err;
1887+
SPA->send_error_msg_to_client(sess, msg.c_str());
1888+
} else {
1889+
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Loaded ProxySQL servers from CONFIG\n");
1890+
SPA->send_ok_msg_to_client(sess, NULL, rows, query_no_space);
1891+
}
18351892
GloVars.confFile->CloseFile();
18361893
} else {
18371894
proxy_debug(PROXY_DEBUG_ADMIN, 4, "Unable to open or parse config file %s\n", GloVars.config_file);

0 commit comments

Comments
 (0)