394 lines
14 KiB
Plaintext
394 lines
14 KiB
Plaintext
# ==== Purpose ====
|
|
#
|
|
# This script aims at testing read and truncate operations on encrypted binary
|
|
# log files, as well as related error conditions.
|
|
#
|
|
# Part 1: At server startup, truncate incomplete binary log file
|
|
#
|
|
# The test case will make an encrypted binary log file the last one, forcing
|
|
# recovery checks to evaluate it (see file details below).
|
|
#
|
|
# Before allowing a successful recover, failures to access the encrypted file
|
|
# will be simulated playing with the keyring file and using debug
|
|
# instrumentation. The simulations are the same as sections 4.1 and 4.2.
|
|
#
|
|
# After the attempts with simulated failures, the server will be restarted and
|
|
# become operational again.
|
|
#
|
|
# This will ensure that the server is able to read from the encrypted binary
|
|
# log file on binary log recovery and also is able to open the encrypted file
|
|
# for writing (as no key need to be generated) to clear
|
|
# LOG_EVENT_BINLOG_IN_USE_F flag on it and also to truncate it in the end of
|
|
# the last complete transaction.
|
|
#
|
|
# Part 2: Show binlog events/Show binary logs
|
|
#
|
|
# This will ensure that the server is able to decrypt and access an encrypted
|
|
# binary log file from user requests.
|
|
#
|
|
# It will also ensure that the server is able to show which binary log files
|
|
# are encrypted or not.
|
|
#
|
|
# Part 3: Replicate to a slave server
|
|
#
|
|
# This will ensure that the master is able to replicate from an encrypted
|
|
# binary log file to a slave. It will read from the encrypted binary log file
|
|
# but will replicate its content as a plain binary log events stream (without
|
|
# encryption) to the slave.
|
|
#
|
|
# Part 4: Errors
|
|
#
|
|
# Part 4.1: Simulate errors using debug instrumentation
|
|
#
|
|
# 4.1.1 Use an encryption key that cannot decode the file password
|
|
#
|
|
# By corrupting the encryption key using debug instrumentation, the server
|
|
# shall not be able to recognize the binary log data stream as the decrypted
|
|
# content will not match the original binary log data stream.
|
|
#
|
|
# The remaining simulated errors shall throw replication logs encryption
|
|
# specific errors.
|
|
#
|
|
# 4.1.2 Invalid key type returned by keyring.
|
|
# 4.1.3 Invalid key size returned by keyring.
|
|
# 4.1.4 Unable to read the encrypted header version.
|
|
# 4.1.5 Unsupported encrypted header version.
|
|
# 4.1.6 Read out of header boundaries.
|
|
# 4.1.7 Header contains an unsupported field type.
|
|
# 4.1.8 Header is missing the key ID.
|
|
# 4.1.9 Header is missing the encrypted password.
|
|
# 4.1.10 Header is missing the IV.
|
|
# 4.1.11 Incomplete encryption header.
|
|
#
|
|
# Part 4.2: Use a keyring file without the encryption key
|
|
#
|
|
# After replacing the keyring file with an empty keyring file, the server shall
|
|
# throw an error when requested to access the encrypted binary log file.
|
|
#
|
|
# Part 4.3: Uninstall the keyring from the master
|
|
#
|
|
# After uninstalling the keyring_file plug-in, the server shall throw an error
|
|
# when requested to access the encrypted binary log file.
|
|
#
|
|
# Part 5: mysqlbinlog is unable to dump encrypted binary logs
|
|
#
|
|
# Request mysqlbinlog to dump the content of the encrypted binary log file
|
|
# and parse the output asserting that the expected error message was thrown.
|
|
#
|
|
#
|
|
# This test case rely in two previously generated files:
|
|
#
|
|
# encrypted binary log file
|
|
# -------------------------
|
|
|
|
# It was encrypted by a server using V1 encryption.
|
|
#
|
|
# The server that generated it was running with GTID_MODE = OFF, executed the
|
|
# following statements that were logged into the file:
|
|
# - CREATE TABLE t1 (c1 INT PRIMARY KEY);
|
|
# - INSERT INTO t1 (c1) VALUES (1, 2, 3);
|
|
# - INSERT INTO t1 (c1) VALUES (4, 5, 6);
|
|
# - DROP TABLE t1;
|
|
#
|
|
# The file was copied before binary log rotation, so it still has FD's
|
|
# LOG_EVENT_BINLOG_IN_USE_F flag set, and it was manually truncated in the
|
|
# middle of the Query event with the "DROP TABLE t1:" statement.
|
|
#
|
|
# Once recovered, the master shall clear the LOG_EVENT_BINLOG_IN_USE_F flag and
|
|
# truncate the file in the end of last complete transaction.
|
|
#
|
|
# keyring original file
|
|
# ---------------------
|
|
#
|
|
# This is the keyring file where the server that created the above mentioned
|
|
# binary log file stored the encryption key that shall be used to decrypt the
|
|
# file password.
|
|
#
|
|
#
|
|
# ==== Related Bugs and Worklogs ====
|
|
#
|
|
# WL#10957: Binary log encryption at rest
|
|
#
|
|
|
|
# This test case is binary log format agnostic
|
|
--source include/have_debug.inc
|
|
--source include/have_binlog_format_row.inc
|
|
--let $rpl_skip_start_slave= 1
|
|
--source include/master-slave.inc
|
|
|
|
--let $keyring_file= $MYSQL_TMP_DIR/keyring_master
|
|
--let $keyring_original_file= $MYSQL_TEST_DIR/std_data/rpl_nogtid_encryption_keyring_master
|
|
--let $encrypted_binlog_file= $MYSQL_TEST_DIR/std_data/rpl_nogtid_encryption_master-bin.000002
|
|
--let $MASTER_DATADIR= `select @@datadir`
|
|
# Makes the index file to contain two files (we will replace the second one
|
|
# by a previously generated encrypted binary log file.
|
|
FLUSH LOCAL LOGS;
|
|
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
|
|
--let $assert_text= Master status shall point to master-bin.000002
|
|
--let $assert_cond= "$binlog_file" = "master-bin.000002"
|
|
--source include/assert.inc
|
|
--let $binlog_file_path= $MASTER_DATADIR/$binlog_file
|
|
|
|
# Stop the master server
|
|
--let $rpl_server_number= 1
|
|
--source include/rpl_stop_server.inc
|
|
--connection slave
|
|
# Replace the binary log file
|
|
--remove_file $binlog_file_path
|
|
--copy_file $encrypted_binlog_file $binlog_file_path
|
|
|
|
--echo # Part 1
|
|
--let $point= 0
|
|
--let $master_error_log=$MYSQL_TMP_DIR/master.err
|
|
--let $keyring_parameters=$KEYRING_PLUGIN_OPT $KEYRING_PLUGIN_LOAD --keyring_file_data=$keyring_file
|
|
while ($point < 13)
|
|
{
|
|
--inc $point
|
|
--let $rpl_server_parameters= $keyring_parameters --log-error=$master_error_log
|
|
if ($point == 1)
|
|
{
|
|
# Using a keyring key without the key to access the file
|
|
--let $rpl_server_parameters= --log-error=$master_error_log
|
|
--let $debug=
|
|
--let $error_message=Cannot get file password for encrypted replication log file
|
|
}
|
|
if ($point == 2)
|
|
{
|
|
# Using a keyring key without the key to access the file
|
|
--let $debug=
|
|
--let $error_message=Cannot get file password for encrypted replication log file
|
|
}
|
|
if ($point == 3)
|
|
{
|
|
# Corrupting the encryption key (plain binlog stream magic is not recognized)
|
|
--let $debug=--debug=d,corrupt_replication_encryption_key
|
|
--let $error_message=Binlog has bad magic number
|
|
}
|
|
if ($point == 4)
|
|
{
|
|
# Corrupting the encryption key type
|
|
--let $debug=--debug=d,corrupt_replication_encryption_key_type
|
|
--let $error_message=Fetched an invalid key from keyring
|
|
}
|
|
if ($point == 5)
|
|
{
|
|
# Corrupting the encryption key size
|
|
--let $debug=--debug=d,corrupt_replication_encryption_key_size
|
|
--let $error_message=Fetched an invalid key from keyring
|
|
}
|
|
if ($point == 6)
|
|
{
|
|
# Corrupt the encrypted header version
|
|
--let $debug=--debug=d,corrupt_encrypted_header_version
|
|
--let $error_message=Unable to determine encryption header version
|
|
}
|
|
if ($point == 7)
|
|
{
|
|
# Force an unsupported encryption header version
|
|
--let $debug=--debug=d,force_encrypted_header_version_2
|
|
--let $error_message=Unsupported encryption header version
|
|
}
|
|
if ($point == 8)
|
|
{
|
|
# Force a header with fields over the header size
|
|
--let $debug=--debug=d,corrupt_encryption_header_read_above_header_size
|
|
--let $error_message=Header is corrupted
|
|
}
|
|
if ($point == 9)
|
|
{
|
|
# Force a header with an unknown field type
|
|
--let $debug=--debug=d,corrupt_encryption_header_unknown_field_type
|
|
--let $error_message=Unknown field type
|
|
}
|
|
if ($point == 10)
|
|
{
|
|
# Force a header without a key ID
|
|
--let $debug=--debug=d,corrupt_encryption_header_missing_key_id
|
|
--let $error_message=Header is missing the replication encryption key ID
|
|
}
|
|
if ($point == 11)
|
|
{
|
|
# Force a header without password
|
|
--let $debug=--debug=d,corrupt_encryption_header_missing_password
|
|
--let $error_message=Header is missing the encrypted password
|
|
}
|
|
if ($point == 12)
|
|
{
|
|
# Force a header without IV
|
|
--let $debug=--debug=d,corrupt_encryption_header_missing_iv
|
|
--let $error_message=Header is missing the IV
|
|
}
|
|
if ($point == 13)
|
|
{
|
|
# Force an incomplete (< 512 bytes) encryption header
|
|
--let $debug=--debug=d,force_incomplete_encryption_header
|
|
--let $error_message=Header is incomplete
|
|
}
|
|
--echo Try to restart the master with debug instrumentation
|
|
--error 0,1
|
|
--exec $MYSQLD --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group-suffix=.1 $rpl_server_parameters $debug
|
|
--let $assert_file= $master_error_log
|
|
--let $assert_text= Server reported: $error_message
|
|
--let $assert_select= $error_message
|
|
--let $assert_count= 1
|
|
--source include/assert_grep.inc
|
|
--let $assert_text= Server failed to initialize binary log for recovery
|
|
--let $assert_select= Can.t init tc log
|
|
--let $assert_count= 1
|
|
--source include/assert_grep.inc
|
|
--let $assert_text= Server aborted to start
|
|
--let $assert_select= Server.*Aborting
|
|
--let $assert_count= 1
|
|
--source include/assert_grep.inc
|
|
--remove_file $master_error_log
|
|
if ($point == 2)
|
|
{
|
|
# Copy the keyring file
|
|
--remove_file $keyring_file
|
|
--copy_file $keyring_original_file $keyring_file
|
|
}
|
|
}
|
|
|
|
# Restart the server
|
|
--let $rpl_server_number= 1
|
|
--let $rpl_server_parameters= $keyring_parameters
|
|
--let $rpl_omit_print_server_parameters= 1
|
|
--source include/rpl_start_server.inc
|
|
--connection master
|
|
|
|
--echo # Part 2
|
|
--let $assert_text= 1st binary log is not encrypted
|
|
--let $assert_cond= "[SHOW BINARY LOGS, Encrypted, 1]" = "No"
|
|
--source include/assert.inc
|
|
--let $assert_text= 2nd binary log is encrypted
|
|
--let $assert_cond= "[SHOW BINARY LOGS, Encrypted, 2]" = "Yes"
|
|
--source include/assert.inc
|
|
--let $assert_text= 3rd binary log is not encrypted
|
|
--let $assert_cond= "[SHOW BINARY LOGS, Encrypted, 3]" = "No"
|
|
--source include/assert.inc
|
|
--let $binlog_file= master-bin.000002
|
|
--let $keep_gtid_events= 1
|
|
--source include/show_binlog_events.inc
|
|
|
|
--echo # Part 3
|
|
# Start slave threads so it can sync with master
|
|
--source include/rpl_connection_slave.inc
|
|
--source include/start_slave.inc
|
|
--source include/rpl_connection_master.inc
|
|
--source include/sync_slave_sql_with_master.inc
|
|
--let $assert_text= Slave shall have t1 with a 6 rows on it
|
|
--let $assert_cond= [SELECT COUNT(*) AS t1_rows FROM t1, t1_rows, 1] = 6
|
|
--source include/assert.inc
|
|
# Slave cleanup
|
|
DROP TABLE t1;
|
|
--source include/stop_slave.inc
|
|
|
|
--echo # Part 4
|
|
--source include/rpl_connection_master.inc
|
|
|
|
--echo # Part 4.1
|
|
--echo # Part 4.1.1
|
|
--let $debug_point= corrupt_replication_encryption_key
|
|
--source include/add_debug_point.inc
|
|
--error ER_ERROR_WHEN_EXECUTING_COMMAND
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.2
|
|
--let $debug_point= corrupt_replication_encryption_key_type
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_KEYRING_INVALID_KEY
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.3
|
|
--let $debug_point= corrupt_replication_encryption_key_size
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_KEYRING_INVALID_KEY
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.4
|
|
--let $debug_point= corrupt_encrypted_header_version
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.5
|
|
--let $debug_point= force_encrypted_header_version_2
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.6
|
|
--let $debug_point= corrupt_encryption_header_read_above_header_size
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.7
|
|
--let $debug_point= corrupt_encryption_header_unknown_field_type
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.8
|
|
--let $debug_point= corrupt_encryption_header_missing_key_id
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.9
|
|
--let $debug_point= corrupt_encryption_header_missing_password
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.10
|
|
--let $debug_point= corrupt_encryption_header_missing_iv
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
--echo # Part 4.1.11
|
|
--let $debug_point= force_incomplete_encryption_header
|
|
--source include/add_debug_point.inc
|
|
--error ER_RPL_ENCRYPTION_HEADER_ERROR
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
--source include/remove_debug_point.inc
|
|
|
|
--echo # Part 4.2
|
|
UNINSTALL PLUGIN keyring_file;
|
|
# Stop the master server
|
|
--let $rpl_server_number= 1
|
|
--source include/rpl_stop_server.inc
|
|
# Remove the keyring file to create a new empty one
|
|
--remove_file $keyring_file
|
|
# Restart the server
|
|
--let $rpl_server_number= 1
|
|
--let $rpl_server_parameters= $KEYRING_PLUGIN_OPT $KEYRING_PLUGIN_LOAD --keyring_file_data=$keyring_file
|
|
--source include/rpl_start_server.inc
|
|
--error ER_RPL_ENCRYPTION_KEY_NOT_FOUND
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
|
|
--echo # Part 4.3
|
|
UNINSTALL PLUGIN keyring_file;
|
|
--error ER_RPL_ENCRYPTION_FAILED_TO_FETCH_KEY
|
|
--eval SHOW BINLOG EVENTS IN '$binlog_file'
|
|
|
|
--echo # Part 5
|
|
--let $output_file= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.log
|
|
--let $error_file= $MYSQLTEST_VARDIR/tmp/mysqlbinlog.err
|
|
--error 1
|
|
--exec $MYSQL_BINLOG -F $binlog_file_path > $output_file 2> $error_file
|
|
--let $assert_text= mysqlbinlog reported it does not support reading encrypted log files
|
|
--let $assert_file= $error_file
|
|
--let $assert_count= 1
|
|
--let $assert_select= Reading encrypted log files directly is not supported
|
|
--source include/assert_grep.inc
|
|
--remove_file $output_file
|
|
--remove_file $error_file
|
|
|
|
# Cleanup
|
|
--remove_file $keyring_file
|
|
--source include/rpl_connection_slave.inc
|
|
--source include/start_slave.inc
|
|
--source include/rpl_end.inc
|