我的存储桶策略向另一个 AWS 账户授予了完整访问权限。为什么该账户中的 IAM 用户仍会收到“拒绝访问”错误?

上次更新时间:2020 年 3 月 27 日

我的 Amazon Simple Storage Service (Amazon S3) 存储桶策略向另一个 AWS 账户授予了完整访问权限。但是,当该账户中的 AWS Identity and Access Management (IAM) 用户尝试访问我的存储桶时,他们收到了“拒绝访问”错误。如何解决此问题? 

简短描述

如果您的存储桶策略已为其他账户授予访问权限,以下原因可能会导致跨账户用户收到“拒绝访问”错误:

  • 用户的 IAM 策略未授予存储桶访问权限。
  • 对象通过 AWS Key Management Service (AWS KMS) 加密,而用户无权访问 KMS 密钥。
  • 存储桶策略或 IAM 策略中的拒绝语句阻止了用户访问。
  • Amazon Virtual Private Cloud (Amazon VPC) 终端节点策略阻止了对存储桶的访问。
  • AWS Organizations 服务控制策略阻止了对存储桶的访问。
  • 对象不属于拥有该存储桶的 AWS 账户。
  • 存储桶上启用了申请方付款。

解决方法

用户的 IAM 策略未授予存储桶访问权限

对于跨账户访问,必须在账户 A 中的 IAM 策略和账户 B 中的存储桶策略中向用户授予存储桶访问权限。

按照以下步骤检查账户 A 中的用户 IAM 策略:

1.    打开 IAM 控制台

2.    在控制台中,打开应具有存储桶访问权限的 IAM 用户或角色。

3.    在 IAM 用户或角色的权限选项卡中,展开每个策略以查看其 JSON 策略文档。

4.    在 JSON 策略文档中,搜索包含存储桶名称的策略。然后,确认这些策略是否允许在存储桶上执行正确的 S3 操作。

5.    如果 IAM 用户或角色未授予存储桶访问权限,请添加授予相应权限的策略。例如,以下 IAM 策略会授予用户访问 awsexamplebucket 上的所有 S3 操作的权限:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ExampleStmt",
      "Action": "s3:*",
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::awsexamplebucket/",
        "arn:aws:s3:::awsexamplebucket/*"
      ]
    }
  ]
}

对象通过 AWS KMS 加密,而用户无权访问 KMS 密钥

如果账户 A 中的 IAM 策略和账户 B 中的存储桶策略都授予跨账户访问权限,则检查对象的加密属性。如果对象通过 AWS KMS 密钥加密,则用户还需要使用该密钥的权限。

按照以下步骤向 IAM 用户授予 KMS 密钥权限:

1.    编辑 KMS 密钥策略以添加与以下内容类似的语句:

注意:输入 IAM 用户的 Amazon 资源名称 (ARN) 作为委托人

{
   "Sid": "Allow use of the key",
   "Effect": "Allow",
   "Principal": {
     "AWS": [
       "arn:aws:iam::111122223333:user/Jane",
     ]
   },
   "Action": [
     "kms:Encrypt",
     "kms:Decrypt",
     "kms:ReEncrypt*",
     "kms:GenerateDataKey*",
     "kms:DescribeKey"
   ],
   "Resource": "*"
 }

2.    如果 KMS 密钥与 IAM 用户位于同一账户中,则密钥策略中的语句足以向用户授予密钥访问权限。如果 KMS 密钥与 IAM 用户不在同一账户中,则您还须更新 IAM 用户的权限。添加与以下内容类似的 IAM 策略:

注意:输入 KMS 密钥的 ARN 作为资源

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ExampleStmt3",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt",
                "kms:DescribeKey",
                "kms:Encrypt",
                "kms:GenerateDataKey",
                "kms:ReEncrypt*"
            ],
            "Resource": "arn:aws:kms:example-region-1:123456789098:key/a1b2c3d4-e5f6-7890-g1h2-123456789abc"
        }
    ]
}

存储桶策略或 IAM 策略中的拒绝语句阻止了用户访问

检查存储桶策略和用户的 IAM 策略,找出明确拒绝用户访问存储桶的所有语句。

按照以下步骤检查存储桶策略:

1.    打开 Amazon S3 控制台

2.    从存储桶列表中打开您要检查其存储桶策略的存储桶。

3.    选择权限选项卡。

4.    选择存储桶策略

5.    搜索包含 “Effect”: “Deny”的语句。

6.    修改存储桶策略以编辑或删除所有拒绝用户访问该存储桶的 "Effect": "Deny" 语句。

按照以下步骤检查用户的 IAM 策略:

1.    打开 IAM 控制台

2.    在控制台中,打开无法访问存储桶的 IAM 用户或角色。

3.    在 IAM 用户或角色的权限选项卡中,展开每项策略以查看 JSON 策略文档。

4.    在 JSON 策略文档中,使用包含“Effect”: “Deny”的语句查找与 S3 存储桶相关的策略。

5.    修改用户的 IAM 权限策略以编辑或删除所有 "Effect": "Deny" 语句,这些语句错误地拒绝了用户访问存储桶的权限。

VPC 终端节点策略阻止了对存储桶的访问

如果用户使用路由到 VPC 终端节点的 Amazon Elastic Compute Cloud (Amazon EC2) 实例访问存储桶,请检查 VPC 终端节点策略。确认 VPC 终端节点策略是否包含访问 S3 存储桶的相应权限。

例如,以下 VPC 终端节点策略允许访问 awsexamplebucket

{
  "Id": "Policy1234567890123",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1234567890123",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::awsexamplebucket",
        "arn:aws:s3:::awsexamplebucket/*"
      ],
      "Principal": "*"
    }
  ]
}

AWS Organizations 服务控制策略阻止了对存储桶的访问

如果用户账户启用了 AWS Organizations,请检查服务控制策略,以确保允许访问 Amazon S3。例如,以下策略明确拒绝访问 Amazon S3 并导致“拒绝访问”错误。

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

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

对象不属于拥有该存储桶的 AWS 账户

默认情况下,S3 对象归上传它的 AWS 账户所有。即使存储桶归另一个账户所有,也是如此。当对象归其他账户所有时,存储桶的权限不会自动应用于该对象。发送到另一账户中的存储桶的服务日志可能会发生这种情况。服务日志示例包括 AWS CloudTrail 日志Amazon Virtual Private Cloud (Amazon VPC) 流日志

要解决对象所有权访问遭拒错误:

1.    对象拥有者必须显式授予存储桶拥有者完全控制对象的权限

2.    然后,要应用所有权更改,存储桶拥有者必须将对象复制在同一位置上。为此,存储桶拥有者可以运行 cp 命令,类似于以下内容:

aws s3 cp s3://awsexamplebucket/awsexampleobject  s3://awsexamplebucket/awsexampleobject  --metadata-directive REPLACE

存储桶拥有者将对象复制在同一位置上后,对象将属于存储桶拥有者账户。

存储桶上启用了申请方付款

如果您的存储桶启用了 Requester Pays,则其他账户的用户在向您的存储桶发送请求时必须指定 request-payer 参数。否则,这些用户会遇到“拒绝访问”错误。

对于 GET、HEAD 或 POST 请求,用户必须在标头中添加 x-amz-request-payer 参数。对于 REST 请求,用户必须在请求中添加 x-amz-request-payer 参数。

对于 AWS 命令行界面 (AWS CLI) 命令,用户必须添加 --request-payer 参数,与以下内容类似:

aws s3 cp exampleobject.jpg s3://awsexamplebucket/exampleobject.jpg --request-payer requester