跳转到主要内容

联邦 CopyObject:保持目标对象契约

Server 20260916 通过 PR #157、PR #159、PR #163、PR #177 与 PR #179 修复了旧版 etcd 存储桶联邦(bucket federation)的 CopyObject 转发路径。当代理节点将跨集群复制作为远端 PutObject 转发到目标集群时,代理节点流式读取并发送源对象的逻辑字节,由目标端执行加密与 Object Lock 规则,校验完整对象校验和,并原样返回目标端实际提交的写入元数据。

转发一次逻辑字节,由目标端执行加密

代理节点在本地按需解密并解压源对象,读取其逻辑字节流,并在向目标集群发起的 PutObject 请求中声明逻辑字节长度:

  • 禁止双重转换: 代理节点绝不在本地预先加密或压缩后再转发给远端重复处理。
  • SSE-C 与 SSE-KMS 边界: 读取 SSE-C 源对象仍要求提供源客户密钥并使用安全传输。新对象的加密方式完全由客户端显式携带的目标 SSE 请求头或目标桶自身的默认加密配置决定;当客户端未指定加密头时,代理节点不会注入本地默认加密配置。SSE-KMS 上下文按标准 JSON 对象格式转发。
  • 拒绝原始 SSE-C 副本复制: 联邦路径在创建目标对象前以 501 NotImplemented 显式拒绝可信原始 SSE-C 副本的 CopyObject 请求。

校验和与元数据过滤规则

普通转发写入按大小写不敏感规则剥离所有保留的内部元数据前缀,仅通过标准 S3 字段转发公开的用户元数据与对象标签。转发写入的校验和必须描述实际写入目标端的完整逻辑对象:

  • 整对象校验和转换: 当请求显式指定校验和算法,或源对象携带分段复合校验和(COMPOSITE)时,目标端必须生成并保存整对象校验和(FULL_OBJECT)。
  • 流式 trailer 与请求头传递: 非空对象流通过 x-amz-trailer 传递尾部校验和并由目标端验证;零字节对象无流式尾部,改用普通 x-amz-checksum-* 请求头;源对象已有的 FULL_OBJECT 校验和可直接作为普通校验和请求头转发给目标端验证。
  • 远端响应校验: 若远端 PutObject 响应缺失必需的校验和、格式非法或仍带有分段 -N 后缀,代理节点直接报错,不会将其包装成合法的整对象结果。由于报错时远端写入可能已经落盘,针对版本化桶重试前应先检查目标端实际生成的版本。

Object Lock 头部类型与时间精度

代理节点通过类型化的 LegalHold 客户端选项转发法律保留状态,确保请求发送标准的 x-amz-object-lock-legal-hold 请求头,而非误转为 x-amz-meta-* 用户元数据。对象保留期(Retention)时间戳完整保留亚秒级精度,不再截断为整秒。目标端继续独立执行权限认证与桶级 Object Lock 校验。

返回实际提交的目标写入身份

CopyObjectResult XML 响应与 ObjectCreated:Copy 事件均直接采用目标端本次写入返回的键名、逻辑大小、ETag、精确 VersionID 与修改时间。代理节点既不在本地伪造修改时间,也不通过后续不带版本号的 HEAD 请求二次读取(避免并发写入下读到其他版本的元数据)。当请求指定了源 versionId 时,源版本响应头继续标识所选中的源版本。

源码与测试索引