CloudFront + S3网站:应显示隐式索引文档时“指定的键不存在”

Posted

技术标签:

【中文标题】CloudFront + S3网站:应显示隐式索引文档时“指定的键不存在”【英文标题】:CloudFront + S3 Website: "The specified key does not exist" when an implicit index document should be displayed 【发布时间】:2016-03-07 17:40:17 【问题描述】:

我刚刚在 Amazon S3 上部署了一个静态网站,目前可以在这里查看:http://www.rdegges.com.s3-website-us-east-1.amazonaws.com/

如果您单击任何文章链接,您会注意到以下错误:

S3 抱怨文件不存在。现在,这很奇怪——我在我的域上使用 CloudFront。因此,当您单击该文章链接时,它会将请求发送到 CloudFront,然后它会尝试从 S3 存储桶中取回文件。

但是,如果您直接从 S3 访问相同的 URL,例如:http://www.rdegges.com.s3-website-us-east-1.amazonaws.com/2015/building-a-heroku-addon-planning/,页面将正常加载。

这里的翻译似乎遗漏了一些东西。

有人对我可以做些什么来修复我的设置提出建议吗?

【问题讨论】:

【参考方案1】:

我会冒险说指定的密钥在技术上不存在,因此错误消息在技术上是准确的,但并不能说明全部情况。这应该很容易解决。

S3 存储桶有两个¹端点,“REST”和“网站”。它们有两个不同的功能集。网站端点提供了索引文档的神奇解析(例如 index.html,在您提供的示例中,这似乎是实际应该返回给浏览器的内容),而 REST 端点则没有。

当您在用于网站托管的存储桶前面配置 CloudFront 时,您通常不希望通过从下拉列表中选择存储桶名称来将源配置为“S3”源;相反,您希望将其配置为“自定义”源,并使用 S3 控制台中提供的网站端点主机名(例如 example-bucket.s3-website-us-east-1...),否则,CloudFront 假定您希望它使用存储桶的 REST 端点(允许身份验证和私有内容,而网站端点则不允许)。

重要

不要从列表中选择您的存储桶的名称,例如,example.com.s3.amazonaws.com。

http://docs.aws.amazon.com/gettingstarted/latest/swh/getting-started-create-cfdist.html

由于最初回答了此问题,因此对文档进行了重构,因此上面显示的消息现在出现在一页后,并且已被重新措辞,但要点是相同的。 “存储桶的名称”似乎是指下拉菜单中显示的选项,这不是您想要的。

注意

请务必指定静态网站托管端点,而不是存储桶的名称。

http://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-cloudfront-walkthrough.html

您正在为存储桶使用 REST 端点的提示是错误消息以 XML 形式返回。如果您使用的是网站端点,那么网站端点将以 HTML 格式返回错误消息。

