Drafting again support for ClickHouse

Introduced new ClickHouse Server module
Introduced new ClickHouse Authentication module

None of the two new modules are working yet: only initialized.
pull/1175/head
René Cannaò 9 years ago
parent 983dc5d111
commit b57ff42b9c

@ -0,0 +1,83 @@
#ifndef CLASS_PROXYSQL_CLICKHOUSE_AUTHENTICATION_H
#define CLASS_PROXYSQL_CLICKHOUSE_AUTHENTICATION_H
#include "proxysql.h"
#include "cpp.h"
#define PROXYSQL_AUTH_PTHREAD_MUTEX
#ifndef ACCOUNT_DETAILS_T
#define ACCOUNT_DETAILS_T
typedef struct _account_details_t {
char *username;
char *password;
void *sha1_pass;
bool use_ssl;
int default_hostgroup;
char *default_schema;
bool schema_locked;
bool transaction_persistent;
bool fast_forward;
int max_connections;
int num_connections_used;
bool __frontend; // this is used only during the dump
bool __backend; // this is used only during the dump
bool __active;
} account_details_t;
typedef std::map<uint64_t, account_details_t *> umap_auth;
#endif // ACCOUNT_DETAILS_T
#ifdef DEBUG
#define DEB "_DEBUG"
#else
#define DEB ""
#endif /* DEBUG */
#define PROXYSQL_CLICKHOUSE_AUTHENTICATION_VERSION "0.1.0702" DEB
class PtrArray;
#ifndef CREDS_GROUPS_T
#define CREDS_GROUPS_T
typedef struct _creds_group_t {
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_t lock;
#else
rwlock_t lock;
#endif
umap_auth bt_map;
PtrArray *cred_array;
} creds_group_t;
#endif // CREDS_GROUPS_T
class ClickHouse_Authentication {
private:
creds_group_t creds_backends;
creds_group_t creds_frontends;
bool _reset(enum cred_username_type usertype);
public:
ClickHouse_Authentication();
~ClickHouse_Authentication();
bool add(char *username, char *password, enum cred_username_type usertype,
bool use_ssl, int default_hostgroup, char *default_schema,
bool schema_locked, bool transaction_persistent, bool fast_forward,
int max_connections);
bool del(char *username, enum cred_username_type usertype,
bool set_lock = true);
bool reset();
void print_version();
char *lookup(char *username, enum cred_username_type usertype,
bool *use_ssl, int *default_hostgroup, char **default_schema,
bool *schema_locked, bool *transaction_persistent,
bool *fast_forward, int *max_connections, void **sha1_pass);
int dump_all_users(account_details_t ***, bool _complete = true);
int increase_frontend_user_connections(char *username, int *mc = NULL);
void decrease_frontend_user_connections(char *username);
void set_all_inactive(enum cred_username_type usertype);
void remove_inactives(enum cred_username_type usertype);
bool set_SHA1(char *username, enum cred_username_type usertype,
void *sha_pass);
};
#endif // CLASS_PROXYSQL_CLICKHOUSE_AUTHENTICATION_H

