如何对来自 Amazon S3 的 403 访问被拒绝错误执行故障排查?

上次更新日期:2022 年 5 月 13 日

我的用户尝试访问我的 Amazon Simple Storage Service (Amazon S3) 存储桶中的对象,但 Amazon S3 返回“403 访问被拒绝”错误。如何解决此错误?

解决方法

使用 AWS Systems Manager 自动化文档

在 AWS Systems Manager 上使用 AWSSupport-TroubleshootS3PublicRead 自动化文档。此自动化文档可帮助您诊断关于从您指定的公共 S3 存储桶读取对象的问题。

检查存储桶和对象所有权

对于来自 GetObjectHeadObject 请求的 AccessDenied 错误,请检查该对象是否也归存储桶拥有者所有。此外,请验证存储桶拥有者是否具有读取或完全控制访问控制列表(ACL)权限

确认拥有这些对象的账户

默认情况下,S3 对象归上传此对象的 AWS 账户所有。即使存储桶由另一个账户拥有,也是如此。如果其他账户可以将对象上传到您的存储桶,则验证您的用户无法访问的对象所属的账户。

注意:如果在运行 AWS CLI 命令时收到错误,请确保您使用的是最新的 AWS CLI 版本

1.    通过查询拥有者 ID 运行 list-buckets AWS Command Line Interface (AWS CLI) 命令以获取账户的 Amazon S3 规范 ID。

aws s3api list-buckets --query "Owner.ID"

2.    运行 list-objects 命令以获取用户无法访问的对象所属账户的 Amazon S3 规范 ID。将 DOC-EXAMPLE-BUCKET 替换为您的存储桶名称,并将 exampleprefix 替换为您的前缀值。

aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix exampleprefix

提示:使用 list-objects 命令查看多个对象。

3.    如果规范 ID 不匹配,则您不拥有该对象。对象拥有者可以通过运行 put-object-acl 命令授予您对该对象的完全控制权限。将 DOC-EXAMPLE-BUCKET 替换为包含对象的存储桶的名称。将 exampleobject.jpg 替换为您的键名称。

aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key exampleobject.jpg --acl bucket-owner-full-control

4.    在对象拥有者将对象的 ACL 更改为 bucket-owner-full-control 后,存储桶拥有者可以访问该对象。但是,仅更改 ACL 不会更改对象的所有权。要将对象拥有者更改为存储桶的账户,请从存储桶账户运行 cp 命令,将对象复制到其自身上。

将所有新对象复制到另一个账户的存储桶中

1.    设置一个存储桶策略,该策略要求使用 bucket-owner-full-control ACL 上传对象

2.    然后,在 AWS 管理控制台中启用 S3 对象所有权并将其设置为首选的存储桶拥有者

然后,使用 bucket-owner-full-control ACL 上传该对象时,自动将该对象的拥有者更新为存储桶拥有者。

创建具有存储桶权限的 IAM 角色

对于持续的跨账户权限,在账户中创建具有存储桶权限的 IAM 角色。然后,授予另一个 AWS 账户代入该 IAM 角色的权限。有关更多信息,请参阅教程:使用 IAM 角色委派跨 AWS 账户的访问权限

检查存储桶策略或 IAM 用户策略

查看存储桶策略或关联的 IAM 用户策略中可能拒绝访问的任何语句。验证对存储桶的请求满足存储桶策略或 IAM 策略中的任何条件。检查策略中是否有任何错误的拒绝语句、缺失的操作或错误的空格。

拒绝语句条件

根据以下内容检查拒绝语句是否存在阻止访问的条件:

  • 多重身份验证 (MFA)
  • 加密密钥
  • 特定的 IP 地址
  • 特定的 VPC 或 VPC 终端节点
  • 特定的 IAM 用户或角色

注意:如果您要求进行 MFA,且用户通过 AWS CLI 发送请求,请确保用户配置 AWS CLI 以使用 MFA

