TXSQL是腾讯基础架构部数据库团队自研的MySQL分支,对腾讯云以及众多的内部业务提供了强大的数据库内核支撑。相比原生的MySQL,TXSQL在BINLOG复制和InnoDB存储引擎方面做了很多的优化,另外在Server层面也做了大量的工作。因此TXSQL拥有更好的性能,更好的稳定性和可维护性,以及更多的企业级特性。本文将对加密和审计这两个企业级特性进行详细的解读。
一、加密
这里的加密是指对存储在磁盘上数据的进行加密。对数据的通信进行加密MySQL很早就开始支持了。数据的加密操作是可以脱离数据库进行的,比如用户在插入一条数据时,对该数据进行加密;检索数据时,再对该数据进行解密操作。这样做存在两个问题:其一,加密数据在数据库中的查询效率低下:加密数据在数据库中很难进行相似性(like)查询,以及进行范围查询。其二,加密密钥的安全性问题由用户保证:密钥由用户维护和管理,增加了安全的风险和维护的难度。
1.1 MySQL数据加密
MySQL在5.7版本推出数据加密功能:透明数据加密(Transparent Data Encryption)。透明加密是指数据的加解密操作对用户透明。用户在创建加密表时,不用指定加密密钥。数据在写盘时加密,在读盘时解密。目前透明数据加密只支持InnoDB存储引擎。下面的语句创建了一个加密表:
CREATE TABLE t1 (c1 INT) ENGINE=InnoDB ENCRYPTION='Y';
其中,ENCRYPTION='Y'表示对该表的数据进行加密。那么数据是如何进行加解密的呢?
1.1.1两层密钥体系
我们在创建加密表的时候,会自动生成一个随机的表空间密钥(Tablespace Key)。数据由表空间密钥保护。当我们在加密表中插入一条记录,记录以明文插入到缓冲区(Buffer Pool)的数据页中。当数据页要写盘时,通过表空间密钥,对该页上的所有数据记录进行加密后再写盘。当请求的数据页不在缓冲区时,数据页从磁盘读入,通过表空间密钥,对数据页中所有记录进行解密之后,加入到缓冲区中。一句话:数据页在缓冲区中是明文,在磁盘上是密文。另外数据加密采用的加密算法是AES256。
表空间密钥是如何保存的?MySQL有一个全局的主密钥(Master Key), 主密钥有对应的ID(Master Key ID)。表空间密钥由主密钥保存。当表空间密钥生成后,通过主密钥加密,写入到表空间的第一个数据页中,和加密后的表空间密钥一同保存的还有主密钥的ID。当表空间第一次打开时,读取第一个数据页,通过主密钥ID,得到主密钥;然后通过主密钥对表空间密钥进行解密。
当系统运行之后,第一次创建加密表之前,全局的主密钥为空。创建加密表时,当主密钥为空,InnoDB会自动生成一个主密钥ID,由固定前缀加server uuid以及序号组成。通过主密钥管理接口,为主密钥ID生成一个对应的主密钥。
1.1.2 KEYRING密钥管理框架
主密钥的管理则是通过MySQL的KEYRING插件框架进行的。主要有四个接口:
- l my_key_fetch my_bool my_key_fetch(const char *key_id, const char **key_type, const char* user_id, void **key, size_t *key_len);
- l my_key_generate my_bool my_key_generate(const char *key_id, const char *key_type, const char *user_id, size_t key_len);
- l my_key_remove
- l my_key_store
我们可以把KEYRING框架理解为一个简单的Key-Value的store。上述InnoDB内部生成主密钥的过程是通过调用my_key_generate和my_key_fetch完成。
MySQL社区版本提供KEYRING插件的一个简单的文件实现:KEYRING_FILE。密钥保存在文件中,通常叫keyring_file。这种实现方式非常不安全。当加密的表空间文件和keyring_file一同被拷贝出去,那么加密的表空间文件是可以正常读取的。
MySQL商业版提供KEYRING插件的另外一种实现:KEYRING_OKV。密钥保存在ORACLE Key Vault中,确保密钥的安全性。
1.2 TXSQL数据加密
在TXSQL中,我们沿用MySQL的透明加密体系,提供 KEYRING插件的另外一种实现:KEYRING_KMS。将KEYRING与企业级的KMS(Key Management Service) 集成。
KMS是腾讯云一项保护数据及密钥安全的密钥服务。服务涉及的各个流程均采用高安全性协议通信,保证服务高安全;提供分布式集群管理和热备份,保证服务高可靠和高可用。KMS也采用的是两层密钥体系。KMS涉及两类密钥,即用户主密钥(CMK)与数据密钥(Datakey)。用户主密钥用于加密数据密钥或密码、证书、配置文件等小包数据(最多 4KB)。数据密钥用于加密业务数据。海量的业务数据在存储或通信过程中使用数据密钥以对称加密的方式加密,而数据密钥又通过用户主密钥采用非对称加密方式加密保护。
通过API调用KMS接口时,首先创建用户主密钥;然后创建数据密钥。CMK的个数限制为128,而数据密钥则无此限制。在KEYRING_KMS实现上,MySQL的主密钥和KMS的数据密钥对应。由于KMS接口的限制和实际需要,我们只实现了KEYRING的两个接口:my_key_generate和my_key_fetch。
我们依然保留MySQL两层密钥体系,我们只是用KMS来实现了主密钥的管理,但没有使用KMS来进行数据的加密。主要考虑有两点:一是系统可用性方面的考虑,比如万一KMS短时不可用,那么加密数据将无法访问;二是系统性能方面的考虑,所有数据的加解密都通过KMS,加解密效率和网络开销无疑对系统影响巨大
1.2.1 Key Generate
在KEYRING_KMS中,我们同样有一个本地文件,用来存储密钥ID和加密后的数据密钥。这个加密后的数据密钥是由KMS返回,所以解密这个数据密钥也需要通过KMS来做。在下图的流程中,我们通过固定的CMK别名(alias)来获取或创建CMK,然后产生数据密钥,将加密后的数据密钥保存在本地文件中。
1.2.2 Key Fetch
获取密钥首先根据密钥ID从文件中读取加密后的数据密钥,再通过KMS对数据密钥进行解密,获取密钥明文。KMS进行解密时,只需要提供密文,不要需要其他信息。获取密钥明文成功之后,我们对密钥明文进行了缓存,减少对KMS的访问。
1.2.3 基于角色的访问控制
在用户开启加密功能时,在CAM中,为用户创建了一个可以访问KMS的角色(role),并将此角色的权限授予指定的控制台用户。我们通过访问CAM获取临时证书(secret key, secret id,token),通过临时证书来访问KMS。其中CAM是腾讯云提供的访问控制服务。
如果不采用角色访问控制,在开启加密的时候,需要用户提供自己的证书。其一,用户体验差,其二,用户证书的安全性差。
还有一点值得注意:InnoDB中使用的主密钥是可以轮换的。通过如下语句进行轮换:
ALTER INSTANCE ROTATE INNODB MASTER KEY;
主密钥的轮换过程:
1. 产生新的主密钥ID;
2. 获取新的主密钥(key generate);
3. 对所有加密表空间,执行步骤4,5
4. 对加密的表空间,用旧的主密钥解密表空间密钥;
5. 用新的主密钥加密表空间密钥。
主密钥的轮换,进一步提高了系统的安全性。
通过以上介绍,我们可以看到,TXSQL透明数据加密,将KMS和CAM有机的结合在一起,对访问控制,密钥管理和数据加密等各个环节进行严格把控,为用户在腾讯云上提供了一个完整、安全、可靠的数据加密解决方案。
二、审计
数据库审计也是数据库安全的重要一环。所谓审计,就是对用户在数据库中的操作和行为进行记录,基于这些记录,可以进行审查分析。我们可以通过审计记录来对一个非法操作进行追查;对数据库性能和运行状态进行(也可以通过系统监控获得);可以对用户的访问模式进行跟踪建模等等。这些事后的分析可以帮助我们发现数据库运行过程中的风险,发出告警,以及采取必要的干预措施。
2.1 MySQL审计
MySQL同样提供了一个审计插件(Audit Plugin)框架。在框架内部主要处理函数为:
int (*event_notify)(MYSQL_THD, mysql_event_class_t, const void *);
在Server层面,从系统启动,用户登录,到SQL执行的各个节点,以事件的方式,通知审计插件进行记录。以下是事件类型的例子:
- MYSQL_AUDIT_CONNECTION_PRE_AUTHENTICATE
- MYSQL_AUDIT_CONNECTION_CONNECT
- MYSQL_AUDIT_CONNECTION_DISCONNECT
- MYSQL_AUDIT_CONNECTION_DISCONNECT
- MYSQL_AUDIT_COMMAND_START
- MYSQL_AUDIT_COMMAND_END
MySQL社区版只提供审计插件的范例,而在MySQL商业版中提供企业级审计功能。
2.2 TXSQL审计
TXSQL的重要用户有对审计功能的迫切需求:用户需要对数据库操作进行事后的跟踪和分析。我们利用审计插件框架,综合考虑功能和性能,提供了一套全新的审计解决方案。
2.2.1 审计架构
上图是我们整个审计框架的示意图。
用户连接(session)产生的审计记录被写入到一片固定的内存中;专门的写盘线程(Flush Thread)将内存中的审计记录写入到审计文件中(Audit File);审计代理(Audit Agent)则读取审计文件,将审计记录发送到审计日志中心:CTSDB集群进行集中存储。其中,一个TXSQL实例对应一个写盘线程,一个审计代理服务多个TXSQL实例,一台物理机上只有一个审计代理。
CTSDB是腾讯基础架构部数据库团队研发的时间序列数据库(目前可以在腾讯云上申请试用)。审计数据又恰好是时间序列数据。选择CTSDB来存储审计数据带来的好处有:其一数据压缩率高;其二数据吞吐量大;其三数据分析能力强。完全满足我们在高压力情况下,对审计数据的处理和分析能力。
2.2.2 审计日志格式
我们采用json格式对审计日志传输。记录的内容有时间戳,影响的行数,执行的时间,错误码,规则号,主机,实例名,用户名,数据库名,过滤策略名,SQL语句,以及SQL类型等。
2.2.3 审计过滤规则
考虑到审计日志量巨大,提供过滤规则就很必要。我们提供如下过滤规则
1. 主机IP,用户名,数据库名,表名可以使用“include, exclude, =, <>, regex”进行过滤;
2. SQL语句可以使用“include, exclude, regex”进行过滤;
3. SQL类型可以使用“=, <>”进行过滤;
4. 影响函数和之行时间可以使用“>, <, >=, <=, =”进行过滤。
2.2.4 审计性能
为了减少审计带来的性能损失,我们只对命令执行完之后的结果进行审计。这样就省去了很大一部分的审计日志。根据我们的测试,打开审计并进行全量审计(Audit all)时,系统性能损失9%;打开审计并且不进行审计(Audit null)时,性能损失约为3%。
三、小结
TXSQL在实现加密和审计这两个企业级特性,是对用户需求的积极响应。在实现上,也充分结合与腾讯云内其他平台进行结合,提供一站式的解决方案。为了给用户提供性能更好,功能更强,可用性更高的数据库服务,TXSQL一直在努力。另外,TXSQL 关于加密和审计的开源工作也在进行着中,已经初步和 MariaDB 达成了相关合作,在不久的将来里,这两个企业级的功能就能与大家在开源版本中见面。