跳至内容

为什么我在使用 S3 REST API 端点作为 CloudFront 分配的源时收到“403 Access Denied”错误?

4 分钟阅读
0

我想解决 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”错误,则对象不可公开访问。

要将对象设为可公开访问,请执行以下操作之一:

对 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 且不允许显式拒绝语句,请完成以下步骤:

  1. 打开 Amazon S3 控制台

  2. 选择您的存储桶。

  3. 选择 Permissions(权限)选项卡。

  4. 选择 Bucket policy(存储桶策略)。

  5. 检查带有 "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"  
            }  
          }  
        }  
      ]  
    }
  6. 修改存储桶策略以删除或编辑阻止 CloudFront OAI、CloudFront OAC 访问或公开访问 s3:GetObject 的语句。

注意:CloudFront 会将“Access Denied”错误的结果缓存长达 5 分钟。从存储桶策略中删除拒绝语句后,您可以在您的分配上运行失效操作,以从缓存中删除对象。

授予 S3 存储桶和对象的所有权

创建存储桶或对象的 AWS Identity and Access Management (IAM) 身份账户拥有该存储桶或对象。

**注意:**对象所有权要求仅适用于存储桶策略授予的访问权限。不适用于对象的访问控制列表 (ACL) 授予的访问权限。

要检查存储桶和对象的拥有者是否相同,请完成以下步骤:

  1. 运行 list-buckets 命令获取存储桶所有者的 S3 规范 ID:

    aws s3api list-buckets --query Owner.ID
  2. 运行 list-objects 命令获取对象所有者的 S3 规范 ID:

    aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html

    **注意:**上述示例命令的输出显示一个对象,但您可以使用 list-objects 命令检查多个对象。

如果规范 ID 不匹配,则表示存储桶和对象的所有者不同。

**注意:**您还可以使用 Amazon S3 控制台来检查存储桶和对象所有者。您可以在存储桶或对象的 Permissions(权限)选项卡上找到所有者。

要将对象的所有者更改为存储桶所有者,请完成以下步骤:

  1. 在对象所有者的账户中,运行 get-object-acl 命令来检索 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 权限,则从对象所有者的账户运行 put-object-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 替换为您的存储类。

将对象移至存储桶

要检查存储桶中是否存在该对象,请运行 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 控制台上更新您的存储桶策略,请完成以下步骤:

  1. 打开 CloudFront 控制台
  2. 选择您的分配。
  3. 选择 Origins and Origin Groups(源和源组)选项卡。
  4. 选择 S3 来源,然后选择 Edit(编辑)。
  5. 对于 Restrict Bucket Access(限制存储桶访问),选择 Yes(是)。
  6. 对于 Origin Access Identity(来源访问身份),选择现有身份或创建一个新身份。
  7. 对于 Grant read permissions on bucket(授予对存储桶的读取权限),选择 Yes, update bucket policy(是,更新存储桶策略)。
  8. 选择 Yes, edit(是,请编辑)。

相关信息

Troubleshooting error response status codes in CloudFront(对 CloudFront 中的错误响应状态代码进行故障排除)

如何对来自 Amazon S3 的“403 Access Denied”错误进行故障排除?

为什么我在使用 Amazon S3 网站端点作为 CloudFront 分配的源时收到“403 access denied”错误?