域到 S3 存储桶的访问被拒绝

域到 S3 存储桶的访问被拒绝

您好,我遇到了一个问题,我在我的域中收到 AccessDenied 消息

我将我的网站上传到 AWS S3 Bucket,并将其公开,创建一个静态页面,但是当我通过我的 domain.com/mypage 访问时,出现 AccessDenied 错误。

从 aws mydomain.s3.amazonaws.com/mypage 运行良好。

我的域名 DNS 设置如下

;; ANSWER SECTION:
mydomain.com. 2101 IN CNAME mydomain.s3.amazonaws.com.
mydomain.s3.amazonaws.com. 41342 IN CNAME s3-1-w.amazonaws.com.
s3-1-w.amazonaws.com.   219 IN  CNAME   s3-w.us-east-1.amazonaws.com.
s3-w.us-east-1.amazonaws.com. 3 IN  A   52.217.69.36

有什么建议可以解决这个问题吗?

答案1

这是来自亚马逊支持文档

简短的介绍

要解决“访问被拒绝”错误,请确定您的分配的源域名是 S3 网站终端节点还是 S3 REST API 终端节点。请按照以下步骤确定终端节点类型:

  1. 打开 CloudFront 控制台。
  2. 选择您的 CloudFront 分发,然后选择分发设置。
  3. 选择来源和来源组选项卡。
  4. 选择来源和来源组选项卡。

查看源域名和路径下的域名,然后根据域名的格式确定终端节点类型。

REST API 端点使用以下格式:

DOC-EXAMPLE-BUCKET.s3.amazonaws.com

笔记:确保遵循 Amazon S3 存储桶的命名规则。

网站端点使用以下格式:

DOC-EXAMPLE-BUCKET.s3-website-us-east-1.amazonaws.com

笔记:根据 AWS 区域,端点格式可能使用破折号格式(s3-website-Region)或点格式(s3-website.Region)。

如果您的分发使用 REST API 端点,请参阅我正在使用 S3 REST API 端点作为我的 CloudFront 分发的来源。为什么我会收到 403 访问被拒绝错误?

如果您的分配使用网站终端节点,请验证以下要求以避免出现“访问被拒绝”错误:

  1. 存储桶中的对象必须是可公开访问的。
  2. 存储桶中的对象无法通过 AWS Key Management Service (AWS KMS) 加密。
  3. 存储桶策略必须允许访问 s3:GetObject。
  4. 如果存储桶策略授予公共读取访问权限,则拥有该存储桶的 AWS 账户也必须拥有该对象。5. 请求的对象必须存在于存储桶中。
  5. 必须在存储桶上禁用 Amazon S3 阻止公共访问。
  6. 如果启用了请求者付款,则请求必须包含请求付款人参数。
  7. 如果您使用 Referer 标头来限制从 CloudFront 到 S3 源的访问,请查看自定义标头。

笔记:如果您不想允许公开(匿名的) 访问您的 S3 对象,然后更改您的配置以使用 S3 REST API 终端节点作为您的分配的来源。然后,配置您的分配和 S3 存储桶以使用来源访问身份 (OAI) 限制访问。有关说明,请参阅如何使用 CloudFront 为托管在 Amazon S3 上的静态网站提供服务?中的使用 REST API 终端节点作为来源,并通过 OAI 限制访问。

解决

存储桶中的对象必须是可公开访问的

使用网站终端节点的分发仅支持可公开访问的内容。要确定 S3 存储桶中的对象是否可公开访问,请在 Web 浏览器中打开该对象的 URL。或者,您可以在 URL 上运行 curl 命令。

以下是 S3 对象的示例 URL:

http://DOC-EXAMPLE-BUCKET.s3-website-us-east-1.amazonaws.com/index.html

如果 Web 浏览器或 curl 命令返回“访问被拒绝”错误,则表示该对象不可公开访问。

通过以下方式之一允许对对象进行公共读取访问:

  1. 创建一个存储桶策略,允许对存储桶中的所有对象进行公开读取访问。
  2. 使用 Amazon S3 控制台允许对该对象的公共读取访问。
  3. 存储桶中的对象无法使用 AWS KMS 加密
  4. CloudFront 分配不支持 AWS KMS 加密对象。您必须从要使用该分配提供的 S3 对象中删除 KMS 加密。

笔记:不要使用 AWS KMS 加密,而是使用 AES-256 来加密您的对象。

使用以下方式之一检查存储桶中的对象是否经过 KMS 加密:

使用 Amazon S3 控制台查看对象的属性。查看加密对话框。如果选择了 AWS-KMS,则对象是 KMS 加密的。使用 AWS 命令​​行界面 (AWS CLI) 运行 head-object 命令。如果命令返回 ServerSideEncryption 作为 aws:kms,则对象是 KMS 加密的。注意:如果您在运行 AWS CLI 命令时收到错误,请确保您使用的是最新版本的 AWS CLI。要使用 Amazon S3 控制台更改对象的加密设置,请参阅如何向 S3 对象添加加密?

要使用AWS CLI,首先验证对象的存储桶没有默认加密。如果存储桶没有默认加密,则运行以下命令通过将对象复制到自身上来删除对象的加密:

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html

警告:将对象复制到自身上会删除存储类和
网站重定向位置的设置。若要在新对象中保留这些设置,请务必在复制请求中明确指定存储类或网站重定向位置值。

存储桶策略必须允许访问 s3:GetObject。要使用具有 S3 网站终端节点的分发,您的存储桶策略不得包含阻止对 s3:GetObject 操作进行公开读取访问的拒绝语句。

即使您的存储桶策略中有针对 s3:GetObject 的显式允许语句,也请确认没有冲突的显式拒绝语句。显式拒绝语句始终会覆盖显式允许语句。

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

  1. 从 Amazon S3 控制台打开您的 S3 存储桶。

  2. 选择权限选项卡。

  3. 选择存储桶策略。

  4. 查看带有“Action”:“s3:GetObject”或“Action”:“s3:*”的语句的存储桶策略。

以下示例策略包含一个显式允许语句,用于公开访问 s3:GetObject。但是,还有一个显式拒绝语句,用于阻止访问 s3:GetObject,除非请求来自特定的 Amazon Virtual Private Cloud (Amazon VPC)。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "Allow-OAI-Access-To-Bucket",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EAF5XXXXXXXXX"
            },
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
            ]
        },
        {
            "Sid": "Allow-Public-Access-To-Bucket",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
            ]
        },
        {
            "Sid": "Access-to-specific-VPCE-only",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpce": "vpce-1a2b3c4d"
                }
            }
        }
    ]
  }
  1. 修改存储桶策略以删除或编辑阻止对 s3:GetObject 进行公共读取访问的语句。

笔记:CloudFront 会将“访问被拒绝”错误的结果缓存在错误缓存最小 TTL 中指定的时间内。默认值为一分钟。从存储桶策略中删除拒绝语句后,您可以在分配上运行失效以从缓存中删除对象。

如果存储桶策略授予公共读取访问权限,则拥有该存储桶的 AWS 账户也必须拥有该对象。要使存储桶策略允许对对象进行公共读取访问,拥有该存储桶的 AWS 账户也必须拥有该对象。存储桶或对象归创建该存储桶或对象的 AWS Identity and Access Management (IAM) 身份的账户所有。

笔记:对象所有权要求适用于存储桶策略授予的公开读取访问权限。它不适用于对象的访问控制列表 (ACL) 授予的公开读取访问权限。

请按照以下步骤检查存储桶和对象是否具有相同的所有者:

  1. 运行此 AWS CLI 命令以获取存储桶拥有者的 S3 规范 ID:
aws s3api list-buckets --query Owner.ID
  1. 运行此命令以获取对象所有者的 S3 规范 ID:

注意:此示例显示单个对象,但您可以使用 list 命令检查多个对象。

aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html
  1. 如果规范 ID 不匹配,则存储桶和对象有不同的所有者。

