为什么我在使用 S3 REST API 端点作为 CloudFront 分配的源时收到“403 Access Denied”错误?
我想解决 Amazon CloudFront 从 Amazon Simple Storage Service (Amazon S3) 返回的“403 Access Denied”错误。
简短描述
为避免“Access Denied”错误,请使用以下配置:
- 将 S3 对象设为可公开访问。
- 对包含使用 AWS Key Management Service (AWS KMS) 进行服务器端加密的对象的 S3 存储桶使用来源访问控制 (OAC)。
**注意:**您必须使用 OAC 而不是来源访问身份 (OAI)。因为 OAI 不提供 AWS KMS 加密对象。 - 修改 S3 存储桶策略,使其允许访问 s3:GetObject。
- 确保拥有 S3 存储桶的 AWS 账户也拥有该对象。
- 确认请求的对象存在于 S3 存储桶中。
- 定义默认根对象,以便客户端可以请求您的分配的根。
- 对于 OAI 配置,您必须将 OAI 包含在 S3 存储桶策略中。对于 OAC 配置,您必须在 S3 存储桶策略中包含 CloudFront 服务主体。
解决方法
**注意:**如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI。
将 S3 对象设为可公开访问
要确定 S3 存储桶中的对象是否可公开访问,请在 Web 浏览器中打开 S3 对象的 URL。或者,在 URL 上运行 curl 命令。
以下是 S3 对象的示例 URL:
https://DOC-EXAMPLE-BUCKET.s3.amazonaws.com/index.html
如果 Web 浏览器或 curl 命令返回“Access Denied”错误,则对象不可公开访问。
要将对象设为可公开访问,请执行以下操作之一:
- 创建为存储桶授予只读权限的存储桶策略。
- 使用 S3 控制台允许对对象进行公开读取访问。
- 使用 REST API 端点为分配配置 OAC 或 OAI。
- 使用 AWS 签名版本 4 对 S3 的请求进行身份验证。
对 AWS KMS 加密的对象使用 OAC
要使用 OAC,请向 AWS KMS 密钥策略添加一条语句,以授予 CloudFront 服务主体使用密钥的权限。您也可以使用 Lambda@Edge 代替 OAC。有关详细信息,请参阅 Serving SSE-KMS encrypted content from S3 using CloudFront(使用 CloudFront 从 S3 提供 SSE-KMS 加密内容)。
要确认您使用 AWS KMS 加密了对象,请执行以下操作之一:
- 使用 S3 控制台查看对象的属性。查看 Encryption(加密)对话框。如果选择了 AWS KMS,则对象是经过 AWS KMS 加密的。
- 运行 head-object 命令。如果此命令的 ServerSideEncryption 返回 aws:kms,说明对象是使用 AWS KMS 加密。
允许访问 s3: getObject
即使您的存储桶策略中有 s3:GetObject 的显式允许语句,也要确认不存在冲突的显式拒绝语句。显式拒绝语句会覆盖显式允许语句。有关拒绝和允许语句的详细信息,请参阅策略评估逻辑。
要确认您的存储桶策略允许 s3:GetObject 且不允许显式拒绝语句,请完成以下步骤:
-
打开 Amazon S3 控制台。
-
选择您的存储桶。
-
选择 Permissions(权限)选项卡。
-
选择 Bucket policy(存储桶策略)。
-
检查带有 "Action": "s3:GetObject" 或 "Action": "s3:*" 的语句。
以下示例策略包括授予 CloudFront OAC 和 CloudFront OAI 访问 s3:GetObject 权限的允许语句。它还包括允许公众访问 s3:GetObject 的允许语句。但是,s3:GetObject 有一个显示拒绝语句,它会阻止访问,除非请求来自特定 Amazon Virtual Private Cloud(Amazon VPC)。{ "Version": "2012-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [{ "Sid": "Allow-OAC-Access-To-Bucket", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE" } } }, { "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" } } } ] } -
修改存储桶策略以删除或编辑阻止 CloudFront OAI、CloudFront OAC 访问或公开访问 s3:GetObject 的语句。
注意:CloudFront 会将“Access Denied”错误的结果缓存长达 5 分钟。从存储桶策略中删除拒绝语句后,您可以在您的分配上运行失效操作,以从缓存中删除对象。
授予 S3 存储桶和对象的所有权
创建存储桶或对象的 AWS Identity and Access Management (IAM) 身份账户拥有该存储桶或对象。
**注意:**对象所有权要求仅适用于存储桶策略授予的访问权限。不适用于对象的访问控制列表 (ACL) 授予的访问权限。
要检查存储桶和对象的拥有者是否相同,请完成以下步骤:
-
运行 list-buckets 命令获取存储桶所有者的 S3 规范 ID:
aws s3api list-buckets --query Owner.ID -
运行 list-objects 命令获取对象所有者的 S3 规范 ID:
aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html**注意:**上述示例命令的输出显示一个对象,但您可以使用 list-objects 命令检查多个对象。
如果规范 ID 不匹配,则表示存储桶和对象的所有者不同。
**注意:**您还可以使用 Amazon S3 控制台来检查存储桶和对象所有者。您可以在存储桶或对象的 Permissions(权限)选项卡上找到所有者。
要将对象的所有者更改为存储桶所有者,请完成以下步骤:
-
在对象所有者的账户中,运行 get-object-acl 命令来检索 ACL 权限:
aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name -
如果对象具有 bucket-owner-full-control ACL 权限,跳到步骤 3。如果对象没有 bucket-owner-full-control ACL 权限,则从对象所有者的账户运行 put-object-acl 命令:
aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name --acl bucket-owner-full-control -
在存储桶所有者的账户中,运行以下命令复制并覆盖对象,然后更改对象的所有者:
aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html --storage-class STANDARD**注意:**将 --storage-class 替换为您的存储类。
将对象移至存储桶
要检查存储桶中是否存在该对象,请运行 head-object 命令。
**注意:**S3 对象名称区分大小写。确认发送到 CloudFront 的对象请求与 S3 对象名称完全相符。如果请求没有正确的对象名称,则 Amazon S3 会像对象缺失一样进行响应。要识别 CloudFront 从 Amazon S3 请求的对象,请使用服务器访问日志记录。
如果存储桶中存在该对象,“Access Denied”错误不会屏蔽”404 Not Found“错误。检查其他配置要求以解决“Access Denied”错误。
如果存储桶中不存在该对象,则“Access Denied”错误将屏蔽“404 Not Found”错误。您必须解决与对象缺失相关的问题。
定义默认根对象
要定义默认根对象,请参阅 Specifying a default root object(指定默认根对象)。
**注意:**拒绝公共 s3:ListBucket 访问权限是一种安全最佳实践。如果您允许公共 s3:ListBucket 访问权限,则用户可以查看和列出存储桶中的所有对象。这会向所有用户公开对象元数据详细信息,例如密钥和大小。
在 S3 存储桶策略中添加 OAI 或 CloudFront 服务主体权限
要检查您的存储桶策略是否允许 OAI,请打开 Amazon S3 控制台。找到您的存储桶,然后在 Permissions(权限)选项卡上,选择 Bucket policy(存储桶策略)。
在配置 OAC 时,以下示例策略包括 CloudFront 服务主体的允许语句:
{ "Sid": "Allow-OAC-Access-To-Bucket", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE" } } }
以下示例策略包括 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/*" }
要在 CloudFront 控制台上更新您的存储桶策略,请完成以下步骤:
- 打开 CloudFront 控制台。
- 选择您的分配。
- 选择 Origins and Origin Groups(源和源组)选项卡。
- 选择 S3 来源,然后选择 Edit(编辑)。
- 对于 Restrict Bucket Access(限制存储桶访问),选择 Yes(是)。
- 对于 Origin Access Identity(来源访问身份),选择现有身份或创建一个新身份。
- 对于 Grant read permissions on bucket(授予对存储桶的读取权限),选择 Yes, update bucket policy(是,更新存储桶策略)。
- 选择 Yes, edit(是,请编辑)。
相关信息
Troubleshooting error response status codes in CloudFront(对 CloudFront 中的错误响应状态代码进行故障排除)
如何对来自 Amazon S3 的“403 Access Denied”错误进行故障排除?
为什么我在使用 Amazon S3 网站端点作为 CloudFront 分配的源时收到“403 access denied”错误?
- 语言
- 中文 (简体)

