Skip to content

Commit 8c7d8b7

Browse files
MDEV-14180 Automatically disable key rotation checks for file_key_managment plugin
Problem: ======= - InnoDB iterates the fil_system space list to encrypt the tablespace in case of key rotation. But it is not necessary for any encryption plugin which doesn't do key version rotation. Solution: ========= - Introduce a new variable called srv_encrypt_rotate to indicate whether encryption plugin does key rotation fil_space_crypt_t::key_get_latest_version(): Enable the srv_encrypt_rotate only once if current key version is higher than innodb_encyrption_rotate_key_age fil_crypt_must_default_encrypt(): Default encryption tables should be added to default_encryp_tables list if innodb_encyrption_rotate_key_age is zero and encryption plugin doesn't do key version rotation fil_space_create(): Add the newly created space to default_encrypt_tables list if fil_crypt_must_default_encrypt() returns true Removed the nondeterministic select from innodb-key-rotation-disable test. By default, InnoDB adds the tablespace to the rotation list and background crypt thread does encryption of tablespace. So these select doesn't give reliable results.
1 parent 7d2c338 commit 8c7d8b7

File tree

8 files changed

+98
-15
lines changed

8 files changed

+98
-15
lines changed

mysql-test/suite/encryption/r/innodb-key-rotation-disable.result

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
2-
NAME
3-
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
4-
NAME
51
create database enctests;
62
use enctests;
73
create table t1(a int not null primary key, b char(200)) engine=innodb;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
create table t1(f1 int not null)engine=innodb;
2+
create table t2(f1 int not null)engine=innodb;
3+
insert into t1 select * from seq_1_to_100;
4+
insert into t2 select * from seq_1_to_100;
5+
# Enable encryption
6+
set global innodb_encrypt_tables=ON;
7+
# Create a new table and it is added to rotation list
8+
create table t3(f1 int not null)engine=innodb;
9+
insert into t3 select * from seq_1_to_100;
10+
# Increase the version and it should set rotation
11+
# variable for the encryption plugin
12+
set global debug_key_management_version=10;
13+
select @@debug_key_management_version;
14+
@@debug_key_management_version
15+
10
16+
# Decrease the key version and Disable the encryption
17+
set global debug_key_management_version=1;
18+
set global innodb_encrypt_tables=off;
19+
DROP TABLE t1, t2, t3;

mysql-test/suite/encryption/t/innodb-key-rotation-disable.test

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
# not embedded because of restarts
44
-- source include/not_embedded.inc
55

6-
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
7-
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
8-
96
--disable_query_log
107
--disable_warnings
118
let $encryption = `SELECT @@innodb_encrypt_tables`;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--innodb-tablespaces-encryption
2+
--plugin-load-add=$DEBUG_KEY_MANAGEMENT_SO
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--source include/have_innodb.inc
2+
--source include/have_debug.inc
3+
--source include/have_sequence.inc
4+
5+
create table t1(f1 int not null)engine=innodb;
6+
create table t2(f1 int not null)engine=innodb;
7+
insert into t1 select * from seq_1_to_100;
8+
insert into t2 select * from seq_1_to_100;
9+
10+
let $restart_parameters=--innodb_encrypt_tables=0 --innodb_encryption_threads=1 --innodb_encryption_rotate_key_age=9;
11+
--source include/restart_mysqld.inc
12+
13+
--echo # Enable encryption
14+
15+
set global innodb_encrypt_tables=ON;
16+
--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB'`
17+
--let $wait_timeout= 600
18+
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
19+
--source include/wait_condition.inc
20+
--echo # Create a new table and it is added to rotation list
21+
create table t3(f1 int not null)engine=innodb;
22+
insert into t3 select * from seq_1_to_100;
23+
24+
--echo # Increase the version and it should set rotation
25+
--echo # variable for the encryption plugin
26+
27+
set global debug_key_management_version=10;
28+
select @@debug_key_management_version;
29+
--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB'`
30+
--let $wait_timeout= 600
31+
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0;
32+
--source include/wait_condition.inc
33+
34+
--echo # Decrease the key version and Disable the encryption
35+
set global debug_key_management_version=1;
36+
set global innodb_encrypt_tables=off;
37+
38+
--let $wait_timeout= 600
39+
--let $wait_condition=SELECT COUNT(*) >= $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0;
40+
--source include/wait_condition.inc
41+
DROP TABLE t1, t2, t3;

storage/innobase/fil/fil0crypt.cc

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ UNIV_INTERN uint srv_n_fil_crypt_threads_started = 0;
5555
/** At this age or older a space/page will be rotated */
5656
UNIV_INTERN uint srv_fil_crypt_rotate_key_age;
5757

