目前,可以在Percona Server中为MySQL / MySQL 启用透明数据加密(TDE),但是您是否想知道它在幕后如何工作以及TDE对您的服务器实例有什么样的影响?本文将了解TDE在内部如何工作。首先,我们讨论密钥环,因为任何加密都需要它们。然后,我们详细探讨Percona Server for MySQL / MySQL中的加密如何工作以及Percona Server for MySQL提供的额外加密功能。
MySQL钥匙圈
密钥环是允许服务器获取/创建/删除本地文件(keyring_file)或远程服务器(例如HashiCorp Vault)中的密钥的插件。所有密钥都本地缓存在密钥环的缓存中,以加快获取密钥的速度。它们可以分为使用以下内容的两类插件:
- 本地资源作为用于存储密钥(例如本地文件)的后端(我们称为基于资源文件的密钥环)
- 远程资源作为存储密钥的后端,例如Vault服务器(我们称为基于资源服务器的密钥环)
分离非常重要,因为取决于后端,密钥环的行为会有所不同,不仅在存储/获取密钥时,而且在启动时。
对于基于文件的密钥环,启动时的密钥环会将密钥环的整个内容(即密钥ID,密钥用户,密钥类型以及密钥本身)加载到缓存中。
对于基于服务器的密钥环(例如Vault服务器),服务器仅在启动时加载密钥ID和密钥用户的列表,因此不会通过从服务器检索所有密钥来减慢启动速度。值得一提的是,密钥环后端存储了哪些信息。密钥是延迟加载的,这意味着当服务器第一次请求密钥时,keyring_vault会要求Vault服务器发送密钥。密钥环将密钥缓存在内存中,以确保将来服务器是否可以使用内存访问来代替与Vault服务器的TLS连接来检索密钥。
密钥环中的记录包括以下内容:
- 密钥ID – 密钥的ID,例如:INNODBKey-764d382a-7324-11e9-ad8f-9cb6d0d5dc99-1
- 密钥类型 – 密钥的类型,基于使用的加密算法,可能的值为:“ AES”,“ RSA”或“ DSA”
- 密钥长度 –长度以字节为单位,AES:16、24或32,RSA 128、256、512和DSA 128、256或384。
- 用户 –密钥的所有者。如果此密钥是系统密钥(例如主密钥),则此字段为空。使用keyring_udf创建密钥时,此字段是密钥的所有者。
- 密钥本身
每个密钥由一对唯一标识:key_id,用户。
在存储和删除密钥方面也存在差异。
基于文件的密钥环操作应该更快,并且该操作是。您可能会认为密钥存储只是文件密钥的一次写入,但是涉及更多的任务。在进行任何基于文件的密钥环修改之前,密钥环会创建一个包含密钥环全部内容的备份文件,并将此备份文件放在密钥环文件旁边。假设您的密钥环文件称为my_biggest_secrets;备份名为my_biggest_secrets.backup。接下来,密钥环修改高速缓存以添加或删除密钥,如果此任务成功完成,它将从高速缓存中转储(即重写密钥环文件的全部内容)到您的密钥环文件中。在极少数情况下,例如服务器崩溃,您可以观察到此备份文件。下次加载密钥环时(通常在服务器重新启动之后),通过密钥环删除备份文件。
在存储或删除密钥时,基于服务器的密钥环必须连接到服务器,并从服务器传达“发送密钥” /“请求密钥删除”。
让我们回到服务器启动的速度。除了密钥环本身会影响启动时间外,启动时还必须从后端服务器检索多少个密钥。当然,这对于基于服务器的密钥环尤为重要。在服务器启动时,服务器检查解密每个加密表/表空间所需的密钥,并从密钥环中获取此密钥。在使用主密钥加密的“干净”服务器上,应该从密钥环中获取一个主密钥。但是,可能需要更多的密钥,例如,从主备份中重新创建从属时等。在这些情况下,最好考虑主密钥的轮换。我将在以后的博客文章中进一步讨论这一点,但我只是想在此概述使用多个主密钥的服务器的启动时间可能会更长一些,
现在让我们谈谈keyring_file的更多内容。当我开发keyring_file时,还要关注的是如何确保在运行中的服务器下不会更改keyring_file。在5.7中,检查是基于文件统计信息完成的,这不是一个完美的解决方案,该解决方案在8.0中被SHA256校验和取代。
首次启动keyring_file时,服务器会计算并记住文件统计信息和校验和,并且仅在匹配时才应用更改。当然,校验和会随着文件的更新而更新。
到目前为止,我们已经在钥匙圈方面做了很多介绍。但是,还有一个更重要的主题,它经常被忘记或被误解-每个服务器的密钥环分离,以及为什么这很重要。那是什么意思 我的意思是,群集中的每个服务器(假设为Percona服务器)应在Vault服务器上有一个单独的位置,Percona服务器应在其中存储其密钥。存储在密钥环中的主密钥将每个Percona服务器的GUID嵌入其ID中。为什么这很重要?假设您有一台带密钥的Vault服务器,并且群集中的所有Percona服务器都在使用这一台Vault服务器。问题似乎很明显–如果所有Percona服务器都使用没有唯一ID的主密钥(例如,id = 1,id = 2等)–群集中的所有Percona服务器都将使用相同的主密钥。GUID提供的是这种按服务器的分隔。由于每个Percona服务器的唯一GUID已经存在分隔,为什么还要谈论每个服务器的密钥环分隔?好了,还有另一个插件keyring_udf。使用此插件,您服务器的用户可以在Vault服务器中存储自己的密钥。当您的用户在例如server1上创建密钥,然后尝试在server2上创建具有相同标识符(key_id)的密钥时,就会出现问题,如下所示:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
--1 means success
--server2:
select keyring_key_store('ROB_1','AES',"543210987654321");
1
由于两个服务器使用同一台Vault服务器,因此keyring_key_store是否应在服务器上失败?有趣的是,如果您尝试在一台服务器上执行相同的操作,则会失败:
--server1:
select keyring_key_store('ROB_1','AES',"123456789012345");
1
select keyring_key_store('ROB_1','AES',"543210987654321");
0
是的,ROB_1已经存在。
让我们首先讨论第二个例子。正如我们之前讨论的那样,keyring_vault或任何其他keyring插件正在将所有密钥id缓存在内存中。因此,在新密钥之后,将ROB_1添加到服务器1上,并且除了将该密钥发送到Vault之外,还将该密钥添加到了密钥环的缓存中。现在,当我们尝试第二次添加相同的密钥时,keyring_vault会检查此密钥是否已存在于缓存中并且会出错。
在第一个示例中,情况有所不同。server1上的密钥环拥有自己的存储在Vault服务器上的密钥的缓存,而server2拥有其自身的缓存。将ROB_1添加到server1和Vault服务器上的密钥环的缓存后,server2上的密钥环的缓存不同步。server2上的高速缓存没有ROB_1密钥;因此,写入keyring_key_store并将ROB_1写入实际上覆盖(!)先前值的Vault服务器。现在,保管库服务器上的密钥ROB_1为543210987654321。有趣的是,保管库服务器不会阻止此类操作,并且会愉快地覆盖旧值。
现在,我们了解了为什么在Vault服务器上这种按服务器分隔很重要-如果您允许使用keyring_udf,并且还想按顺序将密钥存储在Vault中。我们如何确保Vault服务器上的这种分离?
Vault服务器上有两种分离方式。您可以在Vault服务器中创建装载点-每个服务器一个装载点,也可以在同一装载点内使用不同的路径,每个服务器一个路径。最好通过示例解释这两种方法。因此,让我们看一下配置文件。首先进行挂载点分离:
--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = server1_mount
token = (...)
vault_ca = (...)
--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = sever2_mount
token = (...)
vault_ca = (...)
我们可以看到我们有一个server1正在使用与server2不同的挂载点。在路径分离中,配置文件如下所示:
--server1:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/server1
token = (...)
vault_ca = (...)
--server2:
vault_url = http://127.0.0.1:8200
secret_mount_point = mount_point/sever2
token = (...)
vault_ca = (...)
在这种情况下,两个服务器都使用相同的秘密安装点–“ mount_point”,但路径不同。当您在该路径上的server1上创建第一个机密时,Vault服务器将自动创建一个“ server1”目录。服务器2的操作相同。当您删除mount_point / server1或mount_point / server2中的最后一个机密时,保管库服务器也会删除这些目录。如我们所见,如果使用路径分隔,则必须仅创建一个安装点并修改配置文件以使服务器使用单独的路径。可以使用HTTP请求创建安装点。使用CURL时:
curl -L -H "X-Vault-Token: TOKEN" –cacert VAULT_CA
--data '{"type":"generic"}' --request POST VAULT_URL/v1/sys/mounts/SECRET_MOUNT_POINT
所有字段(TOKEN,VAULT_CA,VAULT_URL,SECRET_MOUNT_POINT)都对应于密钥环配置文件中的选项。当然,您也可以使用Vault二进制文件执行相同的操作。关键是挂载点创建可以自动化。




