MySQL静态数据加密和企业版TDE

小编:啊南 244阅读 2020.11.21

MySQL支持静态数据加密。静态数据加密的目的是为了防止保存在磁盘上的文件被非法盗用,使用该功能可以确保数据库的表空间,日志等文件即使是被盗用,也无法读取里面的敏感数据。

InnoDB通过两层密钥架构实现静态数据加密功能。当表空间文件进行加密时,会产生一个加密的表空间密钥,该密钥保存在表空间文件的文件头。当应用程序或者合法用户对表进行访问时,InnoDB会使用一个主密钥将加密的表空间密钥解密。主密钥可以进行轮换,表空间密钥无法更改,除非对表空间重新进行加密。

静态数据加密功能依靠MySQL的keyring plugin(暂且叫做钥匙环插件吧,密钥全部保存在钥匙环里,挺形象的)实现。目前,MySQL提供如下插件:

  • keyring_file:社区版提供,将钥匙环数据保存在本地的文件。
  • keyring_encrypted_file:企业版提供,将钥匙环数据保存在本地的加密文件。
  • keyring_okv:企业版提供,包含一个KMIP客户端,提供一个兼容KMIP协议的集中管理解决方案,例如,Oracle Key Vault, Gemalto KeySecure等。
  • keyring_aws:企业版提供,与Amazon Web Services Key Management Service 通信,用于后端存储。
  • keyring_hashicorp:企业版提供,与HashiCorp Vault通信,用于后端存储。

一个安全可靠的加密密钥管理解决方案对于安全性和合规要求都是至关重要的。需要注意的是,使用keyring_file 和 keyring_encrypted file 插件时,无法满足某些规范要求的密钥集中管理,因此,当静态加密功能使用集中式密钥管理解决方案时,该特性被称为“MySQL企业透明数据加密(TDE)”。

接下来,将通过一组演示,为大家介绍静态加密的功能和使用方法。由于不具备集中保管密钥的条件,只能使用keyring_encrypted_file的方式进行演示。演示内容包括,安装keyring插件,安装UDF,UDF的目的是通过SQL管理密钥,加密表空间文件,加密redo日志,加密binlog,主密钥轮换。

首先,我们在MySQL里面创建一张表。表名为"tde",非常简单的一张表。

接下来,往里面插入一条记录:

数据已经写入表中了,这时我还没有安装keyring插件,让我们看看表空间文件里能否查到我这条记录:

执行 xxd /usr/local/mysql_old/3310/test/tde.ibd | less可以查看并检索表空间文件里是否包含刚才插入的字符。

果然,表空间文件里存在着刚才插入的记录,如果这是一个敏感数据,则用户就会面临着风险。接下来,我将在服务器里安装插件和UDF。安装其实也非常简单,首先需要创建一个路径用以保存钥匙环。

mkdir -p /opt/mysql-keyring/

chown -R mysql:mysql /opt/mysql-keyring

其次,打开mysql的配置文件my.cnf,在[mysqld]的下面添加如下内容:

early-plugin-load=keyring_encrypted_file.so

keyring_encrypted_file_data=/opt/mysql-keyring/keyring

keyring_encrypted_file_password=password

这里需要注意的是,keyring插件要在服务器启动之前加载,并且只能选择使用一种keyring插件,另外一点,加密的keyring文件密码保存在了配置文件里,因此要严格注意配置文件的访问权限。

执行:INSTALL PLUGIN keyring_udf SONAME 'keyring_udf.so';

安装以后,可以看到插件已经激活。接下来安装一组UDF:

这些UDF用于管理密钥,举个例子看一下,使用kering_key_generate来生成一个密钥,然后再通过keyring_key_fetch查看一下密钥:

下面,我们开启加密,执行:alter table test.tde encryption ='y';

我们再次看看加密情况和表空间文件的内容:

开启加密之后,表空间文件的内容里,已经查找不到我的名字。

表空间的加密演示结束,接下来演示一下redo日志的加密。让我们先看一下redo日志里面的内容。

执行:mysql> \! xxd /usr/local/mysql_old/3310/ib_logfile0 |less

没有加密之前,是可以在redo日志里面找到相关记录的。确认一下参数值,开启加密:

插入第二条记录:

再次确认一下redo日志里面的内容,已经无法找到第二条记录。

接下来,我们开启binlgo加密,在开启之前,先确认一下日志的加密情况。

开启加密:

插入一条新纪录:

再次确认一下日志加密情况,最新的日志已经被加密:

使用mysqlbinlog工具查看日志内容,注意,由于日志格式的原因,需要指定-v才能看到相应的SQL语句。

日志已经显示被加密无法读取。

最后一个环节,让我们看一下如何管理密钥,进行主密钥轮换。

可以通过performance_schema里面的keyring_keys查看当前密钥:内容包括ID,所有者信息。

可以对InnoDB和binlog的主密钥执行轮换:

alter instance rotate innodb master key;

alter instance rotate binlog master key;

需要注意的是,不要在服务器运行和正在启动时轮换密钥,可能会发生无法读取数据的情况,造成数据丢失事故。

关联标签: