为什么我不能在两个 Amazon S3 桶之间复制对象?

3 分钟阅读
0

我想将一个对象从一个 Amazon Simple Storage Service (Amazon S3)桶复制到另一个桶,但无法实现。

解决方法

桶策略和 IAM 策略

要在桶之间复制对象,请确保配置了正确的权限。要在同一 AWS 账户的桶之间复制对象,请使用 AWS 身份和访问管理(IAM)策略来设置权限。要在不同账户的桶之间复制对象,必须同时设置相关的 IAM 策略和桶策略的权限。

**注意:**有关如何修改桶策略的说明,请参阅使用 Amazon S3 控制台添加桶策略。有关如何修改 IAM 用户权限的说明,请参阅更改 IAM 用户的权限。有关如何修改 IAM 角色权限的说明,请参阅修改角色

确认以下所需权限:

  • 至少,您的 IAM 身份(用户或角色)必须拥有在源桶上执行 s3:listBuckets3:getObject 操作的权限。如果桶位于同一个账户中,则使用您的 IAM 身份策略或 S3 桶策略设置这些权限。如果桶位于不同的账户中,则使用桶策略和您的 IAM 身份的策略来设置这些权限。
  • 至少,您的 IAM 身份必须有权在目标桶上执行 s3:listBuckets3:PutObject 操作。如果桶位于同一个账户中,则使用您的 IAM 身份策略或 S3 桶策略设置这些权限。如果桶位于不同的账户中,则使用桶策略和您的 IAM 身份的策略来设置这些权限。
  • 查看相关的桶策略和 IAM 策略,确认不存在与所需权限冲突的明确拒绝声明。显式拒绝语句会覆盖允许语句
  • 对于特定操作,请确认您的 IAM 身份有权在操作中执行所有必要操作。例如,要运行 aws s3 cp 命令,你需要获得 s3:getObjects3:putObject 的权限。要运行带有 --recursive 选项的 aws s3 cp 命令,你需要获得 s3:getObjects3:put Objects3:listBucket 的权限。要运行 aws s3 sync 命令,你需要获得 s3:getObjects3:PutObjects3:listBucket 的权限。
    **注意:**如果您使用 AssumeRole API 操作访问 Amazon S3,请验证是否正确配置了信任关系
  • 对于特定版本的操作,请确认您的 IAM 身份有权执行特定于版本的操作。例如,要复制对象的特定版本,您需要拥有 s3:getObjectVersions3:getObjectVersion 的权限。
  • 要复制带有对象标签的对象,您的 IAM 身份必须具有 s3:get ObjectTaggings3:putObjectTagging 权限。你必须对源对象具有 s3:getObjectTagging 权限,对目标桶中的对象必须具有 s3:putObjectTagging 权限。
  • 查看相关的桶策略和 IAM 策略,以验证资源元素的路径是否正确。对于桶级权限,资源元素必须指向桶。要获得对象级权限,资源元素必须指向一个或多个对象。

例如,诸如 s3:ListBucket 之类的桶级操作的策略声明必须在资源元素中指定一个桶:

"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"

诸如 s3:getObjects3:PutObject 之类的对象级操作的策略声明必须在资源元素中指定一个或多个对象:

"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"

对象所有权

如果桶策略具有正确的权限,但您仍然无法在桶之间复制对象,请检查哪个账户拥有该对象。桶策略仅适用于属于桶所有者的对象。属于其他账户的对象可能在其访问控制列表(ACL)上存在权限冲突。

**注意:**当您跨账户复制 AWS 服务日志时,通常会出现对象所有权和 ACL 问题。服务日志的示例包括 AWS CloudTrail 日志和 Elastic Load Balancing 访问日志。

要查找拥有对象的账户,请按照以下步骤操作:

  1. 打开 Amazon S3 控制台
  2. 导航到您无法在桶之间复制的对象。
  3. 选择对象的权限选项卡。
  4. 查看对象所有者的访问权限其他 AWS 账户的访问权限下的值
  • 如果对象归您的账户所有,则对象所有者访问权限下的规范 ID 将包含**(您的 AWS 账户)**。
  • 如果该对象归其他账户所有,并且您可以访问该对象,则以下情况为真:
    对象所有者访问权限下的规范 ID 包含**(外部账户)
    其他 AWS 账户的访问权限下的
    规范 ID** 包含**(您的 AWS 账户)**。
  • 如果该对象归其他账户所有,而您无法访问该对象,则为真:
    对象所有者的访问权限其他 AWS 账户的访问权限规范 ID 字段均为空。

