diff --git a/mysql-test/suite/rpl/r/rpl_auditing.result b/mysql-test/suite/rpl/r/rpl_auditing.result new file mode 100644 index 00000000000..1861beb4e8f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_auditing.result @@ -0,0 +1,64 @@ +include/master-slave.inc +[connection master] +drop table if exists t1; +connection slave; +reset master; +CREATE TABLE IF NOT EXISTS mysql.server_audit_filters ( +filtername char(80) COLLATE utf8_bin NOT NULL DEFAULT '', +rule longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT 'true' CHECK (json_valid(rule)), +CONSTRAINT c_filtername UNIQUE (filtername) +) ENGINE=Aria; +CREATE TABLE IF NOT EXISTS mysql.server_audit_users (host char(60) COLLATE utf8_bin NOT NULL DEFAULT '', +user char(80) COLLATE utf8_bin NOT NULL DEFAULT '', +filtername char(80) NOT NULL DEFAULT '', +CONSTRAINT c_host_user UNIQUE (host, user) +) ENGINE=Aria; +INSERT INTO mysql.server_audit_filters VALUES ('ignore_sys', '{"ignore_tables" : "mysql.*"}'); +INSERT INTO mysql.server_audit_users VALUES ('%','','ignore_sys'); +INSERT INTO mysql.server_audit_users VALUES ('%','root','ignore_sys'); +install plugin server_audit soname 'server_audit2'; +set global server_audit_logging=on; +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +connection slave; +set global server_audit_logging=off; +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +INSERT INTO mysql.server_audit_filters VALUES ('no_logging','false'); +INSERT INTO mysql.server_audit_users VALUES ('%','','no_logging'); +set global server_audit_logging=on; +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +connection slave; +set global server_audit_logging=off; +uninstall plugin server_audit; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_path=server_audit.log,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,rotate_size=1000000,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_rotations=9,0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=ON,0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_logging=on',0 +TIME,HOSTNAME,,,ID,ID,CREATE,test,t1, +TIME,HOSTNAME,,,ID,ID,WRITE,test,t1, +TIME,HOSTNAME,,,ID,ID,CREATE,test,t1, +TIME,HOSTNAME,,,ID,ID,DROP,test,t1, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select master_pos_wait(\'master-bin.#', POS, 300, \'\')',0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=OFF,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_path=server_audit.log,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,rotate_size=1000000,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_rotations=9,0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=ON,0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_logging=on',0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select master_pos_wait(\'master-bin.#', POS, 300, \'\')',0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=OFF,0 +connection master; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_auditing.test b/mysql-test/suite/rpl/t/rpl_auditing.test new file mode 100644 index 00000000000..3d3cee9a7a0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auditing.test @@ -0,0 +1,77 @@ +if (!$SERVER_AUDIT2_SO) { + skip No SERVER_AUDIT2 plugin; +} + +source include/master-slave.inc; + +--disable_warnings +drop table if exists t1; +sync_slave_with_master; +reset master; +--enable_warnings + +--disable_warnings +CREATE TABLE IF NOT EXISTS mysql.server_audit_filters ( + filtername char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + rule longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT 'true' CHECK (json_valid(rule)), + CONSTRAINT c_filtername UNIQUE (filtername) +) ENGINE=Aria; + +CREATE TABLE IF NOT EXISTS mysql.server_audit_users (host char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + user char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + filtername char(80) NOT NULL DEFAULT '', + CONSTRAINT c_host_user UNIQUE (host, user) +) ENGINE=Aria; +--enable_warnings + +INSERT INTO mysql.server_audit_filters VALUES ('ignore_sys', '{"ignore_tables" : "mysql.*"}'); +INSERT INTO mysql.server_audit_users VALUES ('%','','ignore_sys'); +INSERT INTO mysql.server_audit_users VALUES ('%','root','ignore_sys'); + +install plugin server_audit soname 'server_audit2'; +set global server_audit_logging=on; + +# this is done to make test deterministic +# so the above 'set' command is always logged before the 'create table t1' +-- disable_query_log +-- disable_result_log +select * from mysql.server_audit_filters; +select * from mysql.server_audit_users; +-- enable_result_log +-- enable_query_log + +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +sync_slave_with_master; + +set global server_audit_logging=off; + +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +INSERT INTO mysql.server_audit_filters VALUES ('no_logging','false'); +INSERT INTO mysql.server_audit_users VALUES ('%','','no_logging'); + +set global server_audit_logging=on; + +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +sync_slave_with_master; + +set global server_audit_logging=off; +uninstall plugin server_audit; +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +let $MYSQLD_DATADIR= `SELECT @@datadir`; +# replace the timestamp and the hostname with constant values +--replace_regex /[0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\,[^,]*\,/TIME,HOSTNAME,/ /\,[1-9][0-9]*\,/,1,/ /\,[1-9][0-9]*/,ID/ /000001\\', [0-9]*,/#', POS,/ +cat_file $MYSQLD_DATADIR/server_audit.log; +remove_file $MYSQLD_DATADIR/server_audit.log; + +connection master; +--source include/rpl_end.inc diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 82bed1ccff2..f03e5780ad9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -297,7 +297,8 @@ static TYPELIB tc_heuristic_recover_typelib= }; const char *first_keyword= "first"; -const char *my_localhost= "localhost", *delayed_user= "DELAYED"; +const char *my_localhost= "localhost", + *delayed_user= "delayed", *slave_user= ""; bool opt_large_files= sizeof(my_off_t) > 4; static my_bool opt_autocommit; ///< for --autocommit command-line option diff --git a/sql/mysqld.h b/sql/mysqld.h index 8d26bcbb5f0..5fa8e22c2ab 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -264,7 +264,7 @@ extern time_t server_start_time, flush_status_time; extern char *opt_mysql_tmpdir, mysql_charsets_dir[]; extern size_t mysql_unpacked_real_data_home_len; extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list; -extern const char *first_keyword, *delayed_user; +extern const char *first_keyword, *delayed_user, *slave_user; extern MYSQL_PLUGIN_IMPORT const char *my_localhost; extern MYSQL_PLUGIN_IMPORT const char **errmesg; /* Error messages */ extern const char *myisam_recover_options_str; diff --git a/sql/slave.cc b/sql/slave.cc index 3726bc1a6f6..f70336e980a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3511,6 +3511,7 @@ static int init_slave_thread(THD* thd, Master_info *mi, } thd->security_ctx->skip_grants(); + thd->security_ctx->user=(char*) slave_user; thd->slave_thread= 1; thd->connection_name= mi->connection_name; thd->variables.sql_log_slow= !MY_TEST(thd->variables.log_slow_disabled_statements & LOG_SLOW_DISABLE_SLAVE); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 39b1be87040..1c207cd54eb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7532,7 +7532,7 @@ static bool can_grant_role(THD *thd, ACL_ROLE *role) { Security_context *sctx= thd->security_ctx; - if (!sctx->user) // replication + if (!sctx->is_user_defined()) // galera return true; ACL_USER *grantee= find_user_exact(sctx->priv_host, sctx->priv_user); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a358d9c3351..ad8e961d6d8 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4504,7 +4504,7 @@ void Security_context::destroy() my_free((char*) host); host= NULL; } - if (user != delayed_user) + if (is_user_defined()) { my_free((char*) user); user= NULL; diff --git a/sql/sql_class.h b/sql/sql_class.h index a8ef8648210..f887a6cfa92 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1506,6 +1506,8 @@ public: */ bool check_access(const privilege_t want_access, bool match_any = false); bool is_priv_user(const char *user, const char *host); + bool is_user_defined() const + { return user && user != delayed_user && user != slave_user; }; }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9f1dee1f598..63c00f8614e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2776,9 +2776,10 @@ static my_bool list_callback(THD *tmp, list_callback_arg *arg) thd_info->thread_id=tmp->thread_id; thd_info->os_thread_id=tmp->os_thread_id; - thd_info->user= arg->thd->strdup(tmp_sctx->user ? tmp_sctx->user : - (tmp->system_thread ? - "system user" : "unauthenticated user")); + thd_info->user= arg->thd->strdup(tmp_sctx->user && tmp_sctx->user != slave_user ? + tmp_sctx->user : + (tmp->system_thread ? + "system user" : "unauthenticated user")); if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && arg->thd->security_ctx->host_or_ip[0]) { @@ -3225,7 +3226,7 @@ static my_bool processlist_callback(THD *tmp, processlist_callback_arg *arg) /* ID */ arg->table->field[0]->store((longlong) tmp->thread_id, TRUE); /* USER */ - val= tmp_sctx->user ? tmp_sctx->user : + val= tmp_sctx->user && tmp_sctx->user != slave_user ? tmp_sctx->user : (tmp->system_thread ? "system user" : "unauthenticated user"); arg->table->field[1]->store(val, strlen(val), cs); /* HOST */