注意:您还可以使用 Amazon S3 控制台检查存储桶和对象所有者。所有者位于相应存储桶或对象的“权限”选项卡中。

按照以下步骤将对象的所有者更改为存储桶所有者:

  1. 从对象所有者的帐户运行此命令以检索分配给该对象的 ACL 权限:
aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name
  1. 如果对象具有 bucket-owner-full-control ACL 权限,则跳至步骤 3。如果对象没有 bucket-owner-full-control ACL 权限,则从对象所有者的账户运行此命令:
aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name --acl bucket-owner-full-control
  1. 从存储桶拥有者的账户运行此命令,通过将对象复制到自身来更改对象的所有者:
aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html

请求的对象必须存在于存储桶中如果用户没有 s3:ListBucket 权限,则用户会收到缺少对象的“访问被拒绝”错误,而不是“404 未找到”错误。运行 head-object AWS CLI 命令检查存储桶中是否存在对象。

笔记:确认发送到 CloudFront 的对象请求与 S3 对象名称完全匹配。S3 对象名称区分大小写。如果请求没有正确的对象名称,则 Amazon S3 会响应该对象缺失的情况。要识别 CloudFront 从 Amazon S3 请求哪个对象,请使用服务器访问日志记录。

如果存储桶中存在该对象,则不会出现“访问被拒绝”错误 屏蔽 404 Not Found 错误. 验证其他配置要求以解决“访问被拒绝”错误。

如果对象不在存储桶中,则“访问被拒绝”错误为 屏蔽 404 Not Found 错误.解决与缺失对象相关的问题。

笔记:启用公共 s3:ListBucket 访问权限并非最佳安全做法。启用公共 s3:ListBucket 访问权限允许用户查看和列出存储桶中的所有对象。即使用户没有下载对象的权限,这也向用户公开了对象元数据详细信息(例如,密钥和大小)。

必须在存储桶上禁用 Amazon S3 阻止公共访问确认存储桶未应用任何 Amazon S3 阻止公共访问设置。这些设置可以覆盖允许公共读取访问的权限。Amazon S3 阻止公共访问设置可应用于单个存储桶或 AWS 账户。

如果启用了请求方付款,则请求必须包含请求付款人参数。如果在存储桶上启用了请求方付款,则不允许匿名访问该存储桶。其他账户的用户在向存储桶发送请求时必须指定请求付款人参数。否则,这些用户会收到“访问被拒绝”错误。

如果您使用 Referer 标头来限制从 CloudFront 到 S3 源的访问,则请检查自定义标头。如果您使用 Referer 标头来限制从 CloudFront 到 S3 网站终端节点源的访问,请检查 S3 存储桶策略上设置的密钥值或令牌。然后,确认密钥值或令牌与 CloudFront 源自定义标头上的值匹配。

如果您在存储桶策略中使用显式拒绝语句,请确认还存在根据 Referer 标头授予访问权限的允许语句。您无法仅使用显式拒绝语句授予访问权限。

例如,当请求包含字符串时,以下存储桶策略授予对 S3 源的访问权限 “aws:Referer”:“MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER”:

{
  "Version":"2012-10-17",
  "Id":"http referer policy example",
  "Statement":[
    {
      "Sid":"Allow get requests originating from my CloudFront with referer header",
      "Effect":"Allow",
      "Principal":"*",
      "Action":"s3:GetObject",
      "Resource":"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
      "Condition":{
        "StringLike":{"aws:Referer":"MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER"}
      }
    }
  ]
}

对于此示例存储桶策略,CloudFront 源自定义标头必须是:

  • 标头: 引荐来源
  • 价值:MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER

笔记: 示例存储桶策略授予对存储桶的公共(匿名)访问权限,因为 Principal 是通配符值(“Principal”:“*”)。但是,由于条件语句,仅当请求包含 Referer 标头且标头值与存储桶策略中的值匹配时,才授予对 S3 源的访问权限。

相关内容