仅允许通过CloudFront访问S3静态网站的配置问题排查
我在AWS上搭建了一个简单的静态网站作为练习,网站存储在AWS S3 Bucket中,结构如下:
/ ├─ releases/ │ ├─ index.html │ ├─ index.js │ ├─ index.css ├─ secret.html
我配置了Bucket Policy,仅允许访问releases目录,禁止访问存储secret.html的根目录,原有策略如下:
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::www.aws-serverless.tc/releases/*" } ] }
为提升网站的可靠性与安全性,我配置了CloudFront,目前网站可通过http://*.s3-website.eu-north-1.amazonaws.com和https://*.cloudfront.net两种URL访问。
我希望网站仅能通过CloudFront URL访问,而非S3网站URL。于是我尝试了以下配置(已替换为自己的S3 Bucket ARN和CloudFront ARN):
{ "Version": "2012-10-17", "Statement": { "Sid": "AllowCloudFrontServicePrincipalReadOnly", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<S3 bucket name>/releases/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/<CloudFront distribution ID>" } } } }
替换原有配置后,S3网站URL返回403(符合预期),但CloudFront URL也返回403。该配置来自亚马逊官方文档,请问为何未达到预期效果?
源类型配置错误:如果CloudFront分发的源设置为S3网站端点(格式如
http://<bucket-name>.s3-website-<region>.amazonaws.com),CloudFront会以匿名身份向S3发起请求,不会携带CloudFront服务主体的身份信息,导致Bucket Policy中的AWS:SourceArn条件无法匹配,最终返回403。此时需要将源切换为S3 REST API端点(格式如<bucket-name>.s3.<region>.amazonaws.com),这样CloudFront才会使用服务主体身份访问S3,匹配策略中的条件。ARN或策略语法错误:检查CloudFront分发的ARN是否完全正确(账号ID、分发ID无拼写错误),同时确认S3 Bucket名称在Resource ARN中无误。另外,确保策略版本
2012-10-17对应的语法格式正确,比如单个Statement用对象、多个用数组的规则(你的配置为单个Statement,格式没问题)。缓存行为与HTTP方法限制:确认CloudFront缓存行为中允许的HTTP方法包含
GET和HEAD,静态网站访问通常需要这两种方法,若限制过严也会导致403。
修正步骤:
- 进入CloudFront控制台,找到目标分发并编辑源设置;
- 将源域名替换为S3 REST API端点(可从S3控制台的Bucket概述页面复制);
- 检查缓存行为的HTTP方法配置,确保
GET、HEAD被允许; - 保存配置后等待CloudFront部署完成(通常需5-15分钟),再测试CloudFront URL的访问情况。
内容的提问来源于stack exchange,提问作者violetflare