58+
/** Whether the encryption plugin does key rotation */
59+
static bool srv_encrypt_rotate;
60+
5861
/** Event to signal FROM the key rotation threads. */
5962
static os_event_t fil_crypt_event;
6063

@@ -136,6 +139,14 @@ fil_space_crypt_t::key_get_latest_version(void)
136139

137140
if (is_key_found()) {
138141
key_version = encryption_key_get_latest_version(key_id);
142+
/* InnoDB does dirty read of srv_fil_crypt_rotate_key_age.
143+
It doesn't matter because srv_encrypt_rotate
144+
can be set to true only once */
145+
if (!srv_encrypt_rotate
146+
&& key_version > srv_fil_crypt_rotate_key_age) {
147+
srv_encrypt_rotate = true;
148+
}
149+
139150
srv_stats.n_key_requests.inc();
140151
key_found = key_version;
141152
}
@@ -1380,6 +1391,11 @@ fil_crypt_return_iops(
13801391
fil_crypt_update_total_stat(state);
13811392
}
13821393

1394+
bool fil_crypt_must_default_encrypt()
1395+
{
1396+
return !srv_fil_crypt_rotate_key_age || !srv_encrypt_rotate;
1397+
}
1398+
13831399
/** Return the next tablespace from default_encrypt_tables.
13841400
@param space previous tablespace (NULL to start from the start)
13851401
@param recheck whether the removal condition needs to be rechecked after
@@ -1455,7 +1471,7 @@ static fil_space_t *fil_space_next(fil_space_t *space, bool recheck,
14551471
mutex_enter(&fil_system->mutex);
14561472
ut_ad(!space || space->n_pending_ops);
14571473

1458-
if (!srv_fil_crypt_rotate_key_age)
1474+
if (fil_crypt_must_default_encrypt())
14591475
space= fil_system->default_encrypt_next(space, recheck, encrypt);
14601476
else if (!space)
14611477
{
@@ -2448,7 +2464,7 @@ fil_crypt_set_encrypt_tables(
24482464

24492465
srv_encrypt_tables = val;
24502466

2451-
if (srv_fil_crypt_rotate_key_age == 0) {
2467+
if (fil_crypt_must_default_encrypt()) {
24522468
fil_crypt_default_encrypt_tables_fill();
24532469
}
24542470

storage/innobase/fil/fil0fil.cc

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,22 +1464,28 @@ fil_space_create(
14641464
fil_system->max_assigned_id = id;
14651465
}
14661466

1467+
const bool rotate =
1468+
(purpose == FIL_TYPE_TABLESPACE
1469+
&& (mode == FIL_ENCRYPTION_ON
1470+
|| mode == FIL_ENCRYPTION_OFF || srv_encrypt_tables)
1471+
&& fil_crypt_must_default_encrypt());
1472+
14671473
/* Inform key rotation that there could be something
14681474
to do */
1469-
if (purpose == FIL_TYPE_TABLESPACE
1470-
&& !srv_fil_crypt_rotate_key_age && fil_crypt_threads_event &&
1471-
(mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF ||
1472-
srv_encrypt_tables)) {
1475+
if (rotate) {
14731476
/* Key rotation is not enabled, need to inform background
14741477
encryption threads. */
14751478
fil_system->default_encrypt_tables.push_back(*space);
14761479
space->is_in_default_encrypt = true;
14771480
mutex_exit(&fil_system->mutex);
1481+
} else {
1482+
mutex_exit(&fil_system->mutex);
1483+
}
1484+
1485+
if (rotate && srv_n_fil_crypt_threads_started) {
14781486
mutex_enter(&fil_crypt_threads_mutex);
14791487
os_event_set(fil_crypt_threads_event);
14801488
mutex_exit(&fil_crypt_threads_mutex);
1481-
} else {
1482-
mutex_exit(&fil_system->mutex);
14831489
}
14841490

14851491
return(space);

storage/innobase/include/fil0crypt.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,4 +499,10 @@ bool
499499
fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
500500
MY_ATTRIBUTE((warn_unused_result));
501501

502+
/** Add the tablespace to the rotation list if
503+
innodb_encrypt_rotate_key_age is 0 or encryption plugin does
504+
not do key version rotation
505+
@return whether the tablespace should be added to rotation list */
506+
bool fil_crypt_must_default_encrypt();
507+
502508
#endif /* fil0crypt_h */

0 commit comments

Comments
 (0)