我使用 S3 REST API 端点作为我的 CloudFront 分配的来源。为什么我会收到“403 访问被拒绝”错误?
我正在使用 Amazon Simple Storage Service(Amazon S3)存储桶作为我的 Amazon CloudFront 分配的来源。我正在使用 S3 REST API 端点作为源域名。CloudFront 从 Amazon S3 返回 403 访问被拒绝错误。
简短描述
要排查访问被拒绝错误,请确定您的分配的源域名是 S3 网站端点还是 S3 REST API 端点。请按照下面的步骤查找端点类型:
1. 打开 CloudFront 控制台。
2. 选择您的 CloudFront 分配。然后,选择分配设置。
3. 选择源和源组选项卡。
4. 在源域名和路径下查看域名。然后,根据域名的格式确定端点类型。REST API 端点使用下列格式:
DOC-EXAMPLE-BUCKET.s3.region.amazonaws.com DOC-EXAMPLE-BUCKET.s3.amazonaws.com
**重要提示:**格式 bucket-name.s3.amazonaws.com 不适用于 2019 年或之后推出的区域。静态网站端点使用以下格式:
DOC-EXAMPLE-BUCKET.s3-website-us-east-1.amazonaws.com
如果您的分配使用 S3 静态网站端点,则可能会收到 403 访问被拒绝错误。有关更多信息,请参阅I’m using an S3 website endpoint as the origin of my CloudFront distribution。为什么我会收到 403 Access Denied(访问被拒绝)错误?
如果您的分配使用 REST API 端点,请验证您的配置是否满足下面的要求,以避免访问被拒绝错误:
- 如果未配置来源访问控制(OAC)或来源访问身份(OAI),则对象必须可公开访问。或者,必须使用 AWS 签名版本 4 来请求对象。
- 如果 S3 存储桶包含由 AWS Key Management Service(AWS KMS)加密的对象,则应使用 OAC 而不是 OAI。
- S3 存储桶策略必须允许访问 s3:GetObject。
- 如果存储桶策略授予访问权限,那么拥有 S3 存储桶的 AWS 账户也必须拥有该对象。
- 所请求的对象必须存在于 S3 存储桶中。
- 如果客户端请求您的分配的根目录,则必须定义默认根对象。
- 如果配置了 OAI,则必须在 S3 存储桶策略中包含该 OAI。
- 如果配置了 OAC,则必须在 S3 存储桶策略中包含 CloudFront 服务主体。如果配置了 OAI,则必须在 S3 存储桶策略中包含该 OAI。
- 如果未配置 OAC 或 OAI,则必须在存储桶上关闭 Amazon S3 屏蔽公共访问权限。
解决方案
如果未配置 OAC 或 OAI,则您的对象必须可公开访问,或者使用 AWS 签名版本 4 进行请求。
要确定 S3 存储桶中的对象是否可公开访问,请在 Web 浏览器中打开 S3 对象的 URL。或者,在 URL 上运行 curl 命令。
下面是 S3 对象的示例 URL:
https://DOC-EXAMPLE-BUCKET.s3.amazonaws.com/index.html
如果 Web 浏览器或 curl 命令返回“访问被拒绝”错误,则对象不可公开访问。如果对象不可公开访问,则使用下面其中一种配置:
- 创建一个允许对存储桶中的所有对象进行公共读取访问的存储桶策略。
- 使用 Amazon S3 控制台来允许对对象进行公共读取访问。
- 使用 REST API 端点为分配配置 OAC 或 OAI。
- 使用 AWS 签名版本 4 对发送到 Amazon S3 的请求进行身份验证。
由 AWS Key Management Service(AWS SSE-KMS)加密的对象
如果 S3 存储桶包含由 AWS Key Management Service(AWS SSE-KMS)加密的对象,则应使用 OAC 而不是 OAI。
通过设置 OAC,可以使用 CloudFront,为 AWS KMS 加密的对象提供服务。为此,请向 AWS KMS 密钥政策添加一条语句,以授予 CloudFront 服务主体使用密钥的权限。要在不设置 OAC 的情况下为 AWS KMS 加密的对象提供服务,请使用 Lambda@Edge ,为从 S3 存储桶加密的 AWS KMS 密钥提供服务。
使用以下方法之一检查存储桶中的对象是否经过 AWS KMS 加密:
- 使用 Amazon S3 控制台查看对象的属性。查看“加密”对话框。如果选择了 AWS KMS,则对象是经过 AWS KMS 加密的。
- 使用 AWS 命令行界面(AWS CLI)运行 head-object 命令。如果该命令以 aws:kms 的形式返回 ServerSideEncryption,则对象是经过 AWS KMS 加密的。如果在运行 AWS CLI 命令时收到错误,则确保您使用的是最新版本的 AWS CLI。
**注意:**OAI 不支持为 AWS KMS 加密的对象提供服务。
S3 存储桶策略必须允许访问 s3:GetObject
要使用带有 S3 REST API 端点的分配,存储桶策略必须允许公共用户或 CloudFront 的 OAI 使用 s3:GetObject。即使您的存储桶策略中有 s3:GetObject 的显式允许语句,也要确认不存在冲突的显式拒绝语句。显式拒绝语句始终会覆盖显式允许语句。
请按照下面的步骤查看 s3:GetObject 的存储桶策略:
1. 从 Amazon S3 控制台打开您的 S3 存储桶。
2. 选择“权限”选项卡。
3. 选择存储桶策略。
4. 查看存储桶策略中是否有带 "Action": "s3:GetObject" 或 "Action": "s3:*" 的语句。下面的示例策略包括一个允许语句,其授予 CloudFront OAC 对 s3:GetObject 的访问权限。它还包括一个授予 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" } } } ] }
5. 修改存储桶策略以删除或编辑阻止 CloudFront OAI 访问或公开访问 s3:GetObject 的语句
**注意:**CloudFront 会将访问被拒绝错误的结果缓存长达五分钟。从存储桶策略中删除拒绝语句后,您可以在您的分配上运行失效操作,以从缓存中删除对象。
S3 存储桶和对象的所有权
要将存储桶策略应用于外部账户或者服务,拥有该存储桶的 AWS 账户也必须拥有这些对象。存储桶或对象归创建存储桶或对象的 AWS Identity and Access Management(IAM)身份账户所有。
**注意:**对象所有权要求适用于存储桶策略授予的访问权限。它不适用于对象的访问控制列表(ACL)授予的访问权限。
请按照下面的步骤检查存储桶和对象的所有者是否相同:
1. 运行此 AWS CLI 命令以获取存储桶所有者的 S3 规范 ID:
aws s3api list-buckets --query Owner.ID
2. 运行此命令以获取对象所有者的 S3 规范 ID:
**注意:**此示例显示了一个对象,但您可以使用 list 命令来检查多个对象。
aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html
3. 如果规范 ID 不匹配,则表示存储桶和对象的所有者不同。
**注意:**您还可以使用 Amazon S3 控制台来检查存储桶和对象所有者。所有者可在相应存储桶或对象的“权限”选项卡中找到。
请按照下面的步骤将对象的所有者更改为存储桶所有者:
1. 从对象所有者的 AWS 账户中,运行此命令来检索分配给该对象的访问控制列表(ACL)权限:
aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name
2. 如果对象具有 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
3. 从存储桶所有者的账户中,运行以下命令,通过将对象复制到其自身上来更改对象的所有者:
aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html --storage-class STANDARD
**注意:**确保将示例命令中的 --storage-class 值更改为适用于您的用例的存储类。
请求的对象必须存在于存储桶中
如果用户没有 s3:ListBucket 权限,则该用户将获得缺失对象的“访问被拒绝”错误,而不是“404 未找到”错误。运行 head-object AWS CLI 命令以检查存储桶中是否存在对象。
**注意:**确认发送到 CloudFront 的对象请求与 S3 对象名称完全相符。S3 对象名称区分大小写。如果请求没有正确的对象名称,则 Amazon S3 会像对象缺失一样进行响应。要确定 CloudFront 正在从 Amazon S3 请求哪个对象,请使用服务器访问日志记录。
如果存储桶中存在该对象,则“访问被拒绝”错误不会屏蔽“404 未找到”错误。验证其他配置要求以解决“访问被拒绝”错误。
如果存储桶中不存在该对象,则“访问被拒绝”错误将屏蔽“404 未找到”错误。解决与对象缺失相关的问题。
**注意:**允许公有 s3:ListBucket 访问不是安全最佳实践。允许公有 s3:ListBucket 访问让用户能够查看和列出存储桶中的所有对象。这会向用户公开对象元数据详细信息(例如,密钥和大小),即使用户没有下载对象的权限也是如此。
如果客户端请求您的分配的根目录,那么您必须定义默认根对象
如果您的分配未定义默认根对象,并且请求者没有 s3:ListBucket 访问权限,则请求者会收到“访问被拒绝”错误。请求者在请求您的分配的根目录时会收到此错误,而不是“404 未找到”错误。
要定义默认根对象,请参阅 Specifying a default root object。
**注意:**允许公有 s3:ListBucket 访问不是安全最佳实践。允许公有 s3:ListBucket 访问让用户能够查看和列出存储桶中的所有对象。这会向用户公开对象元数据详细信息(例如,密钥和大小),即使用户没有下载对象的权限也是如此。
OAC 或 OAI 的权限
如果配置了 OAC,则必须在 S3 存储桶策略中包含 CloudFront 服务主体。如果配置了 OAI,则必须在 S3 存储桶策略中包含该 OAI
要验证您的存储桶策略是否允许 OAI,请在 Amazon S3 控制台中打开您的 S3 存储桶。然后,选择“权限”选项卡并查看存储桶策略。在下面的示例策略中,第一个语句是配置 OAC 时 CloudFront 服务主体的允许语句。第二个语句是 OAI 的允许语句:
{ "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": "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 控制台更新您的存储桶策略,请按照下面的步骤进行操作:
1. 打开 CloudFront 控制台并选择您的分配。
2. 选择源和源组选项卡。
3. 选择 S3 源,然后选择编辑。
4. 对于限制存储桶访问,选择是。
5. 对于源访问身份,选择现有身份或创建一个新身份。
6. 对于授予对存储桶的读取权限,选择是,更新存储桶策略。
7. 选择是,请编辑。
允许在没有 OAC 或 OAI 的情况下对分配进行公有访问
如果分配未使用 OAC 或 OAI,并且未使用 AWS 签名版本 4 请求对象,则必须允许对象的公有访问。这是因为具有 REST API 端点的分配仅支持公开可读的对象。在这种情况下,您必须确认没有对存储桶应用任何 Amazon S3 屏蔽公有访问权限设置。这些设置会覆盖允许公有读取访问的权限。Amazon S3 屏蔽公有访问权限可以应用于各个存储桶或 AWS 账户。
相关信息
相关内容
- AWS 官方已更新 3 年前
- AWS 官方已更新 1 年前
- AWS 官方已更新 24 天前
- AWS 官方已更新 2 年前