-
Notifications
You must be signed in to change notification settings - Fork 484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PS-4556: Implement innodb redo log encryption #2439
Conversation
b666973
to
bae1cb0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please reference backported commits
client/mysqltest.cc
Outdated
Remove the directory <dir_name> | ||
*/ | ||
|
||
void do_force_rmdir(struct st_command *command, DYNAMIC_STRING *ds_dirname) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static
|
||
#Enable redo log encryption, should report error in server log, since keyring is not loaded. | ||
SET GLOBAL innodb_redo_log_encrypt = ON; | ||
--sleep 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs proper synchronization
|
||
#Enable redo log encryption | ||
SET GLOBAL innodb_redo_log_encrypt = ON; | ||
--sleep 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise
call mtr.add_suppression("You need to use --log-bin to make --binlog-format work"); | ||
--enable_query_log | ||
|
||
--sleep 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
|
||
DROP TABLE t1; | ||
|
||
# Restart the server with keyring loaded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No custom restart sequences, use includes
storage/innobase/os/os0file.cc
Outdated
|
||
ut_ad(static_cast<ulint>(elen) == main_len); | ||
|
||
/* Copy the remain bytes. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remaining
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment not addressed
storage/innobase/os/os0file.cc
Outdated
byte* ptr = src; | ||
dberr_t ret; | ||
|
||
/* Do nothing if it's not a log request. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assert is not a "do nothing"
storage/innobase/os/os0file.cc
Outdated
|
||
/* Encrypt the log blocks one by one. */ | ||
while (ptr != src + src_len) { | ||
//ut_a((m_type == NONE) == !is_encrypted_log(ptr)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
storage/innobase/os/os0file.cc
Outdated
log_block_get_hdr_no(ptr)); | ||
ut_print_buf_hex(std::cerr, ptr, OS_FILE_LOG_BLOCK_SIZE); | ||
fprintf(stderr, "\n"); | ||
ut_print_buf(stderr, m_key, 32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation
storage/innobase/os/os0file.cc
Outdated
@@ -9496,6 +10250,8 @@ Encryption::decrypt( | |||
|
|||
fprintf(stderr, "Decrypting page:%lu.%lu len:%lu\n", | |||
space_id, page_no, src_len); | |||
//ut_print_buf(stderr, m_key, 32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
CMakeLists.txt
Outdated
@@ -13,6 +13,8 @@ | |||
# along with this program; if not, write to the Free Software | |||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |||
|
|||
ADD_DEFINITIONS(-DUNIV_ENCRYPT_DEBUG) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove before merging
@@ -0,0 +1,134 @@ | |||
# WL#9290 InnoDB: Support transparent tablespace data encryption for redo log |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests will need to be made a bit more "abstract" so it could be run with different keyrings - keyring_file, keyring_vault and the future keyrings. Have a look at suite/innodb/table_encrypt_1.test (version for keyring_file) and at keyring_vault/tests/table_encrypt_1.test (version for keyring_vault).
# WL#9290 InnoDB: Support transparent tablespace data encryption for redo log | ||
# This test case will test basic redo log encryption support features. | ||
|
||
--source include/no_valgrind_without_big.inc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I am missing in those tests are actual server crashes that will check if the innodb checkpoint has not been reached. Please have a look at test from MariaDB repo: innodb-redo-badkey.test and innodb-redo-nokey.test.
storage/innobase/fil/fil0fil.cc
Outdated
@@ -7380,8 +7388,6 @@ fil_set_encryption( | |||
return(DB_NOT_FOUND); | |||
} | |||
|
|||
ut_ad(algorithm != Encryption::NONE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this was moved to the bottom of the function ? Seems like unnecessary change.
storage/innobase/fsp/fsp0fsp.cc
Outdated
master_key_id = 0; | ||
master_key = static_cast<byte*>(ut_zalloc_nokey( | ||
ENCRYPTION_KEY_LEN)); | ||
memcpy(master_key, ENCRYPTION_DEFAULT_MASTER_KEY, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does it work - in case of boot we are using predefined master key ? why ? This means we could not encrypt this at all ...
storage/innobase/fsp/fsp0fsp.cc
Outdated
@@ -211,6 +211,21 @@ fsp_flags_to_dict_tf( | |||
|
|||
return(flags); | |||
} | |||
|
|||
bool | |||
fsp_is_undo_tablespace(uint32 space_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused function ?
if (master_key == NULL) { | ||
return(false); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not see information on key version. Please have a look into my email "Supporting different key versions in redo log". Since we are porting this from MySQL, we need to add support for key versioning.
bae1cb0
to
07cbc21
Compare
f1a9fef
to
a0df22e
Compare
PR updated. Major changes:
There are a few formatting issues left / I left a numeric magic constant in the code which should be a define, and maybe a few assertions should be correct error messages instead (they would be quite complex to reach in a real use case, but still) - I'll fix those together with the next round of review comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Spurious submodule updates
- Empty commit message, backported commit(s) not referenced
mysql-test/include/log_encrypt_2.inc
Outdated
DROP TABLE t1; | ||
|
||
# Restart the server with keyring loaded | ||
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use include files, never a hand-coded restart sequence
mysql-test/include/log_encrypt_1.inc
Outdated
call mtr.add_suppression("\\[ERROR\\] InnoDB: Can't set redo log tablespace to be encrypted."); | ||
--enable_query_log | ||
|
||
#Enable redo log encryption, should report error in server log, since keyring is not loaded. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space after #
mysql-test/include/log_encrypt_2.inc
Outdated
--source include/have_innodb.inc | ||
--source include/not_embedded.inc | ||
|
||
#Suppress following messages from myslqd log |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space after #, "mysqld", but the whole comment looks redundant
mysql-test/include/log_encrypt_2.inc
Outdated
INSERT INTO t1 select * from t1; | ||
|
||
# Restart to confirm the encryption info can be retrieved properly. | ||
--source include/kill_mysqld.inc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kill_and_restart_mysqld.inc
storage/innobase/os/os0file.cc
Outdated
byte* src_ptr, | ||
byte* dst_ptr) | ||
{ | ||
ulint len = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Declare locals at first use, const when possible
storage/innobase/os/os0file.cc
Outdated
byte* src, | ||
byte* dst) | ||
{ | ||
ulint data_len; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Declare locals at first use, const when possible
storage/innobase/os/os0file.cc
Outdated
remain_len = data_len - main_len; | ||
|
||
ptr += LOG_BLOCK_HDR_SIZE; | ||
switch(m_type) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Space after switch
storage/innobase/os/os0file.cc
Outdated
|
||
ut_ad(static_cast<ulint>(elen) == main_len); | ||
|
||
/* Copy the remain bytes. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment not addressed
storage/innobase/srv/srv0start.cc
Outdated
@@ -460,6 +460,26 @@ create_log_files( | |||
ut_a(fil_validate()); | |||
ut_a(log_space != NULL); | |||
|
|||
/* Once the redo log is set to be encrypted, | |||
+ initialize encryption information. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra +
Possible values for the variable should be : MASTER_KEY/KEYRING_KEY |
One suggestion about keyring loading and suppression messages in test. There is no need for suppression message (unless explicitly caused by test). The warnings come from non availablity of keyring plugin at startup. I have modified MTR to provide a way to 'early-load' plugin. See mysql-test/suite/innodb/t/percona_sys_tablespace_encrypt-master.opt $KEYRING_PLUGIN_OPT You don't see a single suppression in the mysql-test/suite/innodb/t/percona_sys_tablespace_encrypt.test. This is because of KEYRING_PLUGIN_EARLY_LOAD changes to MTR framework Another benefit of this KEYRING_PLUGIN_EARLY_LOAD is that all subsequent restarts automatically do early-plugin-load. I know that Oracle tests have these suppressions but we can get rid most of them with the above suggested changes. |
03f3794
to
b56b453
Compare
Updated.
|
b56b453
to
dcf5003
Compare
5cb8041
to
184eae1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see the comments.
After the PR is merged, please figure out how compatible redo log encryption with redo log reading in changed page tracking - if not, please file a JIRA issue
let $innodb_file_per_table = `SELECT @@innodb_file_per_table`; | ||
|
||
SET GLOBAL innodb_file_per_table = 1; | ||
SELECT @@innodb_file_per_table; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two very redundant lines, better to use assert.inc or nothing. OK to fix after the merge or never.
--source include/restart_mysqld_no_echo.inc | ||
|
||
SET GLOBAL innodb_redo_log_encrypt = 0; | ||
SELECT @@global.innodb_redo_log_encrypt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what these SELECTs past SET are supposed to test (OK to fix post-merge or never)
storage/innobase/fil/fil0fil.cc
Outdated
@@ -7512,7 +7519,9 @@ fil_encryption_rotate() | |||
for (space = UT_LIST_GET_FIRST(fil_system->space_list); | |||
space != NULL; ) { | |||
/* Skip unencypted tablespaces. */ | |||
if (srv_is_undo_tablespace(space->id) | |||
/* Encrypted redo log tablespaces is handled in function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"tablespaces are"
Fix only if you have to re-push and re-test otherwise
storage/innobase/fsp/fsp0fsp.cc
Outdated
@@ -985,6 +1015,7 @@ fsp_header_fill_encryption_info( | |||
mach_write_to_4(ptr, crc); | |||
|
|||
my_free(master_key); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spurious diff
storage/innobase/include/log0log.h
Outdated
@@ -139,7 +139,12 @@ Closes the log. | |||
@return lsn */ | |||
lsn_t | |||
log_close(void); | |||
/*===========*/ | |||
|
|||
/************************************************************//** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** Enables redo ... */
fix only if you have to re-push/re-test the PR otherwise
storage/innobase/include/log0log.h
Outdated
@param[in] val value to set */ | ||
UNIV_INLINE | ||
void | ||
log_block_set_encrypt_bit( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
log_block_set_encrypt_bit(byte* log_block, bool val);
Fix only if you have to re-push/re-test otherwise
storage/innobase/log/log0log.cc
Outdated
char *redo_key_type = NULL; | ||
byte *rkey = NULL; | ||
unsigned char *rkey2 = NULL; | ||
if(my_key_fetch(PERCONA_REDO_KEY_NAME, &redo_key_type, NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still space after if, but only fix if you have to re-push/re-test otherwise
storage/innobase/os/os0file.cc
Outdated
@@ -9061,7 +9178,7 @@ Encryption::create_master_key(byte** master_key) | |||
|
|||
if (ret || *master_key == NULL) { | |||
ib::error() << "Encryption can't find master key, please check" | |||
" the keyring plugin is loaded."; | |||
" the keyring plugin is loaded."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spurious diffs, but only fix if you have to re-push
if (m_key_id == 0) { | ||
/* When m_key_id is 0, which means it's the | ||
default master key for bootstrap. */ | ||
master_key = static_cast<byte*>(ut_zalloc_nokey( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what is your opinion about considering using my_ allocation?
(by now only change something if you have to re-push/re-test otherwise)
5b972c9
to
522222d
Compare
I fixed the formatting only comments, as I forgot to add the rerecorded result of perfschema.show_sanity. Will I also found out, that the sleeps were likely there to "fix" CI issues, as without those, jenkins release jobs report test failures: https://ps.cd.percona.com/job/percona-server-5.7-param/89/ |
1 similar comment
I fixed the formatting only comments, as I forgot to add the rerecorded result of perfschema.show_sanity. Will I also found out, that the sleeps were likely there to "fix" CI issues, as without those, jenkins release jobs report test failures: https://ps.cd.percona.com/job/percona-server-5.7-param/89/ |
Sleep presence should not block trunk merge in this case, although we will must fix them there afterwards |
8f95e9d
to
f756c78
Compare
Last update, with disabled tests: https://ps.cd.percona.com/job/percona-server-5.7-param/97/#showFailuresLink No failure which occurs on every configuration, except for percona_bug1289599 which seems unrelated. |
22d210c
to
35c1a8a
Compare
This PR implements Encryption threads for encryption/re-encryption/decryption of innodb tablespaces. It is based on MariaDB implementation ported from Google's patch. With this WL user can: 1) Change default KEYRING encryption key 2) Create a new table with KEYRING 3) Encrypt offline already existing tables with KEYRING (with alter) 4) Encrypt/re-encrypt online already existing tables with KEYRING (with innodb_online_encryption, innodb_online_encryption_rotate_key_age variables and innodb_online_encryption_threads) – including tables already encrypted with Master Key encryption. 5) Re-encrypt online already encrypted tables with newer version of encryption key (with variables innodb_online_encryption variable, innodb_online_encryption_threads, innodb_online_encryption_rotate_key_age). This WL also fixed the following bugs reported to MariaDB: (MDEV-17231) Encryption threads keep re-encrypting/encrypting corrupted pages (MDEV-17235) Data dictonary is not updated with encryption flags (MDEV-17234) In memory crypt_data is updated before page0 is updated (MDEV-17233) Page 0 is updated more than once when encryption completes (MDEV-17230) encryption_key_id from alter is ignored by encryption threads (MDEV-17229) Encryption threads ignore innodb_default_encryption_key_id
This is based on WL#9290 in MySQL 8.0, while also adding a keyring based rotated key encryption. The encryption setting supports two options: * master_key, which works like the redo log encryption in MySQL 8.0 * keyring_key, which encrypts each new redo log tablespace with the latest percona_redo key from the keyring. Related commits in upstream 8.0: * 1a6dd57 * 8facbb0
35c1a8a
to
243e2d8
Compare
This is based on WL#9290 in MySQL 8.0, while also adding a keyring based rotated key encryption.
The encryption setting supports two options:
Related commits in upstream 8.0: