对象加密

Swift 支持在存储节点的静态数据加密。对象数据的加密旨在降低未经授权方获得磁盘物理访问权限后读取用户数据的风险。

注意

Swift 的静态数据加密接受客户端的明文对象数据,在集群中对其进行加密,并存储加密后的数据。这可以防止对象数据在数据驱动器离开 Swift 集群时被意外暴露。如果用户希望确保明文数据在传输和存储过程中始终加密,强烈建议在将其发送到 Swift 集群之前对其进行加密。客户端加密是确保数据在其整个生命周期内完全加密的唯一方法。

静态数据加密由可能包含在代理服务器 WSGI 管道中的中间件实现。此功能是 Swift 集群内部的,未通过 API 暴露。客户端不知道此功能内部对数据进行了加密;内部加密的数据不应通过 Swift API 返回给客户端。

以下数据在 Swift 中静态加密

  • 对象内容,即对象 PUT 请求体的 content

  • 具有非零内容的对象的实体标签 (ETag)

  • 所有自定义用户对象元数据值,即使用 X-Object-Meta- 前缀的标头通过 PUT 或 POST 请求发送的元数据

上述列表中未包含的任何数据或元数据均未加密,包括

  • 帐户、容器和对象名称

  • 帐户和容器自定义用户元数据值

  • 所有自定义用户元数据名称

  • 对象 Content-Type 值

  • 对象大小

  • 系统元数据

注意

此功能旨在提供静态数据的机密性,即保护用户数据免受访问存储对象数据的磁盘的攻击者读取。

此功能不旨在防止对静态用户数据进行不可检测的修改

此功能不旨在保护免受访问 Swift 内部网络连接的攻击者,或访问密钥材料或能够修改 Swift 节点上运行的 Swift 代码的攻击者。

部署和操作

通过将两个中间件过滤器添加到代理服务器 WSGI 管道,并将各自的过滤器配置部分包含在 proxy-server.conf 文件中来部署加密。如果正在使用容器同步功能,则需要其他步骤

keymasterencryption 中间件过滤器必须位于管道中的所有其他中间件的右侧,除了最终的代理日志中间件,并且按照此示例中的顺序

<other middleware> keymaster encryption proxy-logging proxy-server

[filter:keymaster]
use = egg:swift#keymaster
encryption_root_secret = your_secret

[filter:encryption]
use = egg:swift#encryption
# disable_encryption = False

有关中间件配置选项的更多详细信息,请参阅 proxy-server.conf-sample 文件。

Keymaster 中间件

在使用之前,必须使用根密钥配置 keymaster 中间件。默认情况下,keymaster 中间件将使用在 proxy-server.conf 文件的中间件过滤器部分中配置的 encryption_root_secret 选项配置的根密钥,例如

[filter:keymaster]
use = egg:swift#keymaster
encryption_root_secret = your_secret

根密钥值必须至少包含 44 个有效的 base-64 字符,并且应在所有代理服务器上保持一致。选择最小长度 44 是因为它是 base-64 编码的 32 字节值的长度。

注意

encryption_root_secret 选项保存用于加密的主密钥。所有加密数据的安全性严重依赖于此密钥,因此应将其设置为高熵值。例如,可以通过 base-64 编码由加密安全的随机数生成器生成的 32 字节(或更长)值来获得合适的 encryption_root_secret

encryption_root_secret 值对于从存储系统中恢复任何加密数据是必需的,因此,必须防止意外丢失。它的值(以及因此,proxy-server.conf 文件)不应存储在任何帐户、容器或对象环中的任何磁盘上。

encryption_root_secret 值在部署后不应更改。这样做将阻止 Swift 正确解密使用前一个值加密的数据,并因此导致该数据丢失。

可以使用 openssl 命令行工具生成适合 encryption_root_secret 的值的一种方法

openssl rand -base64 32

单独的 keymaster 配置文件

encryption_root_secret 选项也可以指定在由 keymaster_config_path 选项指定的路径处的单独配置文件中,例如

[filter:keymaster]
use = egg:swift#keymaster
keymaster_config_path = /etc/swift/keymaster.conf

这样做的好处是允许需要加密感知(例如,proxy-server 和 container-sync)的多个进程共享相同的配置文件,从而确保这些进程使用一致的加密密钥。它还允许 keymaster 配置文件具有与 proxy-server.conf 文件不同的权限。

单独的 keymaster 配置文件应具有包含 encryption_root_secret 选项的 [keymaster] 部分

[keymaster]
encryption_root_secret = your_secret

注意

提供替代的 keymaster 中间件,可以从外部密钥管理系统(例如 Barbican)而不是将根密钥存储在配置文件中检索加密根密钥。

部署后,加密过滤器默认情况下将在处理 PUT 和 POST 请求时加密对象数据和元数据,并在处理 GET 和 HEAD 请求时解密对象数据和元数据。COPY 请求通过 服务器端复制 中间件转换为 GET 和 PUT 请求,然后再到达加密中间件,因此,复制对象数据和元数据时,数据将被解密并重新加密。

更改加密根密钥

有时,可能希望更改用于为写入集群的新数据派生加密密钥的根密钥。 keymaster 中间件允许使用以下形式的选项在配置中指定替代根密钥

encryption_root_secret_<secret_id> = <secret value>

其中 secret_id 是根密钥的唯一标识符,secret value 是满足上述根密钥要求的根密钥值。

在任何给定时间,仅使用一个根密钥来加密新数据。此根密钥使用 active_root_secret_id 选项指定。如果指定,此选项的值应是配置的根密钥 secret_id 值之一;否则,encryption_root_secret 的值将作为默认的活动根密钥。

注意

活动根密钥仅用于派生写入集群的新数据的密钥。更改活动根密钥不会导致任何现有数据被重新加密。

现有加密数据将使用在写入该数据时处于活动状态的根密钥进行解密。因此,必须将所有以前的活动根密钥保留在中间件配置中,才能成功解密现有数据。现有加密数据将通过 secret_id 引用以前的根密钥,因此必须在配置中保持一致。

注意

不要删除或更改任何以前活动的 <secret value><secret_id>

例如,以下 keymaster 配置文件指定了三个根密钥,encryption_root_secret_2 的值是当前的活动根密钥

[keymaster]
active_root_secret_id = 2
encryption_root_secret = your_secret
encryption_root_secret_1 = your_secret_1
encryption_root_secret_2 = your_secret_2

注意

为了确保没有数据可用性损失,将新密钥部署到您的集群需要两个阶段的配置更改。首先,将新密钥添加到 encryption_root_secret_<secret_id> 选项并重新启动代理服务器。对所有代理执行此操作。接下来,将 active_root_secret_id 选项设置为新的密钥 ID 并重新启动代理。再次对所有代理执行此操作。此过程可确保所有代理在任何代理将其用于加密之前,都将新密钥用于解密。

加密中间件

部署后,加密过滤器默认情况下将在处理 PUT 和 POST 请求时加密对象数据和元数据,并在处理 GET 和 HEAD 请求时解密对象数据和元数据。COPY 请求通过 服务器端复制 中间件转换为 GET 和 PUT 请求,然后再到达加密中间件,因此,复制对象数据和元数据时,数据将被解密并重新加密。

外部密钥管理系统中的加密根密钥

使用专用系统存储加密根密钥的好处包括此类系统中已有的审计和访问控制基础设施,以及存储在密钥管理系统 (KMS) 中的加密根密钥可能由硬件安全模块 (HSM) 提供支持,以获得额外的安全性。将根加密密钥存储在外部 KMS 的另一个重要好处是,它在这种情况下永远不会存储在 Swift 集群中的磁盘上。

Swift 支持使用 Barbican 服务或 KMIP 服务分别使用 kms_keymasterkmip_keymaster 中间件检索加密根密钥。

Barbican KMS 中的加密根密钥

确保已安装检索来自外部 KMS 的加密根密钥所需的依赖项。可以通过在 Swift 目录中更改为 Swift 目录并运行以下命令以将 Swift 与 kms_keymaster 额外依赖项一起安装为开发版本来完成

sudo pip install .[kms_keymaster]

另一种安装依赖项的方法是确保以下行存在于 requirements.txt 文件中,并使用 pip install -r requirements.txt 安装它们

cryptography>=1.6                       # BSD/Apache-2.0
castellan>=0.6.0

注意

如果已安装任何必需的软件包,则可能需要对 pip 命令使用 --upgrade 标志,以便安装所需的最低版本。

要使用存储在外部 KMS 中的加密根密钥,请在 proxy-server.conf 中的代理服务器 WSGI 管道中将 keymaster 中间件替换为 kms_keymaster 中间件,顺序如下所示

<other middleware> kms_keymaster encryption proxy-logging proxy-server

并在同一文件中添加一个部分

[filter:kms_keymaster]
use = egg:swift#kms_keymaster
keymaster_config_path = file_with_kms_keymaster_config

创建或编辑上述引用的 file_with_kms_keymaster_config 文件。有关中间件配置选项的更多详细信息,请参阅 keymaster.conf-sample 文件。以下是此文件的内容示例,省略了可选参数

[kms_keymaster]
key_id = changeme
username = swift
password = password
project_name = swift
auth_endpoint = http://keystonehost:5000/v3

加密根密钥应在外部密钥管理系统中创建并存储,然后才能由 keymaster 使用。它应作为对称密钥存储,内容类型为 application/octet-stream,内容编码为 base64,算法为 AES,位长为 256,密钥类型为 symmetric。模式 ctr 也可以存储用于参考目的 - keymaster 当前不会对其进行检查。

可以使用以下命令将当前配置的 encryption_root_secret 值从 proxy-server.conf 文件存储在 Barbican 中

openstack secret store --name swift_root_secret \
--payload-content-type="application/octet-stream" \
--payload-content-encoding="base64" --algorithm aes --bit-length 256 \
--mode ctr --secret-type symmetric --payload <base64_encoded_root_secret>

或者,也可以使用 curl 将现有的根密钥存储在 Barbican 中。

注意

用于将密钥存储在 Barbican 中的凭据应与代理服务器用于检索密钥的凭据相同,即在 keymaster.conf 文件中配置的凭据。出于清晰起见,此处显示的命令省略了凭据 - 可以显式指定它们,或在环境变量中指定。

与其使用现有的根密钥,Barbican 还可以被要求生成一个新的 256 位根密钥,内容类型为 application/octet-stream,算法为 AESmode 参数目前是可选的)

openstack secret order create --name swift_root_secret \
--payload-content-type="application/octet-stream" --algorithm aes \
--bit-length 256 --mode ctr key

命令 order create 创建一个异步请求来创建实际的密钥。可以使用 openstack secret order get 来检索该命令,并且一旦命令成功完成,输出将显示生成的根密钥的 key id。可以使用命令 openstack secret list 列出当前存储在 Barbican 中的密钥。

注意

命令(创建或存储密钥的异步请求)和实际密钥本身都具有相似的唯一标识符。一旦命令完成,key id 将显示在 order get 命令的输出中。

keymaster 使用在 keymaster.conf 文件中显式配置的用户名和密码(以及项目名称等)从外部密钥管理系统检索加密根密钥。使用 Castellan 库 与 Barbican 通信。

对于代理服务器,直接从 proxy-server.conf 文件、从 proxy-server.conf 文件指向的 keymaster.conf 文件,或从 Barbican 等外部密钥管理系统读取加密根密钥,在功能上是等效的。如果从外部密钥管理系统读取加密根密钥失败,代理服务器将无法启动。如果成功检索到加密根密钥,它将在代理服务器的内存中缓存。