例如,在下面的存储桶策略中,Statement1 允许公共访问从 DOC-EXAMPLE-BUCKET 下载对象 (s3:GetObject)。然而,Statement2 明确地拒绝任何人从 DOC-EXAMPLE-BUCKET 下载对象,除非请求来自 VPC 终端节点 vpce-1a2b3c4d。在这种情况下,拒绝语句优先。这意味着尝试从 vpce-1a2b3c4d 以外下载对象的用户将被拒绝访问。

{
  "Id": "Policy1234567890123",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Statement1",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
      "Principal": "*"
    },
    {
      "Sid": "Statement2",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Deny",
      "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpce": "vpce-1a2b3c4d"
        }
      },
      "Principal": "*"
    }
  ]
}

存储桶策略或 IAM 策略

检查存储桶策略或 IAM 策略是否允许用户需要采取的 Amazon S3 操作。例如,以下存储桶策略不包含 s3:PutObjectAcl 操作的权限。如果 IAM 用户尝试修改对象的访问控制列表(ACL),则用户会遇到“访问被拒绝”错误。

{
  "Id": "Policy1234567890123",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1234567890123",
      "Action": [
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
      "Principal": {
        "AWS": [
          "arn:aws:iam::111122223333:user/Dave"
        ]
      }
    }
  ]
}

其他策略错误

确认存储桶策略或 IAM 用户策略中没有任何多余的空格或不正确的 ARN。

