/** * @file mxs1073_binlog_enc.cpp Test binlog router setup with binlogs encryption * - configure binlog router with follwoing options @verbatim encrypt_binlog=1,encryption_key_file=/etc/mariadb_binlog_keys.txt,encryption_algorithm=aes_cbc @endverbatim * - put some date to Master * - check that all slave have the same data * - 'maxbinlogcheck' against Maxscale binlog file * - check 'maxbinlogcheck' output for lack of errors and presence of 'Decrypting binlog file with algorithm' message * - try remote access to Maxscale binlog with 'mysqlbinlog' * - copy Maxscale binlogs to Master and check output of 'show binary logs' before and after copying * (expect same file name and size, but different checksums) */ #include #include #include "testconnections.h" #include "test_binlog_fnc.h" /** * @brief get_first_binlog_file Get name, size and checksum of first binlog file from 'show binary logs' output list * @param Test TestConnections object * @param name string for file name * @param size variable for file size * @param checksum Pointer to checksum string * @return 0 in case of success */ int get_first_binlog_file(TestConnections * Test, char * name, long long unsigned *size, char ** checksum) { char size_str[64]; char cmd[256]; int res = 0; int exit_code; res = find_field(Test->repl->nodes[0], (char *) "SHOW BINARY LOGS", (char *) "Log_name", name); res += find_field(Test->repl->nodes[0], (char *) "SHOW BINARY LOGS", (char *) "File_size", size_str); sscanf(size_str, "%llu", size); sprintf(cmd, "sha1sum /var/lib/mysql/%s | cut -f 1 -d \" \"", name); *checksum = Test->repl->ssh_node_output(0, cmd, true, &exit_code); if (exit_code != 0) { res++; } Test->tprintf("First master binlog file:\nname: '%s'\nsize: %llu\nchecksum: %s\n", name, *size, *checksum ); return res; } int main(int argc, char *argv[]) { printf("ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!\n" "ERROR! ERROR!\n" "ERROR! This test require file key management plugin! ERROR!\n" "ERROR! ERROR!\n" "ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!ERROR!\n"); return 1; TestConnections * Test = new TestConnections(argc, argv); Test->set_timeout(1000); char str1[1024]; char str2[1024]; char * alg; char * alg1 = (char *) "aes_cbc"; char * alg2 = (char *) "aes_ctr"; Test->tprintf("%s %s\n", Test->test_name, argv[1]); if (strcmp(Test->test_name, "mxs1073_binlog_enc_aes_ctr") == 0) { alg = alg2; } else { alg = alg1; } int i; Test->repl->connect(); Test->try_query(Test->repl->nodes[0], (char *) "DROP TABLE IF EXISTS t1"); Test->tprintf("Coping encription config .cnf files to all nodes \n"); sprintf(str1, "%s/binlog_enc_%s.cnf", Test->test_dir, alg); sprintf(str2, "%s/mariadb_binlog_keys.txt", Test->test_dir); for (i = 0; i < Test->repl->N; i++) { Test->repl->copy_to_node(str1, (char *) "~/", i); Test->repl->ssh_node(i, (char *) "cp ~/binlog_enc*.cnf /etc/my.cnf.d/", true); Test->repl->copy_to_node(str2, (char *) "~/", i); Test->repl->ssh_node(i, (char *) "cp ~/mariadb_binlog_keys.txt /etc/", true); } Test->maxscales->copy_to_node(str2, (char *) "~/", 0); Test->maxscales->ssh_node_f(0, true, "cp ~/mariadb_binlog_keys.txt /etc/"); Test->start_binlog(); Test->repl->connect(); Test->tprintf("Put some data to DB\n"); Test->set_timeout(100); create_t1(Test->repl->nodes[0]); Test->add_result(insert_into_t1(Test->repl->nodes[0], 4), "Data inserting to t1 failed\n"); Test->stop_timeout(); Test->tprintf("Sleeping to let replication happen\n"); sleep(60); for (i = 0; i < Test->repl->N; i++) { Test->tprintf("Checking data from node %d (%s)\n", i, Test->repl->IP[i]); Test->set_timeout(100); Test->add_result(select_from_t1(Test->repl->nodes[i], 4), "Selecting from t1 failed\n"); Test->stop_timeout(); } Test->tprintf("Flush logs\n"); execute_query(Test->repl->nodes[0], (char *) "FLUSH LOGS"); Test->tprintf("Running 'maxbinlogcheck' against Maxscale binlog file\n"); char * maxscale_binlogcheck_output = Test->maxscales->ssh_node_f(0, true, "maxbinlogcheck -M -K /etc/mariadb_binlog_keys.txt -H /var/lib/maxscale/Binlog_Service/mar-bin.000001 --aes_algo=%s 2> 1", alg); //puts(maxscale_binlogcheck_output); if (strstr(maxscale_binlogcheck_output, "error") != NULL) { Test->add_result(1, "Errors in the maxbinlogcheck output:\n%s\n", maxscale_binlogcheck_output); } sprintf(str1, "Decrypting binlog file with algorithm: %s", alg); if (strstr(maxscale_binlogcheck_output, str1) == NULL) { Test->add_result(1, "No '%s' in the maxbinlogcheck output:\n%s\n", str1, maxscale_binlogcheck_output); } sprintf(str1, "mysqlbinlog -R -h %s -P %d -u%s -p%s mar-bin.000001 --stop-position=60000", Test->maxscales->IP[0], Test->maxscales->binlog_port[0], Test->maxscales->user_name, Test->maxscales->password); Test->tprintf("running mysqlbinlog on node_000 to connecto Maxscale: %s\n", str1); int exit_code; char * mysql_binlog_connect_output = Test->repl->ssh_node_output(0, str1, false, &exit_code); Test->add_result(exit_code, "Remote access to Maxscale binlog failed"); sprintf(str1, "LOGS/%s/mysql_binlog_connect_output", Test->test_name); FILE *f = fopen(str1, "wt"); fprintf(f, "%s", mysql_binlog_connect_output); fclose(f); Test->tprintf("Checking binlog files on master\n"); long long unsigned size_before; long long unsigned size_after; long long unsigned size_after_restart; char * checksum_before; char * checksum_after; char * checksum_after_restart; char name_before[256]; char name_after[256]; char name_after_restart[256]; Test->add_result(get_first_binlog_file(Test, name_before, &size_before, &checksum_before), "Error getting binlog name and size\n"); Test->tprintf("Copying binlogs from Maxscale to Master\n"); system("rm -rf binlogs"); system("mkdir binlogs"); Test->maxscales->copy_from_node((char *) "/var/lib/maxscale/Binlog_Service/*", (char *) "binlogs/", 0); Test->repl->ssh_node(0, "rm -rf binlogs", true); Test->repl->copy_to_node("-r binlogs", "./", 0); Test->repl->ssh_node(0, "chown mysql:mysql binlogs/*", true); //Test->repl->ssh_node(0, "rm /var/lib/mysql/mar-bin*", true); Test->repl->ssh_node(0, "cp binlogs/* /var/lib/mysql/", true); sleep(5); Test->tprintf("Checking binlog files on master after copying binlogs from Maxscale\n"); Test->add_result(get_first_binlog_file(Test, name_after, &size_after, &checksum_after), "Error getting binlog name and size\n"); Test->repl->close_connections(); if (size_before != size_after) { Test->add_result(1, "Master binlog file size after copying Maxscale binlogs to Master is different\n"); } if (strcmp(name_before, name_after) != 0) { Test->add_result(1, "Master binlog file name after copying Maxscale binlogs to Master is different\n"); } if (strcmp(checksum_before, checksum_after) == 0) { Test->add_result(1, "Master binlog file checksum after copying Maxscale binlogs to Master is the same. Probably binlog copying error different\n"); } Test->repl->stop_node(0); Test->repl->start_node(0, (char *) ""); sleep(5); Test->tprintf("Checking binlog files on master after copying binlogs from Maxscale and Master restart\n"); Test->repl->connect(); Test->add_result(get_first_binlog_file(Test, name_after_restart, &size_after_restart, &checksum_after_restart), "Error getting binlog name and size\n"); Test->repl->close_connections(); if (size_before != size_after_restart) { Test->add_result(1, "Master binlog file size after copying Maxscale binlogs to Master and restart is different\n"); } if (strcmp(name_before, name_after_restart) != 0) { Test->add_result(1, "Master binlog file name after copying Maxscale binlogs to Master and restart is different\n"); } if (strcmp(checksum_after_restart, checksum_after) != 0) { Test->add_result(1, "Master binlog file checksum after Master restart is different\n"); } // clean up Test->tprintf("Cleaning up nodes and restart replication\n"); Test->repl->stop_nodes(); for (i = 0; i < Test->repl->N; i++) { Test->repl->ssh_node(i, (char *) "rm /etc/my.cnf.d/binlog_enc*.cnf", true); Test->repl->ssh_node(i, (char *) "rm /etc/mariadb_binlog_keys.txt", true); } Test->repl->start_replication(); int rval = Test->global_result; delete Test; return rval; }