有关配置选项的更多详细信息,请参阅 proxy-server.conf-sample 文件中的 [filter:kms_keymaster] 部分和 keymaster.conf-sample 文件。

KMIP 服务中的加密根密钥

此中间件使 Swift 能够从 KMIP 服务获取根密钥。预计根密钥之前已在 KMIP 服务中创建,并通过其唯一标识符进行引用。该密钥应为 AES-256 对称密钥。

要使用此中间件,Swift 必须安装额外的必需依赖项

sudo pip install .[kmip_keymaster]

添加 -e 标志以将其安装为开发版本。

编辑 swift proxy-server.conf 文件,将中间件插入到 wsgi 管道中,替换任何其他 keymaster 中间件

[pipeline:main]
pipeline = catch_errors gatekeeper healthcheck proxy-logging \
    <other middleware> kmip_keymaster encryption proxy-logging proxy-server

并添加一个新的过滤器部分

[filter:kmip_keymaster]
use = egg:swift#kmip_keymaster
key_id = <unique id of secret to be fetched from the KMIP service>
host = <KMIP server host>
port = <KMIP server port>
certfile = /path/to/client/cert.pem
keyfile = /path/to/client/key.pem
ca_certs = /path/to/server/cert.pem
username = <KMIP username>
password = <KMIP password>

除了 usekey_id 之外,选项与 PyKMIP 客户端的定义相同。这些选项的权威定义可以在 https://pykmip.readthedocs.io/en/2025.2/client.html 找到。

选项 key_id 的值应为从 KMIP 服务检索的密钥的唯一标识符。

keymaster 配置也可以通过使用 keymaster_config_path 选项在单独的配置文件中定义

[filter:kmip_keymaster]
use = egg:swift#kmip_keymaster
keymaster_config_path = /etc/swift/kmip_keymaster.conf

在这种情况下,filter:kmip_keymaster 部分不应包含除 usekeymaster_config_path 之外的任何其他选项。所有其他选项应在名为 kmip_keymaster 的单独配置文件中的一个部分中定义。例如

[kmip_keymaster]
key_id = 1234567890
host = 127.0.0.1
port = 5696
certfile = /etc/swift/kmip_client.crt
keyfile = /etc/swift/kmip_client.key
ca_certs = /etc/swift/kmip_server.crt
username = swift
password = swift_password

更改外部 KMS 的加密根密钥

由于 KMS 和 KMIP keymaster 源自默认 KeyMaster,因此它们也有能力定义多个密钥。唯一的区别是密钥选项名称。与其使用 encryption_root_secret_<secret_id> 形式,这两个外部 KMS 都使用 key_id_<secret_id>,因为它是其现有配置的扩展。例如

...
key_id = 1234567890
key_id_foo = 0987654321
key_id_bar = 5432106789
active_root_secret_id = foo
...

除此之外,该过程与 Changing the encryption root secret 相同。

升级注意事项

升级现有集群以部署加密时,建议执行以下步骤

  1. 升级所有对象服务器

  2. 升级所有代理服务器

  3. 将 keymaster 和加密中间件添加到每个代理服务器的中间件管道中,并将加密 disable_encryption 选项设置为 True,并将 keymaster encryption_root_secret 值设置为如上所述。

  4. 如果需要,请遵循 Container sync configuration 中的步骤。

  5. 最后,将加密 disable_encryption 选项更改为 False

在部署 keymaster 和加密中间件之前存在于集群中的对象仍然可以使用 GET 和 HEAD 请求读取。除非通过 PUT 或 COPY 请求再次写入,否则这些对象的内容将不会被加密。除非通过 PUT、POST 或 COPY 请求再次写入,否则这些对象的任何用户元数据将不会被加密。

禁用加密

部署后,不应从管道中删除 keymaster 和加密中间件。这样做会导致加密的对象数据和/或元数据在对先前加密的对象发出 GET 或 HEAD 请求时返回。

可以通过将加密 disable_encryption 选项设置为 True 来禁用入站对象数据的加密,在这种情况下,现有的加密对象将保持加密,但使用 PUT、POST 或 COPY 请求写入的新数据将不会被加密。即使在不需要对新对象进行加密时,keymaster 和加密中间件也应保留在管道中。加密中间件需要处理可能先前加密的对象的 GET 请求。keymaster 需要为这些请求提供密钥。

容器同步配置

如果正在使用容器同步,则必须将 keymaster 和加密中间件添加到容器同步内部客户端管道中。需要执行以下配置步骤

  1. 如果尚未存在,则基于示例文件 internal-client.conf-sample 创建一个自定义的内部客户端配置文件,用于容器同步。例如,将 internal-client.conf-sample 复制到 /etc/swift/container-sync-client.conf

  2. 修改此文件,以与上述代理服务器的描述方式相同,在管道中包含中间件。

  3. 修改所有容器服务器配置文件的容器同步部分,使用 internal_client_conf_path 选项指向此内部客户端配置文件。例如

    internal_client_conf_path = /etc/swift/container-sync-client.conf
    

注意

由于 encryption_root_secret 值对于恢复存储系统中的任何加密数据是必要的,因此必须防止意外丢失。其值(以及随之而来的自定义内部客户端配置文件)不应存储在任何帐户、容器或对象环中的任何磁盘上。

注意

如果测试集群的代理管道中包含加密中间件,则这些容器同步配置步骤对于容器同步探测测试通过是必要的。

实现

加密方案

纯文本数据使用由 python cryptography 包 实现的 AES 密码和 256 位密钥加密。该密码以计数器 (CTR) 模式使用,以便密文中的任何字节或字节范围都可以独立于密文中的任何其他字节进行解密。这使得处理范围 GET 变得非常简单。

通常,未加密的数据项 plaintext 被转换为加密的数据项 ciphertext

ciphertext = E(plaintext, k, iv)

其中 E 是加密函数,k 是加密密钥,iv 是为每个加密上下文选择的唯一初始化向量 (IV)。例如,对象体是一个随机选择的 IV 的加密上下文。

plaintext = D(ciphertext, k, iv)

其中 D 是解密函数。

CTR 模式的实现遵循 NIST SP800-38A,并且传递给加密或解密函数的完整 IV 作为初始计数器块。

通常,任何加密项都伴随着描述 IV 和用于加密的密码算法的 crypto-metadata

crypto_metadata = {"iv": <16 byte value>,
                   "cipher": "AES_CTR_256"}

此 crypto-metadata 与密文一起存储(对于用户元数据和 etag)或作为单独的标头(对于对象体)。

密钥管理

keymaster 中间件负责提供每个加密和解密操作所需的密钥。处理对象请求时需要两个密钥:与容器路径唯一关联的 容器密钥 和与对象路径唯一关联的 对象密钥。这些密钥通过 keymaster 在 WSGI 请求环境中安装的回调函数提供给加密中间件。

当前的 keymaster 实现通过使用 encryption_root_secret 作为密钥并使用容器或对象路径作为消息以确定论方式从 encryption_root_secret 派生容器和对象密钥,例如

object_key = HMAC(encryption_root_secret, "/a/c/o")

未来替代 keymaster 中间件的实现可以使用其他提供对象和容器密钥的策略。

在每个对象 PUT 期间,会生成一个随机密钥来加密对象体。然后,该随机密钥使用 keymaster 提供的对象密钥加密。这样可以安全地将加密的随机密钥与加密的对象数据和元数据一起存储。

这种 密钥包装 过程能够更有效地进行重新密钥化事件,当可能需要替换对象密钥,并且因此使用该密钥加密的任何数据必须重新加密时。密钥包装将使用这些密钥加密的数据量最小化为其他随机选择的密钥,这些密钥可以有效地重新包装,而无需重新加密使用随机密钥加密的更大数量的数据。

