InnoDB Tablespace Encryption
InnoDB支持对存储file-per-table表空间中的InnoDB表中的数据进行加密。该特性为物理表空间数据文件提供静态加密。
InnoDB表空间加密使用两层加密密钥架构,由主加密密钥和表空间密钥组成。当一个InnoDB表被加密时,表空间密钥被加密并存储在表空间头中。当应用程序或经过认证的用户想要访问加密的表空间数据时,InnoDB使用一个主加密密钥来解密表空间密钥。表空间密钥的解密版本永远不会改变,但主加密密钥可以根据需要改变。此操作称为主键旋转。
InnoDB表空间加密特性依赖于keyring插件进行主加密密钥管理。
所有MySQL版本都提供了keyring_file插件,该插件将主加密密钥数据存储在keyring_file_data配置选项指定的位置的keyring文件中。
非企业版MySQL中的InnoDB表空间加密特性使用keyring_file插件进行加密密钥管理,这并不是一个符合法规的解决方案。安全标准,如PCI,FIPS和其他要求使用密钥管理系统来保护、管理和保护密钥库或硬件安全模块(hsm)中的加密密钥。
MySQL企业版提供了keyring_okv插件,其中包括一个KMIP客户端(KMIP 1.1),它与Oracle密钥库(OKV)一起工作,提供加密密钥管理。当InnoDB表空间加密使用OKV进行加密密钥管理时,该特性被称为“MySQL企业”透明数据加密(TDE)。
一个安全、健壮的加密密钥管理解决方案(如OKV)对于安全性和符合各种安全标准至关重要。在其他好处中,使用密钥库可确保密钥安全存储,永远不会丢失,并且只有授权的密钥管理员知道。密钥库还维护加密密钥历史记录
InnoDB表空间加密支持AES (Advanced encryption Standard)块加密算法。它采用ECB (Electronic Codebook)块加密方式对表空间密钥进行加密CBC (Cipher Block chainaining)块加密方式,用于数据加密
InnoDB表空间加密前提条件
必须安装和配置keyring插件(keyring_file插件或keyring_okv插件)。Keyring插件安装在启动时使用–early-plugin-load选项执行。提前加载可以确保插件在InnoDB存储引擎初始化之前可用。
一次只能启用一个keyring插件。不支持启用多个密匙环插件。
一旦在MySQL实例中创建了加密表,在创建加密表时加载的keyring插件必须在InnoDB初始化之前使用–early-plugin-load选项继续加载。如果不这样做,会导致启动和恢复InnoDB时出现错误。
启用加密模块
mysql> INSTALL PLUGIN keyring_file soname 'keyring_file.so'; Query OK, 0 rows affected (0.09 sec)
创建密钥文件目录
[mysql@localhost ~]$ mkdir -p /mysqldata/mysql/mysql-keyring/ [mysql@localhost ~]$ chown -R mysql:mysql /mysqldata/mysql/mysql-keyring/ [mysql@localhost ~]$ chmod -R 775 /mysqldata/mysql/mysql-keyring/
设置加密key存放路径
mysql> set global keyring_file_data='/mysqldata/mysql/mysql-keyring/keyring'; Query OK, 0 rows affected (0.00 sec)
永久启用设置
上诉两个步骤都是临时的,重启服务都会失效,我们把配置写到配置文件里,确保重启服务后也能生效
[mysqld] early-plugin-load=keyring_file.so keyring_file_data=/mysqldata/mysql/mysql-keyring/keyring
查看key的存放路径
mysql> show global variables like '%keyring_file_data%'; +-------------------+----------------------------------------+ | Variable_name | Value | +-------------------+----------------------------------------+ | keyring_file_data | /mysqldata/mysql/mysql-keyring/keyring | +-------------------+----------------------------------------+ 1 row in set (0.02 sec)
要验证keyring插件是否处于活动状态,请使用SHOW PLUGINS语句或查询INFORMATION_SCHEMA.PLUGINS表。例如:
mysql> show plugins; +----------------------------+----------+--------------------+-----------------+---------+ | Name | Status | Type | Library | License | +----------------------------+----------+--------------------+-----------------+---------+ | keyring_file | ACTIVE | KEYRING | keyring_file.so | GPL | | binlog | ACTIVE | STORAGE ENGINE | NULL | GPL | | mysql_native_password | ACTIVE | AUTHENTICATION | NULL | GPL | | sha256_password | ACTIVE | AUTHENTICATION | NULL | GPL | | CSV | ACTIVE | STORAGE ENGINE | NULL | GPL | | MEMORY | ACTIVE | STORAGE ENGINE | NULL | GPL | | InnoDB | ACTIVE | STORAGE ENGINE | NULL | GPL | | INNODB_TRX | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_LOCKS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_LOCK_WAITS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_CMP | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_CMP_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_CMPMEM | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_CMPMEM_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_CMP_PER_INDEX | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_CMP_PER_INDEX_RESET | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_BUFFER_PAGE | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_BUFFER_PAGE_LRU | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_BUFFER_POOL_STATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_TEMP_TABLE_INFO | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_METRICS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_FT_DEFAULT_STOPWORD | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_FT_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_FT_BEING_DELETED | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_FT_CONFIG | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_FT_INDEX_CACHE | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_FT_INDEX_TABLE | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_TABLES | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_TABLESTATS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_INDEXES | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_COLUMNS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_FIELDS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_FOREIGN | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_FOREIGN_COLS | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_TABLESPACES | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_DATAFILES | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | INNODB_SYS_VIRTUAL | ACTIVE | INFORMATION SCHEMA | NULL | GPL | | MyISAM | ACTIVE | STORAGE ENGINE | NULL | GPL | | MRG_MYISAM | ACTIVE | STORAGE ENGINE | NULL | GPL | | PERFORMANCE_SCHEMA | ACTIVE | STORAGE ENGINE | NULL | GPL | | ARCHIVE | ACTIVE | STORAGE ENGINE | NULL | GPL | | BLACKHOLE | ACTIVE | STORAGE ENGINE | NULL | GPL | | FEDERATED | DISABLED | STORAGE ENGINE | NULL | GPL | | partition | ACTIVE | STORAGE ENGINE | NULL | GPL | | ngram | ACTIVE | FTPARSER | NULL | GPL | +----------------------------+----------+--------------------+-----------------+---------+ mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS -> FROM INFORMATION_SCHEMA.PLUGINS -> WHERE PLUGIN_NAME LIKE 'keyring%'; +--------------+---------------+ | PLUGIN_NAME | PLUGIN_STATUS | +--------------+---------------+ | keyring_file | ACTIVE | +--------------+---------------+ 1 row in set (0.00 sec)
必须启用innodb_file_per_table选项(默认值)。InnoDB表空间加密只支持每表一个文件的表空间。或者,您可以指定TABLESPACE=’innodb_file_per_table’选项,用于创建加密表或修改现有表以启用加密。
mysql> show variables like '%innodb_file_per_table%'; +-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | innodb_file_per_table | ON | +-----------------------+-------+ 1 row in set (0.01 sec)
在对生产数据使用InnoDB表空间加密特性之前,请确保已采取措施防止丢失主加密密钥。如果主加密密钥丢失,则无法恢复加密表空间文件中存储的数据。如果您正在使用keyring_file插件,建议您在创建第一个加密表之后以及主密钥旋转前后立即创建keyring文件的备份。keyring文件位置由keyring_file_data配置选项定义。如果您正在使用keyring_okv插件,请确保您已经执行了必要的keyring_okv插件和Oracle密钥库(OKV)配置。
开启和关闭InnoDB表空间加密
要为一个新的InnoDB表启用加密,在create table语句中指定encryption选项。
mysql> CREATE TABLE t1 (c1 INT) ENCRYPTION='Y'; Query OK, 0 rows affected (0.01 sec)
要对现有的InnoDB表启用加密,请在alter table语句中指定encryption选项。
mysql> alter table abc encryption='y'; Query OK, 1 row affected (0.04 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> show create table abc; +-------+-------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-------------------------------------------------------------------------------------------------------------------------+ | abc | CREATE TABLE `abc` ( `a` int(11) NOT NULL, PRIMARY KEY (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ENCRYPTION='y' | +-------+-------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
使用alter table设置encryption =’N’来禁用InnoDB表的加密功能
mysql> alter table abc encryption='n'; Query OK, 1 row affected (0.02 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> show create table abc; +-------+-------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-------------------------------------------------------------------------------------------------------------------------+ | abc | CREATE TABLE `abc` ( `a` int(11) NOT NULL, PRIMARY KEY (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ENCRYPTION='n' | +-------+-------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
InnoDB表空间加密和主密钥轮换
主加密密钥应该定期轮换,只要您怀疑密钥可能已被泄露。
主密钥轮换是一个原子的实例级操作。每次轮换主加密密钥时,MySQL实例中的所有表空间密钥都将重新加密并保存回各自的表空间头中。作为原子操作,一旦启动轮换操作,所有表空间密钥都必须重新加密成功。如果主密钥轮换因服务器故障而中断,InnoDB将在服务器重启时前滚该操作。
轮换主加密密钥只会更改主加密密钥并重新加密表空间密钥。它不解密或重新加密相关的表空间数据
轮换主加密密钥,执行以下命令:
[root@localhost ~]# cd /mysqldata/mysql/mysql-keyring/ [root@localhost mysql-keyring]# ll total 4 -rw-r-----. 1 mysql mysql 155 Mar 3 17:20 keyring mysql> ALTER INSTANCE ROTATE INNODB MASTER KEY; Query OK, 0 rows affected (0.00 sec) [root@localhost mysql-keyring]# ll total 4 -rw-r-----. 1 mysql mysql 283 Mar 10 15:58 keyring
alter instance rotate innodb master key支持并发DML。但是,它不能与create table … encryption或alter table … encryption操作一起并发执行,采用锁来防止这些语句并发执行时可能产生的冲突。如果一个冲突的语句正在运行,那么它必须在另一个语句运行之前完成。
InnoDB表空间加密与恢复
ALTER INSTANCE ROTATE INNODB MASTER KEY语句仅在主数据库和从数据库所运行的MySQL版本支持表空间加密特性的复制环境中被支持。
成功的ALTER INSTANCE ROTATE INNODB MASTER KEY语句被写入二进制日志,用于在slave上复制。
如果一个ALTER INSTANCE ROTATE INNODB MASTER KEY语句失败,它不会被记录到二进制日志中,也不会被复制到slave上。
如果keyring插件安装在主节点上而从节点没有安装,复制ALTER INSTANCE ROTATE INNODB MASTER KEY操作失败。
如果keyring_file插件同时安装在主服务器和从服务器上,但是从服务器上没有keyring文件,假设keyring文件数据没有缓存在内存中,复制的ALTER INSTANCE ROTATE INNODB MASTER KEY语句将在从服务器上创建keyring文件。如果可用的话,ALTER INSTANCE INNODB MASTER KEY使用缓存在内存中的keyring文件数据。
识别使用InnoDB表空间加密的表
当在CREATE TABLE或ALTER TABLE语句中指定了ENCRYPTION选项时,它将记录在INFORMATION_SCHEMA.TABLES的CREATE_OPTIONS字段中。可以查询该字段以识别MySQL实例中的加密表。
mysql> SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES -> WHERE CREATE_OPTIONS LIKE '%ENCRYPTION="Y"%'; +--------------+------------+-------------------------------------------------------+ | TABLE_SCHEMA | TABLE_NAME | CREATE_OPTIONS | +--------------+------------+-------------------------------------------------------+ | test | t1 | ENCRYPTION="Y" | | test | ts02 | row_format=COMPRESSED KEY_BLOCK_SIZE=4 ENCRYPTION="Y" | | test | ts03 | COMPRESSION="zlib" ENCRYPTION="Y" | +--------------+------------+-------------------------------------------------------+ 3 rows in set (0.42 sec)
InnoDB表空间加密使用说明
a.如果服务器在正常运行期间退出或停止,建议使用之前配置的相同加密设置重新启动服务器。
b.第一个主加密密钥是在对第一个新表或现有表进行加密时生成的。
c.主密钥轮换会重新加密表空间密钥,但不会改变表空间密钥本身。要更改表空间密钥,必须使用alter table tbl_name encryption禁用并重新启用表加密,这是一个ALGORITHM=COPY操作来重建表。
d.Keyring_file插件使用说明
如果keyring文件为空或缺失,第一次执行ALTER INSTANCE ROTATE INNODB MASTER KEY将创建一个主加密密钥。
卸载keyring_file插件不会删除现有的keyring文件。
建议不要将keyring文件与表空间数据文件放在同一个目录下。keyring文件的位置由keyring_file_data选项指定。
在运行时修改keyring_file_data选项或使用新的keyring_file_data设置重新启动服务器可能导致以前加密的表不可访问,从而导致数据丢失。
InnoDB表空间加密限制
.系统目前只支持AES (Advanced Encryption Standard)加密算法。InnoDB表空间加密使用ECB (Electronic Codebook)块加密方式对表空间密钥进行加密,使用CBC (Cipher block Chaining)块加密方式对数据进行加密。
.修改表的ENCRYPTION属性是一个ALGORITHM=COPY操作。不支持ALGORITHM=INPLACE。
.InnoDB表空间加密只支持存储在file-per-table表空间中的InnoDB表。存储在其他InnoDB表空间类型中的表不支持加密,包括普通表空间、系统表空间、undo log表空间和临时表空间。
.不能将加密表从file-per-table表空间移动或复制到不支持的InnoDB表空间类型。
.表空间加密只适用于表空间中的数据。重做日志、undo日志或二进制日志中的数据不加密。
.目前不支持直接从keyring_file插件迁移到keyring_okv插件,反之亦然。更改密匙环插件需要解密表,卸载当前的密匙环插件,安装和配置其他密匙环插件,并重新加密表。