如前所述,为 CloudFront 分配创建一个新源,然后更改行为以将请求发送到新源,然后为 /* 发送 CloudFront 缓存失效请求,您应该已设置完毕。

另见:

http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html#WebsiteRestEndpointDiff


¹ 两个端点。从技术上讲,有两个以上,因为所有存储桶都至少有两个可能的 REST 端点主机名……但是端点有两种 类型。存储桶还有一个可选的传输加速终端节点,该终端节点使用 AWS 边缘网络(支持 CloudFront 的相同基础设施)进行更快/优化的传输,尤其是从远离预置存储桶的区域的地理位置传输,但不使用 CloudFront 缓存。如果您激活此端点,它看起来像https://example-bucket.s3-accelerate.amazonaws.com,并且对大多数请求收取额外的使用费,因为您使用更多的 AWS 网络和更少的公共互联网......但是,这是背后的区别- 端点的场景部署,而不是端点的行为。传输加速端点仍然是 REST 端点,因此与其他 REST 端点一样,它没有网站托管功能。 CloudFront 不允许您为源域名使用加速终端节点,因为这没有任何意义——如果允许这样的配置,请求和响应将通过 AWS 边缘网络循环两次,并增加延迟和成本,而无需提供任何好处。

【讨论】:

谢谢!这正是我的问题所在。这很有趣,因为我以前以这种方式部署了许多站点,而这从来都不是问题——我想到目前为止这一切都是相对幸运的,因为我的站点主要是单页。呵呵。 是的!非常感谢。超级有帮助。我希望犯这个愚蠢错误的其他人也能发现你的答案也很有用=) @rdegges 愚蠢的错误制造者签入。每次 CloudFront 调整需要 45 分钟,这占据了我生命中的一天。谈论微妙的...... @markdsievers 您会发现 CloudFront 调整通常会在几分钟内开始工作。如果对更改是否未按预期工作有疑问,您只需等待分发转换回Deployed。如果您知道自己做错了,您可以推动其他更改而不会产生不良影响。如果您遇到错误,它还有助于加快故障排除速度,发送至zero-out the Error Caching Minimum TTLs - 使用不同的计时器缓存错误响应。 提示:如果 AWS 控制台没有显示网站端点,您可以通过从存储桶中复制它来手动输入它静态网站托管 财产。它通常相同,但 s3 组件替换为 s3-website【参考方案2】:

在 CloudFront Origin Settings 中遇到了同样的问题以及我是如何解决的,将 Origin Domain Name 设置为 <website bucket>.s3-website-us-west-2.amazonaws.com

在 CloudFront Generate Settings 中确保将 index.html 作为默认根对象

在 S3 中,确保选择 Use this bucket to host a website 并将 index.html 设置为 索引文档

【讨论】:

我的解决方案是有人将默认根对象设置为/index.html 而不是index.html 谢谢!这正是我的情况的解决方案。 你我的男人,是一个传奇,你不知道我找了多久的答案!我使用类似的设置来托管图像并通过 lambda 和 API Gateway 运行图像大小调整脚本。 太棒了。这是解决方法! 这对我来说有一个额外的变化——我的 S3 存储桶包含一个文件夹,其中包含我的资产。除了上面提到的更改之外,我还必须修改 Web 端点以在 URL 之后添加我的文件夹,例如:website bucket>.s3-website-us-west-2.amazonaws.com/MYFOLDER【参考方案3】:

您是否在 S3 上托管 React 站点?可能与 React Router 一起使用?

注意:我的 S3 存储桶已关闭,不让公众访问,我也不想公开它。另外,虽然我遇到的问题和上面问的一样,但我的解决方案是不同的。

如果您像我一样想要公开您的 S3 端点,并且在使用 React Router 时遇到此问题,其中带有路由的直接 URL 在 CloudFront 上返回 403 Forbidden,请继续阅读:

发生这种情况是因为 CloudFront 期望 S3 存储桶具有您的 URL 应该指向的文件。

例如,如果您有一个静态站点“example.com”和一个路由“/stack”,CloudFront 将尝试在您的 S3 存储桶中查找“stack”文件。这显然不存在,CloudFront 会返回错误。

解决此问题的最佳方法是在 CloudFront 中为 HTTP 错误代码 403 设置自定义错误。自定义错误响应可以指向状态为“200 OK”的“index.html”页面。这将解决错误,将用户指向正确的文件,同时保留原始 URL(example.com/stack),然后 React Router 将获取该 URL。

【讨论】:

【参考方案4】:

请参阅 AWS 文档以了解如何use CloudFront to serve a static website hosted on S3 over https。

为方便起见(或以防链接失效)转录以下内容。


    在存储桶上使用Amazon S3 console 到create a bucket and to enable static website hosting。

    静态网站托管对话框中,复制您的存储桶的端点,不带前导http://。格式类似于 bucketname.s3-website-region.amazonaws.com。您需要此格式的端点以供后续步骤使用。

    Add a bucket policy that allows public read access 到您创建的存储桶。

    创建一个CloudFront web distribution。请务必配置以下内容:

    对于源域名,输入您在步骤 2 中复制的端点。 对于允许的 HTTP 方法,选择 GET、HEAD、OPTIONS。 对于备用域名 (CNAME),输入您要用于您的网站的 CNAME。

    如果您不想为您的网站使用 SSL (HTTPS),请继续执行下一步。如果您想为您的网站使用 SSL,您可以选择Request or Import a Certificate with ACM 来申请证书。如需更多信息,请参阅Using Alternate Domain Names and HTTPS。

    选择创建分布

    更新您的域的 DNS 记录,以将您网站的 CNAME 指向您的 CloudFront 分配的域名。您可以在CloudFront console 中找到您的发行版的域名,其格式类似于 d1234abcd.cloudfront.net

    等待您的 DNS 更改传播并等待之前的 DNS 条目过期。

【讨论】:

【参考方案5】:

我也遇到了类似的问题 我已经按照这些步骤解决了这个问题

步骤:

->go to CloudFront Distributions 
->click the ID
->after Clicking Id you will find different categories like General, Origins and Origin Groups .
->Click the Origins and Origin Groups
->Click the checkbox  of your s3 bucket and click edit
->under grand read Permissions on Bucket click "Yes, Update bucket policy"

这一步解决了我的问题。

【讨论】:

【参考方案6】:

我遇到了同样的问题,我是怎么解决的,下面是步骤

转到Amazon S3,然后转到您的存储桶目录

启用 S3 静态网站托管

转到权限选项卡 -> 阻止所有公共访问 -> 取消选中阻止所有公共访问并保存

转到权限选项卡 -> 存储桶策略 -> 编辑和保存


  "Version": "2012-10-17",
  "Statement": [
      
          "Sid": "PublicRead",
          "Effect": "Allow",
          "Principal": "*",
          "Action": [
              "s3:GetObject",
              "s3:GetObjectVersion"
          ],
          "Resource": "arn:aws:s3:::your-bucket-name/*"
      
  ]

注意:更改此行"Resource": "arn:aws:s3:::your-bucket-name/*"

例如:"Resource": "arn:aws:s3:::ng-ci-cd-aws-demo/*"

参考:https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html

【讨论】:

【参考方案7】:

要让 s3 网站与 Cloudfront 一起工作,有一些要求:

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

https://aws.amazon.com/premiumsupport/knowledge-center/s3-website-cloudfront-error-403/

我遇到的主要问题是,有两种类型的 s3 存储桶网址:

REST 端点格式:https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro

https://bucket-name.s3.Region.amazonaws.com

网站端点格式:https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html

http://bucket-name.s3-website-Region.amazonaws.com
http://bucket-name.s3-website.Region.amazonaws.com

在我的情况下,我需要使用 网站 网址而不是 REST 网址:

休息:http://project-name.s3.us-east-1.amazonaws.com 网址:http://project-name.s3-website-us-east-1.amazonaws.com

使用网站 url 将允许您使用 S3 的网站托管功能,例如索引/错误文档和重定向规则!

【讨论】:

【参考方案8】:

您应该按照以下步骤操作。

要使用 CloudFront 控制台更新您的存储桶策略,请执行以下步骤:

 1. Open the CloudFront console and choose your distribution.
 2. Choose the Origins and Origin Groups tab.
 3. Select the S3 origin and choose Edit.
 4. For Restrict Bucket Access, choose Yes.
 5. For Origin Access Identity, choose the existing identity or create a new one.
 6. For Grant Read Permissions on Bucket, choose Yes, Update Bucket Policy.
 7. Choose Yes, Edit.

如果您配置了 OAI,则 OAI 必须包含在 S3 存储桶策略中 如果您在 CloudFront 分配中添加了 OAI,则还必须在 S3 存储桶策略中包含 OAI 的允许语句。

要验证您的存储桶策略是否允许 OAI,请在 Amazon S3 控制台中打开您的 S3 存储桶。然后,选择 Permissions 选项卡并查看存储桶策略。以下是 OAI 的示例允许语句:


  "Sid": "1",
  "Effect": "Allow",
  "Principal": 
    "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EAF5XXXXXXXXX"
  ,
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"

参考: https://aws.amazon.com/tr/premiumsupport/knowledge-center/s3-rest-api-cloudfront-error-403/

【讨论】:

【参考方案9】:

访问 Cloudfront -> 您的分配

转到错误页面并单击添加错误页面。输入如下详细信息

【讨论】:

【参考方案10】:

当我尝试在我的 route53 重定向中为客户包含存储桶名称时遇到了这个问题,以使其更容易,例如:

https://0832234.signin.aws.amazon.com/console/s3/?bucket=clientbucket.com

点击“所有存储桶”并返回到客户端存储桶/或从 url 中删除存储桶就可以了,我现在可以下载并打开文件了。

【讨论】:

以上是关于CloudFront + S3网站:应显示隐式索引文档时“指定的键不存在”的主要内容,如果未能解决你的问题,请参考以下文章

CloudFront 不能使用 S3 网站来源,只能使用 REST 来源 Cloudformation

如何将 S3 网站的访问限制为 Cloudfront?

AWS CloudFront 重定向到 S3 存储桶

在 CloudFront/S3 中托管 Angular 应用程序 *无需* S3 静态网站托管

当请求标头具有 CloudFront + S3 网站的“接受编码”时,CORS 标头丢失

使用 S3、CloudFront 和源路径的静态网站托管的子文件夹重定向问题