注意

目前未实现重新密钥化。密钥包装的实现是为了预见未来的重新密钥化操作。

加密中间件

加密中间件由一个 encrypter 组件和一个 decrypter 组件组成。

Encrypter 操作

自定义用户元数据

encrypter 使用 keymaster 提供的对象密钥和为该元数据项随机选择的 IV 加密每个自定义用户元数据项。加密的值存储为 Object Transient-Sysmeta,并将关联的 crypto-metadata 附加到加密的值。例如

X-Object-Meta-Private1: value1
X-Object-Meta-Private2: value2

转换为

X-Object-Transient-Sysmeta-Crypto-Meta-Private1:
  E(value1, object_key, header_iv_1); swift_meta={"iv": header_iv_1,
                                                  "cipher": "AES_CTR_256"}
X-Object-Transient-Sysmeta-Crypto-Meta-Private2:
  E(value2, object_key, header_iv_2); swift_meta={"iv": header_iv_2,
                                                  "cipher": "AES_CTR_256"}

删除了未加密的自定义用户元数据标头。

对象体

使用随机选择的体密钥和随机选择的 IV 对对象体进行加密

body_ciphertext = E(body_plaintext, body_key, body_iv)

体密钥使用 keymaster 提供的对象密钥和随机选择的 IV 进行包装

wrapped_body_key = E(body_key, object_key, body_key_iv)

encrypter 将关联的 crypto-metadata 存储在系统元数据标头中

X-Object-Sysmeta-Crypto-Body-Meta:
    {"iv": body_iv,
     "cipher": "AES_CTR_256",
     "body_key": {"key": wrapped_body_key,
                  "iv": body_key_iv}}

请注意,在这种情况下,还有一个额外的 crypto-metadata 项,它存储包装的体密钥及其 IV。

实体标签

在加密对象体时,encrypter 还计算纯文本体的 ETag (md5 摘要)。此值使用 keymaster 提供的对象密钥和随机选择的 IV 进行加密,并保存为系统元数据项,并将关联的 crypto-metadata 附加到加密的值

X-Object-Sysmeta-Crypto-Etag:
  E(md5(plaintext), object_key, etag_iv); swift_meta={"iv": etag_iv,
                                                      "cipher": "AES_CTR_256"}

encrypter 还通过将更新覆盖标头添加到 PUT 请求来强制发送加密的纯文本 ETag 版本。关联的 crypto-metadata 附加到此更新覆盖标头的加密 ETag 值

X-Object-Sysmeta-Container-Update-Override-Etag:
    E(md5(plaintext), container_key, override_etag_iv);
    meta={"iv": override_etag_iv, "cipher": "AES_CTR_256"}

容器密钥用于此加密,以便 decrypter 能够在处理容器请求时解密容器列表中的 ETag,因为对象密钥可能在该上下文中不可用。

由于只有在 encrypter 完成处理整个对象体后才知道纯文本 ETag 值,因此 X-Object-Sysmeta-Crypto-EtagX-Object-Sysmeta-Container-Update-Override-Etag 标头使用代理服务器对请求页脚的支持发送在加密对象体之后。

条件请求

通常,对象服务器通过将 If[-None]-Match 标头中列出的值与存储在对象元数据中的 ETag 进行比较来评估带有 If[-None]-Match 标头的条件请求。当存储在对象元数据中的 ETag 已加密时,这是不可能的。因此,encrypter 在处理对象 PUT 请求时,使用对象密钥和 ETag 计算一个 HMAC,并将其存储在元数据键 X-Object-Sysmeta-Crypto-Etag-Mac

X-Object-Sysmeta-Crypto-Etag-Mac: HMAC(object_key, md5(plaintext))

与 ETag 相关的其他元数据一样,这使用代理服务器对请求页脚的支持在加密对象体之后发送。