@ -0,0 +1,207 @@
#ifndef CLASS_PROXYSQL_CLICKHOUSE_SERVER_H
#define CLASS_PROXYSQL_CLICKHOUSE_SERVER_H
#include "proxy_defines.h"
#include "proxysql.h"
#include "cpp.h"
#include <vector>
class ClickHouse_Session {
public:
SQLite3DB *sessdb;
ClickHouse_Session();
~ClickHouse_Session();
};
class ClickHouse_Server {
private:
volatile int main_shutdown;
SQLite3DB *SQLite_General_DB;
/*
std::vector<table_def_t *> *tables_defs_admin;
std::vector<table_def_t *> *tables_defs_stats;
std::vector<table_def_t *> *tables_defs_config;
pthread_t admin_thr;
*/
int main_poll_nfds;
struct pollfd *main_poll_fds;
int *main_callback_func;
pthread_rwlock_t rwlock;
void wrlock();
void wrunlock();
struct {
// char *admin_credentials;
// char *stats_credentials;
// int refresh_interval;
char *mysql_ifaces;
// char *telnet_admin_ifaces;
// char *telnet_stats_ifaces;
bool read_only;
// bool hash_passwords;
char *version;
#ifdef DEBUG
bool debug;
#endif // DEBUG
} variables;
/*
void dump_mysql_collations();
void insert_into_tables_defs(std::vector<table_def_t *> *, const char
*table_name, const char *table_def);
void drop_tables_defs(std::vector<table_def_t *> *tables_defs);
void check_and_build_standard_tables(SQLite3DB *db,
std::vector<table_def_t *> *tables_defs);
#ifdef DEBUG
void flush_debug_levels_runtime_to_database(SQLite3DB *db, bool
replace);
int flush_debug_levels_database_to_runtime(SQLite3DB *db);
#endif // DEBUG
void __insert_or_ignore_maintable_select_disktable();
void __insert_or_replace_maintable_select_disktable();
void __delete_disktable();
void __insert_or_replace_disktable_select_maintable();
void __attach_db(SQLite3DB *db1, SQLite3DB *db2, char *alias);
void __add_active_users(enum cred_username_type usertype, char
*user=NULL);
void __delete_inactive_users(enum cred_username_type usertype);
void add_admin_users();
void __refresh_users();
void flush_mysql_variables___runtime_to_database(SQLite3DB *db, bool
replace, bool del, bool onlyifempty, bool runtime=false);
void flush_mysql_variables___database_to_runtime(SQLite3DB *db, bool
replace);
*/
char **get_variables_list();
char *get_variable(char *name);
bool set_variable(char *name, char *value);
/*
void flush_admin_variables___database_to_runtime(SQLite3DB *db, bool
replace);
void flush_admin_variables___runtime_to_database(SQLite3DB *db, bool
replace, bool del, bool onlyifempty, bool runtime=false);
void disk_upgrade_mysql_query_rules();
void disk_upgrade_mysql_servers();
void disk_upgrade_mysql_users();
void disk_upgrade_scheduler();
#ifdef DEBUG
void add_credentials(char *type, char *credentials, int hostgroup_id);
void delete_credentials(char *type, char *credentials);
#else
void add_credentials(char *credentials, int hostgroup_id);
void delete_credentials(char *credentials);
#endif // DEBUG
*/
public:
ClickHouse_Server();
~ClickHouse_Server();
/*
struct {
void *opt;
void **re;
} match_regexes;
void public_add_active_users(enum cred_username_type usertype, char
*user=NULL) {
__add_active_users(usertype, user);
}
ProxySQL_Admin();
~ProxySQL_Admin();
SQLite3DB *admindb; // in memory
SQLite3DB *statsdb; // in memory
SQLite3DB *configdb; // on disk
SQLite3DB *monitordb; // in memory
int pipefd[2];
*/
void print_version();
bool init();
/*
bool get_read_only() { return variables.admin_read_only; }
bool set_read_only(bool ro) { variables.admin_read_only=ro; return
variables.admin_read_only; }
bool has_variable(const char *name);
void init_users();
void init_mysql_servers();
void init_mysql_query_rules();
void save_mysql_users_runtime_to_database(bool _runtime);
void save_mysql_servers_runtime_to_database(bool);
void admin_shutdown();
bool is_command(std::string);
*/
void send_MySQL_OK(MySQL_Protocol *myprot, char *msg, int rows = 0);
void send_MySQL_ERR(MySQL_Protocol *myprot, char *msg);
/*
#ifdef DEBUG
int load_debug_to_runtime() { return
flush_debug_levels_database_to_runtime(admindb); }
void save_debug_from_runtime() { return
flush_debug_levels_runtime_to_database(admindb, true); }
#endif // DEBUG
void flush_mysql_users__from_memory_to_disk();
void flush_mysql_users__from_disk_to_memory();
void flush_mysql_servers__from_memory_to_disk();
void flush_mysql_servers__from_disk_to_memory();
void flush_mysql_query_rules__from_memory_to_disk();
void flush_mysql_query_rules__from_disk_to_memory();
void load_mysql_servers_to_runtime();
void save_mysql_servers_from_runtime();
char * load_mysql_query_rules_to_runtime();
void save_mysql_query_rules_from_runtime(bool);
void load_scheduler_to_runtime();
void save_scheduler_runtime_to_database(bool);
void flush_scheduler__from_memory_to_disk();
void flush_scheduler__from_disk_to_memory();
void load_admin_variables_to_runtime() {
flush_admin_variables___database_to_runtime(admindb, true); }
void save_admin_variables_from_runtime() {
flush_admin_variables___runtime_to_database(admindb, true, true, false); }
void load_mysql_variables_to_runtime() {
flush_mysql_variables___database_to_runtime(admindb, true); }
void save_mysql_variables_from_runtime() {
flush_mysql_variables___runtime_to_database(admindb, true, true, false); }
void stats___mysql_query_rules();
void stats___mysql_query_digests(bool reset);
//void stats___mysql_query_digests_reset();
void stats___mysql_commands_counters();
void stats___mysql_processlist();
void stats___mysql_connection_pool(bool _reset);
void stats___mysql_global();
void stats___mysql_users();
int Read_Global_Variables_from_configfile(const char *prefix);
int Read_MySQL_Users_from_configfile();
int Read_MySQL_Query_Rules_from_configfile();
int Read_MySQL_Servers_from_configfile();
int Read_Scheduler_from_configfile();
void flush_error_log();
void GenericRefreshStatistics(const char *query_no_space, unsigned int
query_no_space_length, bool admin);
SQLite3_result * generate_show_table_status(const char *, char **err);
SQLite3_result * generate_show_fields_from(const char *tablename, char
**err);
void mysql_servers_wrlock();
void mysql_servers_wrunlock();
// wrapper to call a private function
unsigned long long scheduler_run_once() { return scheduler->run_once();
}
void flush_configdb(); // 923
*/
};
#endif // CLASS_PROXYSQL_CLICKHOUSE_SERVER_H