如果您无法在桶之间复制的对象归另一个账户所有,则对象所有者可以完成以下选项之一:

  • 对象拥有者可以授予桶拥有者对对象的完全控制权。桶拥有者拥有该对象后,桶策略将应用于该对象。
  • 对象所有者可以保留对象的所有权,但他们必须将 ACL 更改为您的用例所需的设置。

AWS KMS 加密

对象可能使用 AWS Key Management Service(AWS KMS)密钥进行加密。在这种情况下,请确认您的 IAM 身份拥有对密钥的正确权限。如果您的 IAM 身份和 AWS KMS 密钥属于同一个账户,请确认您的密钥政策授予了所需的 AWS KMS 权限

如果您的 IAM 身份和 AWS KMS 密钥属于不同的账户,请确认密钥和 IAM 策略都授予了所需的权限

例如,如果您在两个桶之间复制对象(并且每个桶都有自己的密钥),则 IAM 身份必须指定以下权限:

  • kms:Decrypt 权限,引用第一个 KMS 密钥
  • kms:generateDataKeykms:decrypt 权限,引用第二个 KMS 密钥

有关更多信息,请参阅在 AWS KMS 中使用密钥政策AWS 密钥管理服务的操作、资源和条件密钥

Amazon Archive 存储类或 Amazon Glacier 和 Intelligent Archive 存储类

您无法从 Amazon S3 Glacier 存储类中复制对象。您必须先从 Amazon S3 Glacier 恢复该对象,然后才能复制该对象。有关说明,请参阅恢复存档对象

已在桶上激活 Requester Pays

如果源桶或目标桶已激活 Requester Pays,而您想从其他账户访问该桶,请检查您的请求。请确保您的请求包含正确的 Requester Pays 参数

  • 对于 AWS 命令行界面(AWS CLI)命令,请包括 --request-payer 选项。
    **注意:**如果在运行 AWS CLI 命令时收到错误,请确保您使用的是最新的 AWS CLI 版本
  • 对于 GET、HEAD 和 POST 请求,请包括 x-amz-request-payer : requester
  • 对于签名 URL,请包括 x-amz-request-payer=requester

AWS Organizations 服务控制策略

如果您使用 AWS Organizations,请检查服务控制策略以验证它们是否允许访问 Amazon S3。

例如,当您尝试访问 Amazon S3 时,此策略会导致 403 Forbidden 错误。这是因为它明确拒绝访问:

{  
  "Version": "2012-10-17",  
  "Statement": [  
    {  
      "Effect": "Deny",  
      "Action": "S3:*",  
      "Resource": "*"  
    }  
  ]  
}

有关 AWS Organizations 功能的详细信息,请参阅启用组织中的所有功能

Amazon S3 的 VPC 端点的跨区域请求问题

适用于 Amazon S3 的 VPC 端点不支持跨不同 AWS 区域的请求。例如,假设您在区域 A 中有一个 Amazon Elastic Compute Cloud (Amazon EC2)实例。该实例的关联路由表中配置了一个虚拟私有云(VPC)端点。EC2 实例无法将对象从区域 B 复制到区域 A 中的桶。相反,您会收到一条与以下示例类似的错误消息:

"An error occurred (AccessDenied) when calling the CopyObject operation: VPC endpoints do not support cross-region requests"

要解决此跨区域请求问题,请尝试以下方法:

  • 从路由表中移除 VPC 端点。如果您移除 VPC 端点,则实例必须能够连接到互联网。
  • 从另一个不使用 VPC 端点的实例运行复制命令。或者,从既不在区域 A 也不在区域 B 中的实例上运行复制命令。
  • 如果您必须使用 VPC 端点,请先发送 GET 请求,将对象从源桶复制到 EC2 实例。然后,发送 PUT 请求,将对象从 EC2 实例复制到目标桶。

相关信息

复制对象

如何解决来自 Amazon S3 的 403 Access Denied 错误?

AWS 官方
AWS 官方已更新 8 个月前