17.13 InnoDB 静态数据加密
InnoDB
支持文件-per-表表空间、公共表空间、mysql
系统表空间、redo日志和undo日志的静态数据加密。
您可以为模式和公共表空间设置加密默认值,这样DBAs就可以控制在这些模式和表空间中创建的表是否加密。
InnoDB
静态数据加密功能和能力在本节下面的主题中进行描述。
InnoDB
使用了两级加密密钥架构,包括主加密密钥和表空间密钥。当一个表空间被加密时,表空间密钥将被加密并存储在表空间头部。应用程序或认证用户想要访问加密表空间数据时,InnoDB
使用主加密密钥来解密表空间密钥。解密后的表空间密钥从不改变,但主加密密钥可以根据需要更改。这一操作称为master key rotation。
数据静态加密特性依赖于keyring组件或插件来管理主加密密钥。
所有MySQL版本都提供了component_
keyring_file
组件,该组件将keyring数据存储在服务器主机的本地文件中。
MySQL Enterprise Edition还提供了额外的keyring组件和插件:
-
component_
keyring_encrypted_file
:将keyring数据存储在加密、密码保护的本地文件中。 -
keyring_okv
:KMIP 1.1插件,用于与KMIP兼容的后端keyring存储产品。支持的KMIP兼容产品包括中央化密钥管理解决方案,如Oracle Key Vault、Gemalto KeySecure、Thales Vormetric密钥管理服务器和Fornetix Key Orchestration。 -
keyring_aws
:与Amazon Web Services Key Management Service(AWS KMS)通信,以便在后端生成密钥,并使用本地文件存储密钥。 -
keyring_hashicorp
:与HashiCorp Vault通信,以便在后端存储密钥。
为了加密密钥管理,component_keyring_file
和 component_keyring_encrypted_file
组件不是作为法规遵从性解决方案。安全标准,如PCI、FIPS等,要求使用密钥管理系统来保护和管理加密密钥,在密钥库或硬件安全模块(HSM)中。
一个安全且robust的加密密钥管理解决方案对于安全和遵从各种安全标准是至关重要的。当数据静态加密特性使用集中式密钥管理解决方案时,该特性被称为“MySQL Enterprise Transparent Data Encryption(TDE)”。
数据静态加密特性支持Advanced Encryption Standard(AES)块加密算法。它使用Electronic Codebook(ECB)块加密模式对表空间密钥进行加密,并使用Cipher Block Chaining(CBC)块加密模式对数据进行加密。
关于数据静态加密特性的常见问题,请参阅第A.17节,“MySQL 8.4 FAQ: InnoDB Data-at-Rest Encryption”。
-
必须在启动时安装和配置密钥ring组件或插件。早期加载确保组件或插件在InnoDB存储引擎初始化之前可用。关于密钥ring安装和配置的指南,请参阅第8.4.4节,“The MySQL Keyring”。该指南显示如何确保选择的组件或插件处于活动状态。
在 MySQL 实例中,只能启用一个密钥环组件或插件。启用多个密钥环组件或插件是未支持的,可能会导致结果与预期不同。
Important创建加密表空间后,在 MySQL 实例启动时,用于创建加密表空间的密钥环组件或插件必须继续被加载。如果否则,服务器启动和 InnoDB 恢复过程中将出现错误。
-
在生产数据加密时,请确保采取措施防止主加密密钥丢失。如果主加密密钥丢失,存储在加密表空间文件中的数据将不可恢复。如果使用
component_
或keyring_
组件,请立即备份密钥环数据文件,在创建第一个加密表空间后、主密钥轮转前和主密钥轮转后。每个组件的配置文件中都指明了数据文件的位置。如果使用keyring_
插件,请确保已经进行了必要的配置。详细信息请见第8.4.4节,“MySQL密钥环”。
为模式和一般表空间定义加密默认值
default_table_encryption
系统变量定义了对架构和公共表空间的默认加密设置。CREATE TABLESPACE
和CREATE SCHEMA
操作在不指定明确的ENCRYPTION
子句时将应用default_table_encryption
设置。
ALTER SCHEMA
和ALTER TABLESPACE
操作不应用default_table_encryption
设置。要更改现有架构或公共表空间的加密,必须指定明确的ENCRYPTION
子句。
可以使用default_table_encryption
变量在个体客户端连接或全局设置。例如,以下语句将对架构和公共表空间的加密设置为全局:
mysql> SET GLOBAL default_table_encryption=ON;
可以使用DEFAULT ENCRYPTION
子句在创建或修改架构时定义默认加密设置,例如:
mysql> CREATE SCHEMA test DEFAULT ENCRYPTION = 'Y';
如果在创建架构时未指定DEFAULT ENCRYPTION
子句,則将应用default_表_加密
设置。要修改现有架构的默认加密设置,必须指定DEFAULT ENCRYPTION
子句;否则,架构将保留其当前加密设置。
默认情况下,表继承了它创建时所在架构或公共表空间的加密设置。例如,在加密启用的架构中创建的表默认是加密的。这一行为使DBA能够通过定义和强制架构和公共表空间加密默认来控制表加密使用。
加密默认值由启用table_encryption_privilege_check
系统变量来强制执行。当table_encryption_privilege_check
启用时,在创建或更改具有不同加密设置的架构或通用表空间、或创建或更改与默认架构加密不同的表时,会发生权限检查。当table_encryption_privilege_check
禁用(默认)时,不会发生权限检查,并且将在警告中继续执行前述操作。
需要TABLE_ENCRYPTION_ADMIN
特权来覆盖默认加密设置,当table_encryption_privilege_check
启用时。DBA可以授予该特权,以便用户在创建或更改架构或通用表空间时,可以偏离default_table_encryption
设置,也可以偏离默认架构加密when创建或更改表。该特权不允许在创建或更改表时偏离通用表空间的加密设置。表必须与其所在的通用表空间具有相同的加密设置。
File-Per-Table 表space 加密
文件表空间继承了在创建该表时的架构的默认加密设置,除非在CREATE TABLE
语句中指定了明确的ENCRYPTION
子句。
mysql> CREATE TABLE t1 (c1 INT) ENCRYPTION = 'Y';
要更改现有文件表空间的加密设置,必须指定ENCRYPTION
子句。
mysql> ALTER TABLE t1 ENCRYPTION = 'Y';
table_encryption_privilege_check
已启用,指定与默认架构加密不同的ENCRYPTION
子句需要TABLE_ENCRYPTION_ADMIN
权限。请参阅定义架构和一般表空间的加密默认值。
一般表space 加密
default_table_encryption
变量确定新创建的一般表space 的加密,除非在CREATE TABLESPACE
语句中显式指定ENCRYPTION
子句。
mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' ENCRYPTION = 'Y' Engine=InnoDB;
要更改现有一般表space 的加密,必须指定ENCRYPTION
子句。
mysql> ALTER TABLESPACE ts1 ENCRYPTION = 'Y';
如果启用了table_encryption_privilege_check
,指定一个与default_table_encryption
设置不同的ENCRYPTION
子句需要TABLE_ENCRYPTION_ADMIN
权限。请参阅定义 schema 和通用表空间的加密默认值。
在 MySQL 8.4 中,InnoDB
自动将属于加密表空间的双写文件页加密。无需执行任何操作。使用关联表空间的加密密钥加密的双写文件页写入到表空间数据文件中也会被写入到双写文件中。属于未加密表空间的双写文件页保持未加密状态。
在恢复过程中, 加密的双写文件页将被解密并检查是否损坏。
mysql 系统表空间加密
MySQL系统表空间包含mysql
系统数据库和 MySQL 数据字典表。默认情况下,它是未加密的。要为mysql
系统表空间启用加密,请在ALTER TABLESPACE
语句中指定表空间名称和ENCRYPTION
选项。
mysql> ALTER TABLESPACE mysql ENCRYPTION = 'Y';
要禁用mysql
系统表空间的加密,请使用ALTER TABLESPACE
语句将ENCRYPTION = 'N'
设置为'N'
。
mysql> ALTER TABLESPACE mysql ENCRYPTION = 'N';
启用或禁用mysql
系统表空间的加密需要在实例中拥有CREATE TABLESPACE
特权权限(CREATE TABLESPACE on *.*)
)。
重做日志加密
使用innodb_redo_log_encrypt
配置选项启用重做日志加密。默认情况下,重做日志加密是禁用的。
与表空间数据类似,重做日志数据加密发生在写入磁盘时,解密发生在读取磁盘时。从磁盘读取到内存后,重做日志数据将变为未加密的形式。重做日志数据使用表空间加密密钥进行加密和解密。
当innodb_redo_log_encrypt
启用时,磁盘上存在的未加密redo日志页将保持未加密状态,而新的redo日志页将以加密形式写入磁盘。同样,当innodb_redo_log_encrypt
禁用时,磁盘上存在的加密redo日志页将保持加密状态,而新的redo日志页将以未加密形式写入磁盘。
redo日志加密元数据,包括表空间加密密钥,在redo日志文件中最 recent 检查点LSN的头部存储。如果删除了包含加密元数据的redo日志文件,redo日志加密将被禁用。
启用redo日志加密后,正常启动不可能,因为InnoDB
在启动时必须能够扫描redo页,这在redo页加密的情况下不可行。没有keyring组件或插件或加密密钥,只能强制启动,不使用redo日志(SRV_FORCE_NO_LOG_REDO
)。请参阅第17.20.3节,“强制InnoDB恢复”。
undo日志数据加密使用innodb_undo_log_encrypt
配置选项启用。undo日志加密适用于undo表空间中的undo日志。请参阅第17.6.3.4节,“Undo Tablespaces”。undo日志数据加密默认处于禁用状态。
与表空间数据类似,undo日志数据加密发生在写入磁盘时,并在读取磁盘时解密。将undo日志数据读入内存后,它将变为未加密形式。undo日志数据使用表空间加密密钥进行加密和解密。
当innodb_undo_log_encrypt
启用时,磁盘上存在未加密的undo日志页将保持未加密状态,而新的undo日志页将写入磁盘以加密形式。相反,当innodb_undo_log_encrypt
禁用时,磁盘上存在加密的undo日志页将保持加密状态,而新的undo日志页将写入磁盘以未加密形式。
undo日志加密元数据,包括表空间加密密钥,在undo日志文件头中存储。
当undo日志加密disabled时,服务器将继续要求用于加密undo日志数据的keyring组件或插件,直到包含加密undo日志数据的undo表空间被截断。 (只有在undo表空间被截断时,undo表空间中的加密头部才会被删除。) 关于截断undo表空间的信息,请参见截断Undo表空间。
主密钥应该定期旋转,并且在您怀疑密钥已被 compromised时旋转。
主密钥旋转是一个原子、实例级别的操作。每次旋转主密钥时,MySQL实例中的所有表空间密钥都会重新加密并保存回其相应的表空间头部。作为原子操作,重新加密必须在旋转操作开始后成功完成。如果主密钥旋转被中断由服务器故障,InnoDB
将在服务器重启时滚回操作。更多信息,请参见加密和恢复。
旋转主密钥只改变主密钥并重新加密表空间密钥,不会解密或重新加密相关的表空间数据。
旋转主密钥需要ENCRYPTION_KEY_ADMIN
特权(或弃用的SUPER
特权)。
要旋转主密钥,请运行:
mysql> ALTER INSTANCE ROTATE INNODB MASTER KEY;
ALTER INSTANCE ROTATE INNODB MASTER KEY
支持并发DML操作。但是,它不能与表空间加密操作同时执行,并且会锁定以防止可能出现的冲突。如果正在运行ALTER INSTANCE ROTATE INNODB MASTER KEY
操作,它必须完成后才能继续表空间加密操作,反之亦然。
如果在加密操作期间服务器出现故障,操作将在服务器重启时回滚。对于一般表空间,加密操作将在后台线程中从最后处理的页面恢复。
如果在主密钥轮转期间服务器出现故障,InnoDB
将在服务器重启时继续该操作。
keyring组件或插件必须在存储引擎初始化之前加载,以便从表空间头部中检索必要的信息以解密表空间数据页。 (请参阅加密前提。)
当InnoDB
初始化和恢复开始时,主密钥轮换操作将继续。由于服务器故障,一些表空间密钥可能已经使用新的主加密密钥进行加密。InnoDB
从每个表空间头部读取加密数据,如果数据表明该表空间密钥使用的是旧的主加密密钥,InnoDB
从密钥环中检索旧密钥并使用它来解密表空间密钥。InnoDB
然后将表空间密钥重新加密使用新的主加密密钥,并将重新加密后的表空间密钥保存回表空间头部。
导出加密的表空间
仅支持文件-per-表文件表空间的导出。
当导出加密的表空间时,InnoDB
将生成一个transfer key用于加密表空间密钥。加密后的表空间密钥和 transfer key 将存储在一个
文件中。这两个文件一起需要执行导入操作。在导入时,tablespace_name
.cfpInnoDB
将使用 transfer key 解密表空间密钥在
文件中。有关相关信息,请参见第17.6.1.3节,“导入InnoDB表”。tablespace_name
.cfp
加密和复制
-
只有在支持表空间加密的 MySQL 版本中,才支持
ALTER INSTANCE ROTATE INNODB MASTER KEY
语句。 -
成功执行
ALTER INSTANCE ROTATE INNODB MASTER KEY
语句的日志将被写入二进制日志,以便在复制中传播到副本。 -
如果
ALTER INSTANCE ROTATE INNODB MASTER KEY
语句失败,它将不会被写入二进制日志,也不会在副本中传播。 -
如果源服务器安装了密钥环组件或插件,但副本没有安装,
ALTER INSTANCE ROTATE INNODB MASTER KEY
操作将失败。
识别加密的表空间和模式
信息_schemaINNODB_TABLESPACES
表包含一个ENCRYPTION
列,可以用来识别加密的表空间。
mysql> SELECT SPACE, NAME, SPACE_TYPE, ENCRYPTION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
WHERE ENCRYPTION='Y'\G
*************************** 1. row ***************************
SPACE: 4294967294
NAME: mysql
SPACE_TYPE: General
ENCRYPTION: Y
*************************** 2. row ***************************
SPACE: 2
NAME: test/t1
SPACE_TYPE: Single
ENCRYPTION: Y
*************************** 3. row ***************************
SPACE: 3
NAME: ts1
SPACE_TYPE: General
ENCRYPTION: Y
在CREATE TABLE
或ALTER TABLE
语句中指定ENCRYPTION
选项时,它将被记录在INFORMATION_ SCHEMA.TABLES
的CREATE_OPTIONS
列中。这一列可以用来识别存储在加密文件表空间中的表。
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES
WHERE CREATE_OPTIONS LIKE '%ENCRYPTION%';
+--------------+------------+----------------+
| TABLE_SCHEMA | TABLE_NAME | CREATE_OPTIONS |
+--------------+------------+----------------+
| test | t1 | ENCRYPTION="Y" |
+--------------+------------+----------------+
查询INNODB_TABLESPACES
表以获取与特定架构和表相关联的表空间信息。
mysql> SELECT SPACE, NAME, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME='test/t1';
+-------+---------+------------+
| SPACE | NAME | SPACE_TYPE |
+-------+---------+------------+
| 3 | test/t1 | Single |
+-------+---------+------------+
可以通过查询SCHEMATA
表来识别加密启用的架构。
mysql> SELECT SCHEMA_NAME, DEFAULT_ENCRYPTION FROM INFORMATION_SCHEMA.SCHEMATA
WHERE DEFAULT_ENCRYPTION='YES';
+-------------+--------------------+
| SCHEMA_NAME | DEFAULT_ENCRYPTION |
+-------------+--------------------+
| test | YES |
+-------------+--------------------+
SHOW CREATE SCHEMA
也显示了DEFAULT ENCRYPTION
子句。
可以使用Performance Schema
来监控总体表空间和mysql
系统表空间加密进度。
stage/innodb/alter tablespace (加密)
阶段事件仪器报告了通用表空间加密操作的 WORK_ESTIMATED
和 WORK_COMPLETED
信息。
以下示例演示如何启用 stage/innodb/alter tablespace (加密)
阶段事件仪器和相关的消费者表,以监控通用表空间或 mysql
系统表空间加密进度。关于性能_schema 阶段事件仪器和相关消费者的信息,请见第29.12.5节,“性能_schema 阶段事件表”。
-
启用
stage/innodb/alter tablespace (加密)
仪器:mysql> USE performance_schema; mysql> UPDATE setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/alter tablespace (encryption)';
-
启用阶段事件消费者表,这些表包括
events_stages_current
、events_stages_history
和events_stages_history_long
。mysql> UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%stages%';
-
运行表空间加密操作。在这个示例中,一个通用表空间名为
ts1
被加密。mysql> ALTER TABLESPACE ts1 ENCRYPTION = 'Y';
-
通过查询性能chema的
events_stages_current
表来检查加密操作的进度。WORK_ESTIMATED
报告了总共有多少个页面在表空间中。WORK_COMPLETED
报告了已经处理的页面数量。mysql> SELECT EVENT_NAME, WORK_ESTIMATED, WORK_COMPLETED FROM events_stages_current; +--------------------------------------------+----------------+----------------+ | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED | +--------------------------------------------+----------------+----------------+ | stage/innodb/alter tablespace (encryption) | 1056 | 1407 | +--------------------------------------------+----------------+----------------+
如果加密操作已经完成,
events_stages_current
表将返回一个空集。在这种情况下,您可以查看events_stages_history
表,以查看已完成操作的事件数据。例如:mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_history; +--------------------------------------------+----------------+----------------+ | EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED | +--------------------------------------------+----------------+----------------+ | stage/innodb/alter tablespace (encryption) | 1407 | 1407 | +--------------------------------------------+----------------+----------------+
-
在使用
ENCRYPTION
选项对现有文件-每个表空间进行更改时,计划合适。文件-每个表空间中的表将使用COPY
算法重建。在更改ENCRYPTION
属性的通用表空间或mysql系统表空间时,将使用INPLACE
算法。INPLACE
算法允许对通用表空间中的表进行并发DML操作,但会阻止并发DDL操作。 -
当通用表空间或mysql系统表空间被加密时,所有在该表空间中的表都将被加密。类似地,在加密表空间中创建的表也将被加密。
-
在正常操作中,如果服务器退出或停止,建议使用之前配置的加密设置重新启动服务器。
-
第一个主密钥是在首次加密表空间时生成的。
-
主密钥轮换重新加密表空间密钥,但不改变表空间密钥本身。要更改表空间密钥,您必须禁用并重新启用加密。对于文件-每个表空间,重新加密表空间是一个
ALGORITHM=COPY
操作,该操作重建了表。对于一般表空间和mysql
系统表空间,它是一个ALGORITHM=INPLACE
操作,不需要重建在该表空间中的表。 -
如果创建一个同时具有
COMPRESSION
和ENCRYPTION
选项的表,压缩将在加密表空间数据之前进行。 -
卸载
component_keyring_file
或component_keyring_encrypted_file
组件不删除现有密钥环数据文件。 -
建议不要将密钥环数据文件置于表空间数据文件目录下。
-
加密支持InnoDB FULLTEXT索引表,这些表在添加FULLTEXT索引时隐式创建。有关相关信息,请参阅InnoDB Full-Text Index Tables。
-
高级加密标准(AES)是唯一支持的加密算法。
InnoDB
表空间加密使用电子密码本(ECB)块加密模式对表空间密钥进行加密,并使用加密块链(CBC)块加密模式对数据进行加密。没有使用padding与CBC块加密模式,而是InnoDB
确保要加密的文本是一个块大小的整数倍。 -
加密仅支持文件表空间、通用表空间和mysql系统表空间。对其他表空间类型,包括InnoDB系统表空间不支持加密。
-
您不能从加密的文件表空间、通用表空间或mysql系统表空间移动或复制表到不支持加密的表空间类型。
-
您不能从加密表空间移动或复制表到未加密表空间。然而,从未加密表空间移动或复制表到加密表空间是允许的。例如,您可以将未加密的文件表空间或通用表空间中的表移动或复制到加密的通用表空间。
-
默认情况下,表空间加密仅适用于表空间中的数据。redo日志和undo日志数据可以通过启用
innodb_redo_log_encrypt
和innodb_undo_log_encrypt
来加密。请参阅Redo Log 加密和Undo Log 加密。关于二进制日志文件和中继日志文件加密的信息,请参阅第19.3.2节,“ Encrypting Binary Log Files and Relay Log Files”。 -
不能更改存储引擎的表,该表位于或曾经位于加密表空间中。