@ -6,6 +6,8 @@
#define PROXYSQL_AUTH_PTHREAD_MUTEX
#ifndef ACCOUNT_DETAILS_T
#define ACCOUNT_DETAILS_T
typedef struct _account_details_t {
char *username;
char *password;
@ -23,6 +25,9 @@ typedef struct _account_details_t {
bool __active;
} account_details_t;
typedef std::map<uint64_t, account_details_t *> umap_auth;
#endif // ACCOUNT_DETAILS_T
#ifdef DEBUG
#define DEB "_DEBUG"
#else
@ -30,10 +35,11 @@ typedef struct _account_details_t {
#endif /* DEBUG */
#define MYSQL_AUTHENTICATION_VERSION "0.2.0902" DEB
typedef std::map<uint64_t, account_details_t *> umap_auth;
class PtrArray;
#ifndef CREDS_GROUPS_T
#define CREDS_GROUPS_T
typedef struct _creds_group_t {
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_t lock;
@ -43,6 +49,7 @@ typedef struct _creds_group_t {
umap_auth bt_map;
PtrArray *cred_array;
} creds_group_t;
#endif // CREDS_GROUPS_T
class MySQL_Authentication {
private:

@ -10,11 +10,13 @@
#include "MySQL_Monitor.hpp"
#include "MySQL_Protocol.h"
#include "MySQL_Authentication.hpp"
#include "ClickHouse_Authentication.hpp"
#include "fileutils.hpp"
#include "configfile.hpp"
#include "query_processor.h"
#include "proxysql_admin.h"
#include "SQLite3_Server.h"
#include "ClickHouse_Server.h"
#include "MySQL_HostGroups_Manager.h"
#include "MySQL_Logger.hpp"
#include "MySQL_PreparedStatement.h"

@ -75,7 +75,9 @@ class ProxySQL_GlobalVariables {
char *pidfile;
bool restart_on_error;
int restart_delay;
SSL_CTX *ssl_ctx;
SSL_CTX *ssl_ctx;
bool sqlite3_server;
bool clickhouse_server;
} global;
struct mysql {
char *server_version;

@ -0,0 +1,435 @@
#include "btree_map.h"
#include "proxysql.h"
#include "cpp.h"
#include "proxysql_atomic.h"
#include "SpookyV2.h"
ClickHouse_Authentication::ClickHouse_Authentication() {
#ifdef DEBUG
if (glovars.has_debug==false) {
#else
if (glovars.has_debug==true) {
#endif /* DEBUG */
perror("Incompatible debagging version");
exit(EXIT_FAILURE);
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_init(&creds_backends.lock, NULL);
pthread_rwlock_init(&creds_frontends.lock, NULL);
#else
spinlock_rwlock_init(&creds_backends.lock);
spinlock_rwlock_init(&creds_frontends.lock);
#endif
creds_backends.cred_array = new PtrArray();
creds_frontends.cred_array = new PtrArray();
};
ClickHouse_Authentication::~ClickHouse_Authentication() {
reset();
delete creds_backends.cred_array;
delete creds_frontends.cred_array;
};
void ClickHouse_Authentication::print_version() {
fprintf(stderr,"Standard ProxySQL ClickHouse Authentication rev. %s -- %s -- %s\n", PROXYSQL_CLICKHOUSE_AUTHENTICATION_VERSION, __FILE__, __TIMESTAMP__);
};
void ClickHouse_Authentication::set_all_inactive(enum cred_username_type usertype) {
creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
unsigned int i;
for (i=0; i<cg.cred_array->len; i++) {
account_details_t *ado=(account_details_t *)cg.cred_array->index(i);
ado->__active=false;
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
}
void ClickHouse_Authentication::remove_inactives(enum cred_username_type usertype) {
creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
unsigned int i;
__loop_remove_inactives:
for (i=0; i<cg.cred_array->len; i++) {
account_details_t *ado=(account_details_t *)cg.cred_array->index(i);
if (ado->__active==false) {
del(ado->username,usertype,false);
goto __loop_remove_inactives; // we aren't sure how the underlying structure changes, so we jump back to 0
}
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
}
bool ClickHouse_Authentication::add(char * username, char * password, enum cred_username_type usertype, bool use_ssl, int default_hostgroup, char *default_schema, bool schema_locked, bool transaction_persistent, bool fast_forward, int max_connections) {
uint64_t hash1, hash2;
SpookyHash myhash;
myhash.Init(1,2);
myhash.Update(username,strlen(username));
myhash.Final(&hash1,&hash2);
creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator lookup;
lookup = cg.bt_map.find(hash1);
// few changes will follow, due to issue #802
account_details_t *ad=NULL;
bool new_ad=false;
if (lookup != cg.bt_map.end()) {
ad=lookup->second;
if (strcmp(ad->password,password)) {
free(ad->password);
ad->password=strdup(password);
if (ad->sha1_pass) {
free(ad->sha1_pass);
ad->sha1_pass=NULL;
}
}
if (strcmp(ad->default_schema,default_schema)) {
free(ad->default_schema);
ad->default_schema=strdup(default_schema);
}
} else {
ad=(account_details_t *)malloc(sizeof(account_details_t));
ad->username=strdup(username);
ad->default_schema=strdup(default_schema);
ad->password=strdup(password);
new_ad=true;
ad->sha1_pass=NULL;
ad->num_connections_used=0;
}
ad->use_ssl=use_ssl;
ad->default_hostgroup=default_hostgroup;
ad->schema_locked=schema_locked;
ad->transaction_persistent=transaction_persistent;
ad->fast_forward=fast_forward;
ad->max_connections=max_connections;
ad->__active=true;
if (new_ad) {
cg.bt_map.insert(std::make_pair(hash1,ad));
cg.cred_array->add(ad);
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
return true;
};
int ClickHouse_Authentication::dump_all_users(account_details_t ***ads, bool _complete) {
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_rdlock(&creds_frontends.lock);
pthread_rwlock_rdlock(&creds_backends.lock);
#else
spin_rdlock(&creds_frontends.lock);
spin_rdlock(&creds_backends.lock);
#endif
int total_size;
int idx_=0;
unsigned i=0;
account_details_t **_ads;
total_size=creds_frontends.cred_array->len;
if (_complete) {
total_size+=creds_backends.cred_array->len;
}
if (!total_size) goto __exit_dump_all_users;
_ads=(account_details_t **)malloc(sizeof(account_details_t *)*total_size);
for (i=0; i<creds_frontends.cred_array->len; i++) {
account_details_t *ad=(account_details_t *)malloc(sizeof(account_details_t));
account_details_t *ado=(account_details_t *)creds_frontends.cred_array->index(i);
ad->username=strdup(ado->username);
ad->max_connections=ado->max_connections;
ad->default_hostgroup=ado->default_hostgroup;
if (_complete==false) {
ad->password=NULL;
ad->default_schema=NULL;
ad->num_connections_used=ado->num_connections_used;
} else {
ad->num_connections_used=ado->num_connections_used;
ad->password=strdup(ado->password);
ad->default_schema=strdup(ado->default_schema);
ad->sha1_pass=NULL;
ad->use_ssl=ado->use_ssl;
ad->default_schema=strdup(ado->default_schema);
ad->schema_locked=ado->schema_locked;
ad->transaction_persistent=ado->transaction_persistent;
ad->fast_forward=ado->fast_forward;
ad->__frontend=1;
ad->__backend=0;
}
_ads[idx_]=ad;
idx_++;
}
if (_complete==true) {
for (i=0; i<creds_backends.cred_array->len; i++) {
account_details_t *ad=(account_details_t *)malloc(sizeof(account_details_t));
account_details_t *ado=(account_details_t *)creds_backends.cred_array->index(i);
ad->num_connections_used=0;
ad->username=strdup(ado->username);
ad->password=strdup(ado->password);
ad->sha1_pass=NULL;
ad->use_ssl=ado->use_ssl;
ad->default_hostgroup=ado->default_hostgroup;
ad->default_schema=strdup(ado->default_schema);
ad->schema_locked=ado->schema_locked;
ad->transaction_persistent=ado->transaction_persistent;
ad->fast_forward=ado->fast_forward;
ad->max_connections=ado->max_connections;
ad->__frontend=0;
ad->__backend=1;
_ads[idx_]=ad;
idx_++;
}
}
*ads=_ads;
__exit_dump_all_users:
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&creds_frontends.lock);
pthread_rwlock_unlock(&creds_backends.lock);
#else
spin_rdunlock(&creds_frontends.lock);
spin_rdunlock(&creds_backends.lock);
#endif
return total_size;
}
int ClickHouse_Authentication::increase_frontend_user_connections(char *username, int *mc) {
uint64_t hash1, hash2;
SpookyHash *myhash=new SpookyHash();
myhash->Init(1,2);
myhash->Update(username,strlen(username));
myhash->Final(&hash1,&hash2);
delete myhash;
creds_group_t &cg=creds_frontends;
int ret=0;
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator it;
it = cg.bt_map.find(hash1);
if (it != cg.bt_map.end()) {
account_details_t *ad=it->second;
if (ad->max_connections > ad->num_connections_used) {
ret=ad->max_connections-ad->num_connections_used;
ad->num_connections_used++;
}
if (mc) {
*mc=ad->max_connections;
}
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
return ret;
}
void ClickHouse_Authentication::decrease_frontend_user_connections(char *username) {
uint64_t hash1, hash2;
SpookyHash *myhash=new SpookyHash();
myhash->Init(1,2);
myhash->Update(username,strlen(username));
myhash->Final(&hash1,&hash2);
delete myhash;
creds_group_t &cg=creds_frontends;
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator it;
it = cg.bt_map.find(hash1);
if (it != cg.bt_map.end()) {
account_details_t *ad=it->second;
if (ad->num_connections_used > 0) {
ad->num_connections_used--;
}
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
}
bool ClickHouse_Authentication::del(char * username, enum cred_username_type usertype, bool set_lock) {
bool ret=false;
uint64_t hash1, hash2;
SpookyHash *myhash=new SpookyHash();
myhash->Init(1,2);
myhash->Update(username,strlen(username));
myhash->Final(&hash1,&hash2);
delete myhash;
creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);
if (set_lock)
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator lookup;
lookup = cg.bt_map.find(hash1);
if (lookup != cg.bt_map.end()) {
account_details_t *ad=lookup->second;
cg.cred_array->remove_fast(ad);
cg.bt_map.erase(lookup);
free(ad->username);
free(ad->password);
if (ad->sha1_pass) { free(ad->sha1_pass); ad->sha1_pass=NULL; }
free(ad->default_schema);
free(ad);
ret=true;
}
if (set_lock)
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
return ret;
};
bool ClickHouse_Authentication::set_SHA1(char * username, enum cred_username_type usertype, void *sha_pass) {
bool ret=false;
uint64_t hash1, hash2;
SpookyHash *myhash=new SpookyHash();
myhash->Init(1,2);
myhash->Update(username,strlen(username));
myhash->Final(&hash1,&hash2);
delete myhash;
creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator lookup;
lookup = cg.bt_map.find(hash1);
if (lookup != cg.bt_map.end()) {
account_details_t *ad=lookup->second;
if (ad->sha1_pass) { free(ad->sha1_pass); ad->sha1_pass=NULL; }
if (sha_pass) {
ad->sha1_pass=malloc(SHA_DIGEST_LENGTH);
memcpy(ad->sha1_pass,sha_pass,SHA_DIGEST_LENGTH);
}
ret=true;
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
return ret;
};
char * ClickHouse_Authentication::lookup(char * username, enum cred_username_type usertype, bool *use_ssl, int *default_hostgroup, char **default_schema, bool *schema_locked, bool *transaction_persistent, bool *fast_forward, int *max_connections, void **sha1_pass) {
char *ret=NULL;
uint64_t hash1, hash2;
SpookyHash myhash;
myhash.Init(1,2);
myhash.Update(username,strlen(username));
myhash.Final(&hash1,&hash2);
creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_rdlock(&cg.lock);
#else
spin_rdlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator lookup;
lookup = cg.bt_map.find(hash1);
if (lookup != cg.bt_map.end()) {
account_details_t *ad=lookup->second;
ret=l_strdup(ad->password);
if (use_ssl) *use_ssl=ad->use_ssl;
if (default_hostgroup) *default_hostgroup=ad->default_hostgroup;
if (default_schema) *default_schema=l_strdup(ad->default_schema);
if (schema_locked) *schema_locked=ad->schema_locked;
if (transaction_persistent) *transaction_persistent=ad->transaction_persistent;
if (fast_forward) *fast_forward=ad->fast_forward;
if (max_connections) *max_connections=ad->max_connections;
if (sha1_pass) {
if (ad->sha1_pass) {
*sha1_pass=malloc(SHA_DIGEST_LENGTH);
memcpy(*sha1_pass,ad->sha1_pass,SHA_DIGEST_LENGTH);
}
}
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_rdunlock(&cg.lock);
#endif
return ret;
}
bool ClickHouse_Authentication::_reset(enum cred_username_type usertype) {
creds_group_t &cg=(usertype==USERNAME_BACKEND ? creds_backends : creds_frontends);
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_wrlock(&cg.lock);
#else
spin_wrlock(&cg.lock);
#endif
std::map<uint64_t, account_details_t *>::iterator lookup;
while (cg.bt_map.size()) {
lookup = cg.bt_map.begin();
if ( lookup != cg.bt_map.end() ) {
account_details_t *ad=lookup->second;
cg.bt_map.erase(lookup);
free(ad->username);
free(ad->password);
if (ad->sha1_pass) { free(ad->sha1_pass); ad->sha1_pass=NULL; }
free(ad->default_schema);
free(ad);
}
}
while (cg.cred_array->len) {
cg.cred_array->remove_index_fast(0);
}
#ifdef PROXYSQL_AUTH_PTHREAD_MUTEX
pthread_rwlock_unlock(&cg.lock);
#else
spin_wrunlock(&cg.lock);
#endif
return true;
};
bool ClickHouse_Authentication::reset() {
_reset(USERNAME_BACKEND);
_reset(USERNAME_FRONTEND);
return true;
}

File diff suppressed because it is too large Load Diff

@ -61,7 +61,7 @@ default: libproxysql.a
_OBJ = c_tokenizer.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo SQLite3_Server.oo
_OBJ_CXX = ProxySQL_GloVars.oo network.oo debug.oo configfile.oo Query_Cache.oo SpookyV2.oo MySQL_Authentication.oo gen_utils.oo sqlite3db.oo mysql_connection.oo MySQL_HostGroups_Manager.oo mysql_data_stream.oo MySQL_Thread.oo MySQL_Session.oo MySQL_Protocol.oo mysql_backend.oo Query_Processor.oo ProxySQL_Admin.oo MySQL_Monitor.oo MySQL_Logger.oo thread.oo MySQL_PreparedStatement.oo ProxySQL_Cluster.oo SQLite3_Server.oo ClickHouse_Authentication.oo ClickHouse_Server.oo
OBJ_CXX = $(patsubst %,$(ODIR)/%,$(_OBJ_CXX))
%.ko: %.cpp

@ -1,4 +1,4 @@
#include "btree_map.h"
//#include "btree_map.h"
#include "proxysql.h"
#include "cpp.h"
#include "proxysql_atomic.h"

@ -4,6 +4,8 @@
extern MySQL_Authentication *GloMyAuth;
extern MySQL_Threads_Handler *GloMTH;
extern ClickHouse_Authentication *GloClickHouseAuth;
#ifdef max_allowed_packet
#undef max_allowed_packet
#endif
@ -1090,7 +1092,12 @@ bool MySQL_Protocol::process_pkt_auth_swich_response(unsigned char *pkt, unsigne
char reply[SHA_DIGEST_LENGTH+1];
reply[SHA_DIGEST_LENGTH]='\0';
void *sha1_pass=NULL;
password=GloMyAuth->lookup((char *)userinfo->username, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, NULL, NULL, &transaction_persistent, NULL, NULL, &sha1_pass);
enum proxysql_session_type session_type = (*myds)->sess->session_type;
if (session_type == PROXYSQL_SESSION_CLICKHOUSE) {
password=GloClickHouseAuth->lookup((char *)userinfo->username, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, NULL, NULL, &transaction_persistent, NULL, NULL, &sha1_pass);
} else {
password=GloMyAuth->lookup((char *)userinfo->username, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, NULL, NULL, &transaction_persistent, NULL, NULL, &sha1_pass);
}
// FIXME: add support for default schema and fast forward , issues #255 and #256
if (password==NULL) {
ret=false;
@ -1147,7 +1154,12 @@ bool MySQL_Protocol::process_pkt_COM_CHANGE_USER(unsigned char *pkt, unsigned in
cur+=pass_len;
db=(char *)pkt+cur;
void *sha1_pass=NULL;
password=GloMyAuth->lookup((char *)user, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, NULL, NULL, &transaction_persistent, NULL, NULL, &sha1_pass);
enum proxysql_session_type session_type = (*myds)->sess->session_type;
if (session_type == PROXYSQL_SESSION_CLICKHOUSE) {
password=GloClickHouseAuth->lookup((char *)user, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, NULL, NULL, &transaction_persistent, NULL, NULL, &sha1_pass);
} else {
password=GloMyAuth->lookup((char *)user, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, NULL, NULL, &transaction_persistent, NULL, NULL, &sha1_pass);
}
// FIXME: add support for default schema and fast forward, see issue #255 and #256
(*myds)->sess->default_hostgroup=default_hostgroup;
(*myds)->sess->transaction_persistent=transaction_persistent;
@ -1163,6 +1175,7 @@ bool MySQL_Protocol::process_pkt_COM_CHANGE_USER(unsigned char *pkt, unsigned in
ret=true;
}
} else {
if (session_type == PROXYSQL_SESSION_MYSQL) {
ret=proxy_scramble_sha1((char *)pass,(*myds)->myconn->scramble_buff,password+1, reply);
if (ret) {
if (sha1_pass==NULL) {
@ -1173,6 +1186,7 @@ bool MySQL_Protocol::process_pkt_COM_CHANGE_USER(unsigned char *pkt, unsigned in
userinfo->sha1_pass=sha1_pass_hex(reply);
}
}
}
}
if (_ret_use_ssl==true) {
// if we reached here, use_ssl is false , but _ret_use_ssl is true
@ -1259,7 +1273,12 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned
bool transaction_persistent;
bool fast_forward;
int max_connections;
password=GloMyAuth->lookup((char *)user, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, &default_schema, &schema_locked, &transaction_persistent, &fast_forward, &max_connections, &sha1_pass);
enum proxysql_session_type session_type = (*myds)->sess->session_type;
if (session_type == PROXYSQL_SESSION_CLICKHOUSE) {
password=GloClickHouseAuth->lookup((char *)user, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, &default_schema, &schema_locked, &transaction_persistent, &fast_forward, &max_connections, &sha1_pass);
} else {
password=GloMyAuth->lookup((char *)user, USERNAME_FRONTEND, &_ret_use_ssl, &default_hostgroup, &default_schema, &schema_locked, &transaction_persistent, &fast_forward, &max_connections, &sha1_pass);
}
//assert(default_hostgroup>=0);
(*myds)->sess->default_hostgroup=default_hostgroup;
(*myds)->sess->default_schema=default_schema; // just the pointer is passed
@ -1302,14 +1321,16 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned
ret=true;
}
} else {
ret=proxy_scramble_sha1((char *)pass,(*myds)->myconn->scramble_buff,password+1, reply);
if (ret) {
if (sha1_pass==NULL) {
// currently proxysql doesn't know any sha1_pass for that specific user, let's set it!
GloMyAuth->set_SHA1((char *)user, USERNAME_FRONTEND,reply);
if (session_type == PROXYSQL_SESSION_MYSQL) {
ret=proxy_scramble_sha1((char *)pass,(*myds)->myconn->scramble_buff,password+1, reply);
if (ret) {
if (sha1_pass==NULL) {
// currently proxysql doesn't know any sha1_pass for that specific user, let's set it!
GloMyAuth->set_SHA1((char *)user, USERNAME_FRONTEND,reply);
}
if (userinfo->sha1_pass) free(userinfo->sha1_pass);
userinfo->sha1_pass=sha1_pass_hex(reply);
}
if (userinfo->sha1_pass) free(userinfo->sha1_pass);
userinfo->sha1_pass=sha1_pass_hex(reply);
}
}
}

@ -28,6 +28,8 @@ extern MySQL_STMT_Manager_v14 *GloMyStmt;
extern SQLite3_Server *GloSQLite3Server;
extern ClickHouse_Authentication *GloClickHouseAuth;
Session_Regex::Session_Regex(char *p) {
s=strdup(p);
re2::RE2::Options *opt2=new re2::RE2::Options(RE2::Quiet);
@ -317,7 +319,14 @@ MySQL_Session::~MySQL_Session() {
if (client_myds) {
if (client_authenticated) {
GloMyAuth->decrease_frontend_user_connections(client_myds->myconn->userinfo->username);
switch (session_type) {
case PROXYSQL_SESSION_CLICKHOUSE:
GloClickHouseAuth->decrease_frontend_user_connections(client_myds->myconn->userinfo->username);
break;
default:
GloMyAuth->decrease_frontend_user_connections(client_myds->myconn->userinfo->username);
break;
}
}
delete client_myds;
}
@ -3061,9 +3070,19 @@ void MySQL_Session::handler___status_CONNECTING_CLIENT___STATE_SERVER_HANDSHAKE(
}
int free_users=0;
int used_users=0;
if (session_type == PROXYSQL_SESSION_MYSQL) {
if (session_type == PROXYSQL_SESSION_MYSQL || session_type == PROXYSQL_SESSION_CLICKHOUSE) {
client_authenticated=true;
free_users=GloMyAuth->increase_frontend_user_connections(client_myds->myconn->userinfo->username, &used_users);
switch (session_type) {
case PROXYSQL_SESSION_MYSQL:
free_users=GloMyAuth->increase_frontend_user_connections(client_myds->myconn->userinfo->username, &used_users);
break;
case PROXYSQL_SESSION_CLICKHOUSE:
free_users=GloClickHouseAuth->increase_frontend_user_connections(client_myds->myconn->userinfo->username, &used_users);
break;
default:
assert(0);
break;
}
} else {
free_users=1;
}

@ -142,6 +142,8 @@ extern MySQL_STMT_Manager_v14 *GloMyStmt;
extern MySQL_Monitor *GloMyMon;
extern ProxySQL_Cluster *GloProxyCluster;
extern ClickHouse_Authentication *GloClickHouseAuth;
extern ClickHouse_Server *GloClickHouseServer;
#define PANIC(msg) { perror(msg); exit(EXIT_FAILURE); }
@ -266,6 +268,15 @@ pthread_mutex_t users_mutex = PTHREAD_MUTEX_INITIALIZER;
#define STATS_SQLITE_TABLE_PROXYSQL_SERVERS_CHECKSUMS "CREATE TABLE stats_proxysql_servers_checksums (hostname VARCHAR NOT NULL , port INT NOT NULL DEFAULT 6032 , name VARCHAR NOT NULL , version INT NOT NULL , epoch INT NOT NULL , checksum VARCHAR NOT NULL , changed_at INT NOT NULL , updated_at INT NOT NULL , diff_check INT NOT NULL , PRIMARY KEY (hostname, port, name) )"
// ClickHouse Tables
#define ADMIN_SQLITE_TABLE_CLICKHOUSE_USERS_141 "CREATE TABLE clickhouse_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , server VARCHAR , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , PRIMARY KEY (username))"
#define ADMIN_SQLITE_TABLE_CLICKHOUSE_USERS ADMIN_SQLITE_TABLE_CLICKHOUSE_USERS_141
#define ADMIN_SQLITE_TABLE_RUNTIME_CLICKHOUSE_USERS "CREATE TABLE runtime_clickhouse_users (username VARCHAR NOT NULL , password VARCHAR , active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1 , server VARCHAR , max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000 , PRIMARY KEY (username))"
static char * admin_variables_names[]= {
@ -2958,6 +2969,11 @@ bool ProxySQL_Admin::init() {
#ifdef DEBUG
insert_into_tables_defs(tables_defs_admin,"debug_levels", ADMIN_SQLITE_TABLE_DEBUG_LEVELS);
#endif /* DEBUG */
// ClickHouse
if (GloVars.global.clickhouse_server) {
insert_into_tables_defs(tables_defs_admin,"clickhouse_users", ADMIN_SQLITE_TABLE_CLICKHOUSE_USERS);
insert_into_tables_defs(tables_defs_admin,"runtime_clickhouse_users", ADMIN_SQLITE_TABLE_RUNTIME_CLICKHOUSE_USERS);
}
insert_into_tables_defs(tables_defs_config,"mysql_servers", ADMIN_SQLITE_TABLE_MYSQL_SERVERS);
insert_into_tables_defs(tables_defs_config,"mysql_users", ADMIN_SQLITE_TABLE_MYSQL_USERS);
@ -2971,7 +2987,10 @@ bool ProxySQL_Admin::init() {
#ifdef DEBUG
insert_into_tables_defs(tables_defs_config,"debug_levels", ADMIN_SQLITE_TABLE_DEBUG_LEVELS);
#endif /* DEBUG */
// ClickHouse
if (GloVars.global.clickhouse_server) {
insert_into_tables_defs(tables_defs_config,"clickhouse_users", ADMIN_SQLITE_TABLE_CLICKHOUSE_USERS);
}
insert_into_tables_defs(tables_defs_stats,"stats_mysql_query_rules", STATS_SQLITE_TABLE_MYSQL_QUERY_RULES);
insert_into_tables_defs(tables_defs_stats,"stats_mysql_commands_counters", STATS_SQLITE_TABLE_MYSQL_COMMANDS_COUNTERS);

@ -73,6 +73,9 @@ ProxySQL_GlobalVariables::ProxySQL_GlobalVariables() {
#ifdef DEBUG
global.gdb=0;
#endif
global.sqlite3_server=false;
global.clickhouse_server=false;
opt=new ez::ezOptionParser();
opt->overview="High Performance Advanced Proxy for MySQL";
opt->syntax="proxysql [OPTIONS]";
@ -101,6 +104,9 @@ ProxySQL_GlobalVariables::ProxySQL_GlobalVariables() {
#endif /* IDLE_THREADS */
opt->add((const char *)"",0,1,0,(const char *)"Administration Unix Socket",(const char *)"-S",(const char *)"--admin-socket");
opt->add((const char *)"",0,0,0,(const char *)"Enable SQLite3 Server",(const char *)"--sqlite3-server");
opt->add((const char *)"",0,0,0,(const char *)"Enable ClickHouse Server",(const char *)"--clickhouse-server");
confFile=new ProxySQL_ConfigFile();
};
@ -167,6 +173,14 @@ void ProxySQL_GlobalVariables::process_opts_pre() {
}
#endif /* IDLE_THREADS */
if (opt->isSet("--sqlite3-server")) {
global.sqlite3_server=true;
}
if (opt->isSet("--clickhouse-server")) {
global.clickhouse_server=true;
}
config_file=GloVars.__cmd_proxysql_config_file;
if (config_file==NULL) {

@ -176,6 +176,7 @@ int socket_fd;
Query_Cache *GloQC;
MySQL_Authentication *GloMyAuth;
ClickHouse_Authentication *GloClickHouseAuth;
Query_Processor *GloQPro;
ProxySQL_Admin *GloAdmin;
MySQL_Threads_Handler *GloMTH;
@ -192,6 +193,7 @@ std::thread *MyMon_thread;
MySQL_Logger *GloMyLogger;
SQLite3_Server *GloSQLite3Server;
ClickHouse_Server *GloClickHouseServer;
ProxySQL_Cluster *GloProxyCluster = NULL;
@ -327,6 +329,7 @@ void ProxySQL_Main_init_main_modules() {
GloQPro=NULL;
GloMTH=NULL;
GloMyAuth=NULL;
GloClickHouseAuth=NULL;
GloMyMon=NULL;
GloMyLogger=NULL;
GloMyStmt=NULL;
@ -404,6 +407,13 @@ void ProxySQL_Main_init_SQLite3Server() {
GloSQLite3Server->print_version();
}
void ProxySQL_Main_init_ClickHouseServer() {
// start SQServer
GloClickHouseServer = new ClickHouse_Server();
GloClickHouseServer->init();
GloClickHouseServer->print_version();
}
void ProxySQL_Main_join_all_threads() {
cpu_timer t;
if (GloMTH) {
@ -467,6 +477,30 @@ void ProxySQL_Main_shutdown_all_modules() {
GloQPro=NULL;
#ifdef DEBUG
std::cerr << "GloQPro shutdown in ";
#endif
}
if (GloClickHouseAuth) {
cpu_timer t;
delete GloClickHouseAuth;
GloClickHouseAuth=NULL;
#ifdef DEBUG
std::cerr << "GloClickHouseAuth shutdown in ";
#endif
}
if (GloClickHouseServer) {
cpu_timer t;
delete GloClickHouseServer;
GloClickHouseServer=NULL;
#ifdef DEBUG
std::cerr << "GloClickHouseServer shutdown in ";
#endif
}
if (GloSQLite3Server) {
cpu_timer t;
delete GloSQLite3Server;
GloSQLite3Server=NULL;
#ifdef DEBUG
std::cerr << "GloSQLite3Server shutdown in ";
#endif
}
if (GloMyAuth) {
@ -624,11 +658,18 @@ void ProxySQL_Main_init_phase3___start_all() {
std::cerr << "Main phase3 : MySQL Monitor initialized in ";
#endif
}
if (1) { // always trye for now
if ( GloVars.global.sqlite3_server == true ) {
cpu_timer t;
ProxySQL_Main_init_SQLite3Server();
#ifdef DEBUG
std::cerr << "Main phase3 : SQLite3 Server initialized in ";
#endif
}
if ( GloVars.global.clickhouse_server == true ) {
cpu_timer t;
ProxySQL_Main_init_ClickHouseServer();
#ifdef DEBUG
std::cerr << "Main phase3 : ClickHouse Server initialized in ";
#endif
}
}

Loading…
Cancel
Save