encrypter 还会计算包含在 If[-None]-Match 标头中的每个 ETag 值的 HMAC,并将这些附加到 If[-None]-Match 标头。encrypter 还会将 X-Backend-Etag-Is-At 标头设置为指向先前存储的 X-Object-Sysmeta-Crypto-Etag-Mac 元数据,以便对象服务器通过比较 If[-None]-Match 中包含的 HMAC 值与存储在 X-Object-Sysmeta-Crypto-Etag-Mac 下的值来评估条件请求。例如,给定带有标头的条件请求

If-Match: match_etag

encrypter 会将请求标头转换为包含

If-Match: match_etag,HMAC(object_key, match_etag)
X-Backend-Etag-Is-At: X-Object-Sysmeta-Crypto-Etag-Mac

这使得对象服务器能够在不泄露 ETag 本身或泄露有关对象体的信息的情况下执行加密比较以检查 ETag 是否匹配。

Decrypter 操作

对于每个对对象的 GET 或 HEAD 请求,解密器会检查响应中是否存在加密项(通过加密元数据头暴露),如果发现任何加密项,它将

  1. 通过其回调从密钥管理服务器获取对象和容器密钥

  2. 解密 X-Object-Sysmeta-Crypto-Etag

  3. 解密 X-Object-Sysmeta-Container-Update-Override-Etag

  4. 使用对象密钥解密元数据头值

  5. 解密在 X-Object-Sysmeta-Crypto-Body-Meta 中找到的封装体密钥

  6. 使用体密钥解密主体

对于每个对容器的 GET 请求,如果该请求将在其响应主体中包含 ETags,则解密器将

  1. 获取包含容器列表的响应主体

  2. 通过其回调从密钥管理服务器获取容器密钥

  3. 使用容器密钥解密容器列表中任何加密的 ETag 条目

对其他 Swift 服务和功能的影响

加密对 版本化写入 没有影响,除非任何先前未加密的对象在复制到或从版本容器时将被加密。密钥管理服务器和加密中间件应放置在代理服务器管道中的 versioned_writes 之后,如 部署和操作 中所述。

容器同步 使用内部客户端来 GET 要同步的对象。此内部客户端必须配置为使用密钥管理服务器和加密中间件,如 上方 所述。

加密对 object-auditor 服务没有影响。由于与对象一起存储的 ETag 头是加密对象体的 md5 和,因此审计器将验证加密数据是否有效。

加密对 object-expirer 服务没有影响。 X-Delete-AtX-Delete-After 头不会被加密。

加密对 object-replicatorobject-reconstructor 服务没有影响。这些服务不知道对象或 EC 片段数据是否被加密。

加密对 container-reconciler 服务没有影响。 container-reconciler 使用内部客户端在不同的策略环之间移动对象。协调器的管道一定不能启用加密。目标对象与源对象具有相同的 URL,并且对象在不重新加密的情况下移动。

开发者注意事项

开发者应注意,密钥管理服务器和加密中间件依赖于对象路径保持不变。包含的密钥管理服务器基于其路径和 encryption_root_secret 为容器和对象派生密钥。密钥管理服务器不依赖于对象元数据来告知其为 GET 和 HEAD 请求生成密钥,因为在处理 条件请求 时,需要在读取对象中的任何元数据之前提供对象密钥。

因此,开发者应仔细考虑任何新的功能,这些功能会通过不经过代理管道中的加密中间件并重新加密的方式在 Swift 集群内重新定位对象数据和元数据。

与每个加密项目关联的加密元数据包含一些由密钥管理服务器提供的 key_id 元数据,其中包含用于派生密钥的路径。此 key_id 元数据会持久保存,以预期未来可能需要解密已重新定位而无需重新加密的对象的情况,在这种情况下,可以使用该元数据来派生用于加密的密钥。但是,这本身不足以处理条件请求和解密已重新定位的容器列表,并且需要进一步的工作来解决这些问题。