例如,如果 IAM 策略的 Amazon Resource Name (ARN) 中存在一个多余的空格,如下所示:arn:aws:s3::: DOC-EXAMPLE-BUCKET/*。在这种情况下,ARN 会被错误地评估为 arn:aws:s3:::%20DOC-EXAMPLE-BUCKET/,并给出 IAM 用户访问被拒绝的错误。

确认 IAM 权限边界允许访问 Amazon S3

查看在尝试访问存储桶的 IAM 身份上设置的 IAM 权限边界。确认 IAM 权限边界允许访问 Amazon S3。

检查存储桶的 Amazon S3 阻止公有访问设置

如果您在被允许的公共读取请求上遇到“访问被拒绝”错误,请检查存储桶的 Amazon S3 阻止公有访问设置。

在账户和存储桶级别查看“S3 阻止公有访问”设置。这些设置会覆盖允许公开读取访问的权限。Amazon S3 阻止公共访问可以应用于各个存储桶或 AWS 账户。

查看用户凭证

查看用户已配置用于访问 Amazon S3 的凭证。必须将 AWS 开发工具包和 AWS CLI 配置为使用可访问您的存储桶的 IAM 用户或角色的凭证。

对于 AWS CLI,运行 configure 命令以检查所配置的凭证:

aws configure list

如果用户通过 Amazon Elastic Compute Cloud(Amazon EC2)实例访问您的存储桶,则验证实例是否使用了正确的角色。连接到实例,然后运行 get-caller-identity 命令:

aws sts get-caller-identity

查看临时安全凭证

如果用户收到使用 AWS Security Token Service(AWS STS)授予的临时安全凭证发出的“访问被拒绝”错误,请查看关联的会话策略。当管理员使用 AssumeRole API 调用或 assume-role 命令创建临时安全凭证时,他们可以传递特定于会话的策略。

要查找与来自 Amazon S3 的访问被拒绝错误相关联的会话策略,请在 AWS CloudTrail 事件历史记录中查找 AssumeRole 事件。请确保在与访问 Amazon S3 的失败请求相同的时间范围内查找 AssumeRole 事件。然后,查看相关 CloudTrail 日志中 requestParameters 字段中的任何 policypolicyArns 参数。确认关联的策略或策略 ARN 授予了必要的 Amazon S3 权限。

例如,下面的 CloudTrail 日志代码段显示临时凭证包含一个内联会话策略,该策略将 s3:GetObject 权限授予 DOC-EXAMPLE-BUCKET

"requestParameters": {
        "roleArn": "arn:aws:iam::123412341234:role/S3AdminAccess",
        "roleSessionName": "s3rolesession",
        "policy": "{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n  {\n  \"Effect\": \"Allow\",\n           
         \"Action\": [\n   \"s3:GetObject\"\n ],\n    \"Resource\": [\n \"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*\"\n  ]\n   }  }\n    ]\n}\n"
    }

确认 Amazon VPC 终端节点策略包含访问 S3 存储桶和对象的正确权限

如果用户使用通过 VPC 终端节点路由的 EC2 实例访问您的存储桶,则检查 VPC 终端节点策略

例如,以下 VPC 终端节点策略仅允许访问 DOC-EXAMPLE-BUCKET。通过此 VPC 终端节点发送请求的用户无法访问任何其他存储桶。

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

查看您的 Amazon S3 访问点的 IAM 策略

如果您使用 Amazon S3 访问点来管理对存储桶的访问,请查看访问点的 IAM 策略

只有在底层存储桶策略也允许相同的访问时,访问点策略中授予的权限才有效。确认存储桶策略和访问点策略授予了正确的权限。

确认对象没有丢失对象或包含特殊字符

检查存储桶中是否存在请求的对象。否则,请求找不到对象,Amazon S3 会假定该对象不存在。如果您没有适当的 s3:ListBucket 权限,那么您会收到“访问被拒绝”错误(而不是“404 未找到”错误)。

具有特殊字符(例如空格)的对象需要进行特殊处理才能检索该对象。

运行 head-object AWS CLI 命令以检查存储桶中是否存在某对象。将 DOC-EXAMPLE-BUCKET 替换为您要检查的存储桶的名称。

aws s3api head-object --bucket DOC-EXAMPLE-BUCKET --key exampleobject.jpg

如果存储桶中存在该对象,则“访问被拒绝”错误不会屏蔽“404 未找到”错误。检查其他配置要求以解决“访问被拒绝”错误。

如果存储桶中不存在该对象,则“访问被拒绝”错误将屏蔽“404 未找到”错误。解决与对象缺失相关的问题。

检查 AWS KMS 加密配置

请注意以下有关 AWS KMS(SSE-KMS)加密的事项:

  • 如果 IAM 用户无法访问用户具有完全权限的对象,则检查该对象是否经 SSE-KMS 加密。您可以使用 Amazon S3 控制台查看对象的属性,其中包括对象的服务器端加密信息。
  • 如果对象经 SSE-KMS 加密,请确保 KMS 密钥策略授予 IAM 用户使用密钥所需的最低权限。例如,如果 IAM 用户仅使用密钥下载 S3 对象,则 IAM 用户必须拥有 kms:Decrypt 权限。有关更多信息,请参阅允许访问 AWS 账户并启用 IAM 策略
  • 如果 IAM 身份和密钥在同一账户中,则需要使用密钥策略授予 kms:Decrypt 权限。密钥策略必须引用与 IAM 策略相同的 IAM 身份。
  • 如果 IAM 用户所属的账户与 AWS KMS 密钥不同,则还必须在 IAM 策略上授予这些权限。例如,要下载 SSE-KMS 加密的对象,必须在密钥策略和 IAM 策略中指定 kms:Decrypt 权限。有关 IAM 用户和 KMS 密钥之间的跨账户访问的更多信息,请参阅允许其他账户中的用户使用 KMS 密钥

确认 request-payer 参数由用户指定(如果您使用的是申请方付款)

如果您的存储桶激活了申请方付款,则其他账户的用户在向您的存储桶发送请求时必须指定 request-payer 参数。要检查“申请方付款”是否已启用,请使用 Amazon S3 控制台查看存储桶属性

以下 AWS CLI 命令示例包含访问启用了“申请方付款”的跨账户存储桶的正确参数:

aws s3 cp exampleobject.jpg s3://DOC-EXAMPLE-BUCKET/exampleobject.jpg --request-payer requester

检查 AWS Organizations 服务控制策略

如果您使用的是 AWS Organizations,则检查服务控制策略以确保允许访问 Amazon S3。服务控制策略为受影响的账户指定最大权限。例如,以下策略明确拒绝访问 Amazon S3 并导致“访问被拒”错误:

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

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


这篇文章对您有帮助吗?


您是否需要账单或技术支持?