WL#12261: Control (enforce and disable) table encryption
Affects: Server-8.0
—
Status: Complete
Currently the option that controls if a table is encrypted or not is:
* Specified per table.
* Everybody can specify it (no extra privileges required) and with any value.
* Has a single compiled in default (off).
This is not very convenient in environments where DBA want to
grant CREATE TABLE to users while still retaining some control
over encryption usage, e.g.:
* They want to enforce that all tables in a certain database are encrypted
* They want to make sure people don't do double encryption since the underlying
storage engine is encrypted.
This WL aim to provide following functionality:
1) Enforce table encryption globally:
Enable all tables to be encrypted by default. Add global system
variable 'default_table_encryption'. This variable value would be used
as default encryption type for the commands CREATE DATABASE and
CREATE TABLESPACE. This would enable a way to keep all tables
as encrypted in a MySQL server instance.
2) Force encryption for certain database:
Enable all tables in the specific database be encrypted by
default. Add new DEFAULT ENCRYPTION clause for database to
support the same. Databases would inherit the global
'default_table_encryption' as DEFAULT ENCRYPTION if user does not
supply one.
3) Disable encryption globally:
Disable tables encryption in MySQL by default. The system
variable 'default_table_encryption' enables the same. This could be
helpful to avoid double encryption since underlying storage is
encrypted already in cloud setup.
4) Backward compatible setup:
Keep CREATE TABLE ... ENCRYPTION=Y|N and
CREATE TABLESPACE ENCRYPTION=Y|N work as before.
5) Introduce a privilege TABLE_ENCRYPTION_ADMIN. This would enable
user to override the checks mentioned in case 6) below.
6) Introduce a switch which indicates whether we do privilege
check if user tries to use non-default value for CREATE DATABASE
or CREATE TABLESPACE or when he tries to do CREATE TABLE with
ENCRYPTION option which deviates from per-database default.
Following could be the system variable name. It be defined as
GLOBAL variable.
--table-encryption-privilege-check=Y|N
FR1) Add new boolean system variable 'default_table_encryption',
with GLOBAL+SESSION scope. Allow PERSIST/PERSIST_ONLY on this
variable.
FR2) Allow system variable 'default_table_encryption' to be
changed during runtime as described in section I.C).1.
FR3) Add new boolean system variable
'table_encryption_privilege_check', with GLOBAL scope and allow
behavior as defined in I.C).2.
FR4) Add new privilege TABLE_ENCRYPTION_ADMIN.
The following four FR's point to items in HLS, because each item
in these sections pretty much define a FR.
FR5) Implement HLS II) A) 1., 2. & 3.
FR6) Implement HLS II) B) items 1. to 3.
FR7) Implement HLS II) C) items 1. to 3.
FR8) Implement HLS II) D) items 1. to 11.
FR9) Implement HLS II) E) items 1. to 7.
FR10) Restoring the database and tables into same or higher
version of mysql would retain the original encryption mode,
unless we have following condition during restore,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
Upgrade related:
U1) Upgrade from older 8.0 version to 8.0 with WL12261 would
succeed and may not be affected by both
'default-table-encrpytion' and 'table-encryption-privilege-check'
settings.
U2) Upgrade from 5.7 version to 8.0 with WL12261 will force
--table-encryption-privilege-check='N' during upgrade.
Replication related:
R1. Replication should preserve encryptedness of tables, when the
encryptedness is specified as Y/N/unspecified in the
CREATE DATABASE statement.
R2. Replication should preserve encryptedness of tablespaces, when
the encryptedness is specified as Y/N/unspecified in the
CREATE TABLESPACE statement.
I. INTRODUCTION:
````````````````
The WL introduces following functionality:
A) Support DEFAULT ENCRYPTION property for DATABASE.
1. The purpose of this default is to defines if tables under the
database should be encrypted or unencrypted by default.
2. This default is always set for a database. Either from server
global default is inherited or it is explicitly specified by user.
We do not differentiate between implicit and explicit values
here.
3. Add new DD column mysql.schemata.default_encryption with
type ENUM('No', 'Yes') to store the new DEFAULT ENCRYPTION
database property.
B) Support new privilege TABLE_ENCRYPTION_ADMIN.
The primary purpose of this new privilege is to enable users
to override global or per-database ENCRYPTION properties,
introduced in this WL. Detailed explanation on behavior
changes are in HLS.
C) Add system variables to control following two behaviors,
1. The first system variable to control global encryption default, which
it is used when someone does CREATE DATABASE and CREATE
TABLESPACE without ENCRYPTION clause, it doesn't affect CREATE
TABLE directly. Following is the system variable name:
--default-table-encryption=Y|N
This variable,
* Would be GLOBAL+SESSION variable. A SESSION variable because of alteast
following two primary reason,
- Allow replication slave applier thread to use the
--default-table-encryption value stored in the log event
and set it per session during DDL execution.
- Allow applying binary logs using mysqlbinlog tool.
* Allow --default-table-encryption to be changed during runtime, by a
user who owns both TABLE_ENCRYPTION_ADMIN and SYSTEM_VARIABLES_ADMIN
privileges.
* Allow SET PERSIST/PERSIST_ONLY on this variable, which is useful
in cloud environment.
* Allow users with SUPER and TABLE_ENCRYPTION_ADMIN privilege to set
the variable.
2. The second option is a switch which indicates whether we do
privilege check if user tries to use non-default value for
CREATE DATABASE or CREATE TABLESPACE or when he tries to do
CREATE TABLE with ENCRYPTION option which deviates from
per-database default. Following is the system variable name. It
be defined as GLOBAL variable.
--table-encryption-privilege-check=Y|N
* Allow SET PERSIST/PERSIST_ONLY on this variable, which is useful
in cloud environment.
* Allow users with SUPER privilege to set the variable.
Note:
We can think of a design to achieve the same using single variable as
following, but it may be complex for end-users to understand. So, we
are not going this way. This is JFYI.
# Use single server variable '--table-encryption'.
The variable --table-encryption would support three values
'default|enabled|disabled'.
'default' would mean,
- we disable 'default-table-encryption' = N.
- we disable 'table-encryption-privilege-check' = N.
'enabled' would mean,
- we enable 'default-table-encryption' = Y.
- we enable 'table-encryption-privilege-check' = Y.
'disabled' would mean,
- we disable 'default-table-encryption' = N.
- we enable 'table-encryption-privilege-check' = Y.
D) Allow ENCRYPTION clause for tables using general tablespace.
This allows more uniform way of treating ENCRYPTION clause in
CREATE/ALTER TABLE command and simplifies the design of this WL.
Behavior change with specific commands are noted in below
section II. E).
II. DESIGN:
```````````
A) DEFAULT ENCRYPTION property for DATABASE:
The primary purpose of this property is to enable option to
create all the tables in database to be encrypted OR unencrypted.
1. Extend the CREATE DATABASE command to accept DEFAULT ENCRYPTION=Y/N
E.g., 'CREATE DATABASE db1 DEFAULT ENCRYPTION=Y|N'
Where,
'Y', indicates that tables under this database would be
encrypted by default, but can be overridden.
'N', indicates that tables under this database would be
unencrypted by default, but can be overridden.
2. SHOW CREATE DATABASE will always show the DEFAULT ENCRYPTION
clause. This clause would be shown in comment /*! */. This
enables portability.
CREATE DATABASE db1 /*!80014 DEFAULT ENCRYPTION=Y */;
3. Add new column INFORMATION_SCHEMA.SCHEMATA.DEFAULT_ENCRYPTION
which show the current default for the respective database.
B) Behavior of CREATE|ALTER DATABASE:
1. CREATE DATABASE without explicit DEFAULT ENCRYPTION clause
always succeeds and uses 'default-table-encryption' as
database encryption property.
2. CREATE/ALTER DATABASE with explicit ENCRYPTION clause
succeeds and uses value specified in this clause as database
encryption property unless following condition is met,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND this value doesn't match 'default-table-encryption' value,
In the latter case we fail with an appropriate error message.
3. ALTER DATABASE without explicit DEFAULT ENCRYPTION clause
will retain the original DEFAULT ENCRYPTION value of DATABASE.
C) Behavior of CREATE|ALTER TABLESPACE:
1. CREATE TABLESPACE without explicit ENCRYPTION clause
always succeeds and uses 'default-table-encryption' as
tablespace encryption property. The ENCRYPTION clause would
always be stored with tablespace metadata hence forth.
2. CREATE/ALTER TABLESPACE with explicit ENCRYPTION clause
succeeds and uses value specified in this clause as
tablespace encryption property unless following condition is
met,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND this value doesn't match 'default-table-encryption' value,
In the latter case we fail with an appropriate error message.
3. ALTER TABLESPACE without explicit ENCRYPTION clause will retain
the original ENCRYPTION type of tablespace
4. ALTER TABLESPACE which encrypts tablespace would succeed,
unless following condition is met,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND per-database encryption default is 'N' for any of the
table in this tablespace being altered .
In the latter case we fail with an appropriate error message.
5. ALTER TABLESPACE which decrypts tablespace would succeed,
unless following condition is met,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND per-database encryption default is 'Y' for any of the
table in this tablespace being altered .
In the latter case we fail with an appropriate error message.
6. The ENCRYPTION clause value for the tablespace is stored the
same way as before this WL. i.e.,
a The key 'encryption' in mysql.tablespace.options DD column
holds the value 'Y/N'
b This value is stored for SE that does not support tablespace too.
E.g., tablespace with ENCRYPTION='n' should be acceptable, unless
the SE rejects it.
c After the WL, there is always a ENCRYPTION clause for a tablespace
stored. It is either inherited from 'default-table-encryption' or
is explicitly specified by the user. We do not differentiate between
a explicit and implicitly inherited property.
d Attempt to use ENCRYPTION clause with values other than
'N' (or equivalent 'n' or '') when creating/altering tablespace in
SEs which don't support encryption would produce error and not
silently accept it (as it is done now).
e Do not store implicit/explicit value ENCRYPTION='N' in dictionary for
SE's that does not support encryption. We store it only for tablespace
using SE's that support encryption.
f We store the ENCRYPTION property along with mysql.tablespaces.options
for file-per-table tablespace too, similar to the way we store for
general tablespace.
D) Behavior of CREATE|ALTER TABLE:
1. Notes on the way ENCRYPTION property is stored in DD.
a. ENCRYPTION property is stored the same way as before this WL.
i.e., the key 'encryption' in mysql.tables.options DD column
holds the value.
b. ENCRYPTION clause is stored the same way for both file-per-table
and general tablespace.
c. ENCRYPTION clause is always stored with value 'N', if user does
not supply and if per-database default is 'N'. We do not
differentiate between implicit and explicit ENCRYPTION clause.
SHOW CREATE TABLE would work as per D.11).
d. ENCRYPTION clause is always stored with value 'Y', if user does
not supply it and the per-database default is 'Y'. In other words
the inherited value 'Y' from per-database default is treated as
explicit value and SHOW CREATE TABLE would show it.
e. Attempt to use ENCRYPTION option with values other than
'N' (or equivalent 'n' or '') when creating/altering tables in
SE's which don't support encryption would produce error and not
silently accept it (as it is done now).
f. Do not store implicit/explicit value ENCRYPTION='N' in dictionary for
SE's that does not support encryption. We store it only for tables
using SE's that support encryption.
2. CREATE TABLE without explicit ENCRYPTION clause using file-per-table
tablespace always succeeds and uses database default encryption as
table/tablespace encryption property.
3. CREATE TABLE using a engine that does not support encryption
with ENCRYPTION=N clause will succeed if database encryption is
'N'.
4. CREATE TABLE using ENCRYPTION=N on a engine that
do-not-support-encryption will succeed if database encryption is
'Y', unless following condition is met,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND The database encryption is 'Y'
In the latter case we fail with an appropriate error message.
4.1) Emit a warning when user attempts to create a unencrypted
table without ENCRYPTION clause in following situation,
a) 'table-encryption-privilege-check' is 'N'
b) AND The database encryption is 'Y'
5. CREATE TABLE without ENCRYPTION clause on a engine that
do-not-support-encryption will fail if database
encryption is 'Y'.
6. CREATE/ALTER TABLE with explicit ENCRYPTION clause for table using
file-per-table tablespace succeeds and uses value specified in this
clause as table/tablespace encryption property, unless following
condition is met,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND this value doesn't match database encryption value.
In the latter case we fail with an appropriate error message.
7. Changing table encryption through ALTER TABLE without explicitly
specifying ENCRYPTION clause in it (e.g. by moving table between
tablespaces or by changing table storage engine) is not allowed.
8. (not used)
9.1 Changing table (through ALTER TABLE, without changing table database)
using file-per-table or general unencrypted tablespace to use
file-per-table or general unencrypted tablespace will always succeed
irrespective of user owning TABLE_ENCRYPTION_ADMIN or the per-database
default encryption.
9.2 Moving (through RENAME TABLE or ALTER TABLE RENAME) unencrypted table
to a new database succeeds unless the following condition is met:
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND destination database encryption is 'Y'.
In the latter case we fail with an appropriate error message.
10.1 Changing (through ALTER TABLE) encrypted table to use a encrypted
file-per-table or general tablespace without moving it to different
database will always succeed irrespective of user owning
TABLE_ENCRYPTION_ADMIN or the per-database default encryption.
10.2 Moving (through RENAME TABLE or ALTER TABLE RENAME) encrypted table
to a new database succeeds unless the following condition is met:
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
c) AND destination database encryption is 'N'.
In the latter case we fail with an appropriate error message.
10.3 Do not allow moving encrypted tables from SE which supports
encryption to SE which doesn't support encryption unless user explicitly
specifies ENCRYPTION=N in the same ALTER TABLE.
11. SHOW CREATE TABLE and INFORMATION_SCHEMA.TABLES.OPTIONS
will show ENCRYPTION clause if,
i) the table is encrypted
OR
ii) If the table's encryption type is different from database
encryption type.
E) Behavior of CREATE|ALTER TABLE using general tablespace and
the ENCRYPTION clause:
1. Allow ENCRYPTION clause for CREATE TABLE and ALTER TABLE
commands with tables using general tablespace. This is currently
not allowed and we throw error.
2. Persist the value of ENCRYPTION clause in data dictionary
tables for table using general tablespace too.
3. CREATE/ALTER TABLE with the explicit ENCRYPTION clause along
with TABLESPACE clause, shall emit an error if the ENCRYPTION
clause type differs from the tablespace encryption type.
4. If the ENCRYPTION clause is not provided in CREATE TABLE or
ALTER TABLE, then the implicit ENCRYPTION clause would inherit
value from per-database ENCRYPTION default.
This means that with per-database ENCRYPTION='n' (which is a
default configuration with --default-table-encryption='N'),
and attempt run CREATE TABLE without explicit ENCRYPTION
option and using a encrypted tablespace will start to fail.
(by definition in D.6)
5. ALTER TABLE with ENCRYPTION clause, without TABLESPACE clause
shall emit an error if ENCRYPTION type differs from
tablespace encryption type.
6. Note that the above behavior cannot be overriden by users
with TABLE_ENCRYPTION_ADMIN privilege.
7. SHOW CREATE TABLE command shall works same as mentioned in
point D.11 for tables using general tablespace too.
Note that the behavior defined in section D) are applied after
first checking for condition in points 2., 3., and 4. defined
above.
F) MYSQLDUMP AND RESTORE:
1. SHOW CREATE DATABASE uses versioned mysql-specific
commenting style like /*!80014 DEFAULT ENCRYPTION */ for
portability, so the older server would ignore parsing this
new clause.
2. Restoring the database and tables into same or higher version
of mysql would retain the original encryption mode, unless we
have following condition during restore,
a) User misses TABLE_ENCRYPTION_ADMIN privilege
b) AND 'table-encryption-privilege-check' is 'Y'
Restore failure case 1)
CREATE DATABASE|TABLESPACE with explicit ENCRYPTION clause will fail
if the DATABASE|TABLESPACE encryption type does not match
'default-table-encryption' type and if a) and b) are true.
Restore failure case 2)
CREATE TABLE with explicit ENCRYPTION clause will fail if
the encryption type does not match database encryption type
and if a) and b) are true.
Q) Is there a way to avoid this create table from failing ?
user would need atleast one of a) or b).
Perhaps the restore option should be run by a user with
higher rights?
2.1) Single-table dump-restores might not preserve original
encryption='N' property if per-database default or global
default on target system differ from source system.
2.2) In the scope of this WL, we assume that general tablespaces are
restored with correct encryption property.
G) UPGRADE AND DOWNGRADE:
1. Upgrade from older 8.0 version to 8.0 with WL12261 would
succeed and may not be affected by both
'default-table-encrpytion' and 'table-encryption-privilege-check'
settings. Because these defaults will affect only new
objects that are created.
Any new objects created during internal upgrade process
would not be affected by user provided settings for
'default-table-encrpytion' and 'table-encryption-privilege-check'.
The internal upgrade procedure would consider setting two
variables as 'false'.
Details:
a Schema default encryption would be stored as mentioned in I.A.3).
As this is a new DD column, it gets the default value as
'No' for all schema's and this is a expected value to have after
upgrade.
b Tablespace encryption values from older 8.0 would be stored
in mysql.tablespaces.options. The upgrade process would store
the clause ENCRYPTION='N', for all unencrypted tablespace that
were originally created in older 8.0 without ENCRYPTION clause.
c Tables using file-per-table tables would retain the encryption
flag in mysql.tables.options with key 'encryption'.
d Tables using general encryption tablespace shall be updated
with key encryption='y' in mysql.tables.options.
e The upgrade process shall store ENCRYPTION='N' clause for all
the following unencrypted objects,
- Tables in general tablespace.
- Tables in file-per-table tablespace.
f Remove existing 'encryption' clause if stored for following items,
- Tables in SEs which do not support encryption.
- Tablespace in SEs which do not support encryption.
2. Upgrade from 5.7 version to 8.0 with WL12261 will force
--table-encryption-privilege-check='N' during upgrade.
Otherwise, it is bit confusing to users.
3. Any new objects created during internal upgrade from 5.7
instances would not be affected by user provided settings
for 'default-table-encrpytion' and 'table-encryption-privilege-check'.
The upgrade procedure would consider both the variables
'default-table-encryption' and 'table-encryption-privilege-check'
as 'false'. There by we get following behavior.
This also means that, these settings would not affect
encryption used for 'mysql' system tablespace. That is, it
remains unencrypted during server startup, regardless of these
settings. Mainly because 'default-table-encrpytion' is meant
to govern user objects and not system object. The encryption
of 'mysql' can be managed as defined in WL#12063.
Details:
a Schema default encryption would be stored as mentioned in I.A.3).
As this is a new DD column, it gets the default value as
'No' for all schema's and this is a expected value to have after
upgrade.
b The upgrade process would store the clause ENCRYPTION='N', for all
general tablespace, as there are no encrypted tablespaces possible
in 5.7.
c Tables using file-per-table tables would retain the encryption
flag in mysql.tables.options with key 'encryption'.
d The upgrade process shall store ENCRYPTION='N' clause for all
the following unencrypted objects,
- Tables in file-per-table tablespace.
e Remove existing 'encryption' clause if stored for following items,
- Tables in SEs which do not support encryption.
- Tablespace in SEs which do not support encryption.
4. DOWNGRADE is not supported as of now.
H) REPLICATION:
1. The new DEFAULT ENCRYPTION clause for CREATE DATABASE would
work fine in replication environment. In master-slave
replication or even in group replication, as we do not
replicate logs from new server to a old server.
2. Changes required:
2.1) To support correct replication of CREATE DATABASE/TABLESPACE DDLs
without explicit ENCRYPTION clause between servers with different
values of 'default-table-encryption' options we need to store value
of this system variable in the binlog event of these DDLs.
2.2) In Group Replication setups we need to avoid problems which can occurs
after failover or in multi-primary node if some servers in group are
using different "--default-table-encryption" values.
We will use existing GR mechanism to enforce that all group replication
server nodes have the same value for 'default-table-encryption' system
variable.
I) PERFORMANCE:
There shouldn't be any performance issues caused by this WL changes.
J) DOCUMENTATION:
Yes, changes are required. FR's should help understand the changes.
I) API's introduced:
This API is especially used to ask SE the type of predefined
tablespace names like innodb_file_per_table and innodb_system.
/**
Get the tablespace type given the name, from the SE.
@param[in] tablespace_name tablespace name
@param[out] space_type type of space
@return Operation status.
@retval == 0 Success.
@retval != 0 Error (unknown space type, no error code returned)
*/
typedef bool (*get_tablespace_type_by_name_t)(const char *tablespace_name,
Tablespace_type *space_type);
Copyright (c) 2000, 2025, Oracle Corporation and/or its affiliates. All rights reserved.