[MDEV-14398] When innodb_encryption_rotate_key_age=0 is set, server won't encrypt tablespaces Created: 2017-11-14 Updated: 2021-07-26 Resolved: 2019-05-02 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Encryption, Storage Engine - InnoDB |
| Affects Version/s: | 10.1, 10.2, 10.3 |
| Fix Version/s: | 10.2.24, 10.3.15, 10.4.5 |
| Type: | Bug | Priority: | Critical |
| Reporter: | Geoff Montee (Inactive) | Assignee: | Thirunarayanan Balathandayuthapani |
| Resolution: | Fixed | Votes: | 2 |
| Labels: | encryption, innodb | ||
| Issue Links: |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Description |
|
The fix for Unfortunately, when innodb_encryption_rotate_key_age=0 is set, it also seems to prevent the server from encrypting unencrypted tablespaces in the background. To reproduce, do the following: 1.) Initialize a datadir without encryption enabled. You can ensure that the tablespaces are not encrypted by querying INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION and confirming that there are 0 rows.
2.) Then change the configuration to enable encryption. Be sure to set innodb_encryption_rotate_key_age=0. I used the following configuration:
3.) Restart the server. 4.) Check whether the tablespaces are encrypted. They still are not:
5.) Change the configuration so that innodb_encryption_rotate_key_age=0 is commented out. 6.) Restart the server. 7.) Check whether the tablespaces are encrypted. They are:
|
| Comments |
| Comment by Elena Stepanova [ 2017-11-19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Reproducible as described | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2017-12-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I have tried to convince that this is designed feature after request for a feature where no key rotation is done in background. In this contents unencrypted to encrypted is key rotation as well as encrypted to unencrypted is a key rotation. If unecrypted to encrypted or encrypted to unecrypted key rotation feature is needed it can't be done with no CPU usage because: (1) At startup, we need to iterate all tables to find out what tables need this one time key rotation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Geoff Montee (Inactive) [ 2017-12-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hi jplindst, Thanks for the feedback. I understand your points. We should probably try to improve the documentation on encryption, so that implementation details like this that can affect users are clearer. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Geoff Montee (Inactive) [ 2017-12-13 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Should this be closed as "Not a Bug" and the implementation details added to the documentation (e.g. see | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2017-12-14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Please do not close this yet, lets have a understanding the expectations from customer. In this context there is following possibilities for enhancement:
Question: what should happen when user issues set global innodb-encrypt-tables=[ON|OFF|FORCE]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2017-12-14 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
How about this:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2018-01-08 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
To clarify, one can process the system tablespace first, but after the all tables are en-/decrypted InnoDB should record somewhere this fact, "all tables are en-/decrypted". If system tablespace is processed last, then it implicitly records this fact in its own state. If it's processed first, as now, it must be an explicit value written somewhere "ok, all tables are done" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-01-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
TBoyd Workarounds: (1) New databases: mysql_install_db configuration should set innodb-encryption-rotate-key-age != 0 with other encryption setup this will ensure that system tablespace is encrypted.
And make sure that all tablespaces requiring encryption has marked so. After that shutdown server and you are safe to set innodb_encryption_rotate_key_age = 0 and start server. We are planning to add syntax to encrypt any tablespace in Global metadata on system tablespace has problem we would need to know it is there (as earlier releases did not have it) and maintenance of its value has challenges. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-01-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Normally we acquire a new key version for every create table so setting it as a large value it has impact how often block by block encryption happens. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-02-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Current plan:
Idea is to check only tablespaces whose page 0 is read whenever there is encryption state change and in startup. This requires some CPU time but we do not read page 0 from every tablespace. Naturally, tablespaces that are not much used remain on state they are maybe a long time. They can be encrypted/decrypted doing e.g. select. Users should use explicit encryption (create table t1 ... engine=innodb encrypted=YES) for those tables that require immediate encryption. TBoyd Can you check from customer does this design fulfill their needs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Rick Pizzi [ 2018-02-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
In current implementation (10.1.31) is there a way to decrypt the system tablespace? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-02-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Rick Pizzi [ 2018-02-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Tried that but I don't see any automatic decrypt of innodb tablespace aka ibdata1. It stays encrypted. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-02-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ah, naturally as it is not implemented. If you want totally away from encryption you can try following config:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Rick Pizzi [ 2018-02-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Tried that and it does not work. So, can I assume there is no way out of encryption as of today? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-06-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
As already noted by me this is either "works as designed" or feature request. There is clearly documented (if not then open a new bug to improve the documentation) way to work around this feature. This is not a critical bug. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-06-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
See how to get system tablespace to encrypted/unencrypted state from blog https://mariadb.com/resources/blog/moving-mariadb-database-encrypted-and-unencrypted-states | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2018-06-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I still think it's a regression bug, that needs to be fixed eventually | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2018-07-31 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
jplindst did not like the approach that I had been discussing with thiru: adding some persistent state to the DICT_HDR page in the InnoDB system tablespace to indicate whether all data files are encrypted or all are in cleartext, or there is a mix of them. So, we discussed another approach that does not change any persistent data format, but instead changes the interfaces as follows (my proposal based on the discussion):
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jan Lindström (Inactive) [ 2018-08-06 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ok to push by me | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2018-08-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
How does this another approach solve the original problem or tablespaces not being encrypted? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thirunarayanan Balathandayuthapani [ 2018-08-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Basically patch removed the relation between innodb_encrypt_rotate_key_age and innodb_encrypt_tables variables. Introduced a variable called innodb_encrypt_tables_deferred to avoid i/o usage by rotation thread. Basically rotation threads avoids to if innodb_encrypt_rotate_key_age = 0 then it avoids only re-encrypt the encrypted tablespace. It can encrypt/decrypt the tablespace | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2018-08-27 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
It was agreed that we should persistently store the state of encryption in the InnoDB system tablespace. We can use the 32-bit field DICT_HDR_MIX_ID_LOW for that. Up until now, its value is always 10. We can repurpose this value to mean "some tables might be encrypted, some might not". Then, let us introduce the values 8 and 9 for "all tables are encrypted" and "all tables are unencrypted", respectively. If any other value is present in this field, we must refuse InnoDB startup. Unfortunately, it seems to me that this solution will introduce a one-time first-startup penalty for all users who upgrade to the version with this fix present: When the field carries the old value, we must read the first page of every InnoDB data file in order to determine whether it is encrypted. This is because the data dictionary does not store information about whether encryption is used. That information is only stored in the first page of each data file itself. It is not stored in the InnoDB SYS_TABLES. Also the table option in .frm files is not reliable, because encryption can be by a global parameter. (And also reading all .frm files at startup could be slow.) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2018-09-24 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I reviewed the changes in bb-10.2-MDEV-14398 and requested a few minor changes. In the end, this should also be backported to 10.1. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2018-10-16 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Please submit the 10.1 version as well. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thirunarayanan Balathandayuthapani [ 2018-11-08 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
marko gave some review comments for mdev-14398 patch. Still working on the patch. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thirunarayanan Balathandayuthapani [ 2019-02-01 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Completed the patch for encrypted list of tablespace. Cross verified whether we are doing false-positive case. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thirunarayanan Balathandayuthapani [ 2019-02-04 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I completed the patch for it. patch is in[ bb-10.2- Branch has 3 patches: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-02-07 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I did my review in a bit unconventional way, by pushing clean-up commits to the bb-10.4-MDEV-14398 branch.
Please fix those, and check if you agree with my changes. Ultimately, after you have fixed the failures and we both are happy with the result, I’d squash the commits and push to 10.4. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-02-08 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I pushed one more change that avoids releasing and re-acquiring fil_system.mutex in low-level code, and tries to update the DICT_HDR page at the higher level where appropriate. After that, I was thinking that the global encryption status should also change if we remove the last tablespace of its kind (encrypted or unencrypted). The following patch attempts to do that, but additional tests would start to fail if I actually enable the logic (see below):
If you apply the patch and remove the 4 occurrences of true || at the end of the patch, then the following tests will fail (in addition to the 3 already failing tests):
thiru, please investigate and fix this. Also, while working on the patch, I noticed that MLOG_FILE_CREATE2 is not being written (and flushed) ahead of the file creation, but behind it. That would be fixed in the course of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Geoff Montee (Inactive) [ 2019-02-23 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I see that at some point we added a check, so that you aren't able to change innodb_encrypt_tables if innodb_encryption_rotate_key_age=0 is set. For example:
If the patch for this issue makes it so that background encryption/decryption operations are no longer internally considered key rotation operations, then I think that the patch should also remove this restriction. A lot of users like to disable key rotations because the key rotation checks constantly use CPU in the background. These key rotation checks even waste CPU resources when file_key_management plugin is used, which doesn't support key rotations at all. However, I think this would be a non-issue if | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-04-23 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The code has not been changed since my previous comment. The full code changes against 10.4 can be viewed with the following command:
If I remember correctly, this change is not distinguishing tablespaces based on the ENCRYPTION parameter. My current understanding of the design is that tables that were explicitly created or altered with ENCRYPTION=OFF or ENCRYPTION=ON should not be affected by the innodb_encrypt_tables parameter. Therefore, when keeping track of "mixed encryption status", only ENCRYPTION=DEFAULT tables should be considered. There appears to be a less intrusive alternative that would avoid changing the format of the InnoDB system tablespace and thus be more suitable for implementation in GA releases of MariaDB. Instead, we would extend the update trigger for SET GLOBAL innodb_encrypt_tables in innodb_encrypt_tables_update() or fil_crypt_set_encrypt_tables() as follows:
The observable effects would be as follows:
I agree with GeoffMontee that the check that was added to innodb_encrypt_tables_validate() in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2019-04-30 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Good work! I pushed an amended version for testing. Can we remove fil_system_t::crypt_status and related code? It was mainly needed for writing a persistent global encryption state, in the 10.4 based earlier version of the patch. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Thirunarayanan Balathandayuthapani [ 2019-05-02 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I pushed the removal of fil_system_t::crypt_status and its related code. Let's hope for the testing to give good results. |