CloudFront ディストリビューションのオリジンとして S3 ウェブサイトのエンドポイントを使用しています。403 Access Denied エラーが発生するのはなぜですか?

最終更新日: 2021 年 2 月 17 日

Amazon CloudFront ディストリビューションのオリジンとして Amazon Simple Storage Service (Amazon S3) バケットを使用しています。オリジンドメイン名として S3 静的ウェブサイトエンドポイントを使用しています。CloudFront が Amazon S3 から 403 Access Denied (アクセス拒否) エラーを返すのはなぜですか?

簡単な説明

Access Denied エラーをトラブルシューティングするには、ディストリビューションのオリジンドメイン名が S3 ウェブサイトのエンドポイントか S3 REST API エンドポイントかを確認してください。エンドポイントの種類を確認するには、次の手順に従ってください。

  1. CloudFront コンソールを開きます。
  2. 対象の CloudFront ディストリビューションを選択してから、[配信設定] をクリックします。
  3. [オリジンとオリジングループ] タブを開きます。
  4. [オリジンドメイン名およびパス] の下のドメイン名を見て、ドメイン名の形式に基づきエンドポイントの種類を確認します。

REST API エンドポイントは、次のフォーマットを使用します。

DOC-EXAMPLE-BUCKET.s3.amazonaws.com

注: Amazon S3 バケットの命名規則に従ってください。

ウェブサイトエンドポイントは、以下の形式を使用します。

DOC-EXAMPLE-BUCKET.s3-website-us-east-1.amazonaws.com

注: AWS リージョンによっては、エンドポイント形式にダッシュ形式 (s3-website-Region) またはドット形式 (s3-website.Region) が使用される場合があります。

ディストリビューションが REST API エンドポイントを使用している場合は、「CloudFront ディストリビューションのオリジンとして S3 REST API エンドポイントを使用しています」をご参照ください。403 Access Denied エラーが発生するのはなぜですか?

ディストリビューションがウェブサイトのエンドポイントを使用している場合は、Access Denied エラーを回避するために次の要件を確認してください。

  • バケット内のオブジェクトは公開されている必要があります。
  • バケット内のオブジェクトは、AWS Key Management Service (AWS KMS) を使用して暗号化することはできません。
  • バケットポリシーは、s3:GetObject へのアクセスを許可する必要があります。
  • バケットポリシーがパブリック読み取りアクセスを許可する場合、バケットを所有する AWS アカウントでオブジェクトも所有している必要があります。
  • リクエストされるオブジェクトはバケットに存在している必要があります。
  • Amazon S3 ブロックパブリックアクセスをバケットで無効にする必要があります。
  • リクエスタ支払いが有効になっている場合、リクエストには request-payer パラメータを含める必要があります。
  • Referer ヘッダーを使用して CloudFront から S3 オリジンへのアクセスを制限している場合は、カスタムヘッダーを確認します。

注: S3 オブジェクトへの (匿名での) パブリックアクセスを許可しない場合は、配信のオリジンとして S3 REST API エンドポイントを使用するように設定を変更します。次に、オリジンアクセスアイデンティティ (OAI) によりアクセスを制限するように、配信と S3 バケットを設定します。手順については、「Amazon S3 でホストされている静的ウェブサイトを提供するために CloudFront をどのように使用したらよいですか?」の「 OAI によってアクセスが制限されているオリジンとして REST API エンドポイントを使用する」をご参照ください。

解決方法

バケット内のオブジェクトは公開されている必要がある

ウェブサイトのエンドポイントを使用するディストリビューションは、公開コンテンツのみをサポートしています。S3 バケット内のオブジェクトが公開されているかどうかを判断するには、ウェブブラウザでそのオブジェクトの URL を開きます。または、URL に対して curl コマンドを実行することもできます。

以下は、S3 オブジェクトの URL の例です。

http://DOC-EXAMPLE-BUCKET.s3-website-us-east-1.amazonaws.com/index.html

ウェブブラウザまたは curl コマンドが Access Denied エラーを返した場合、オブジェクトは公開されていません。

次のいずれかの方法で、オブジェクトへのパブリック読み取りアクセスを許可します。

バケット内のオブジェクトを AWS KMS で暗号化することができない

CloudFront ディストリビューションでは、AWS KMS で暗号化されたオブジェクトをサポートしていません。配信を通じ提供する S3 オブジェクトからは、KMS による暗号化を削除する必要があります。

注: AWS KMS での暗号化を使用する代わりに、AES-256 を使用してオブジェクトを暗号化できます

バケット内のオブジェクトが KMS で暗号化されているかどうかを確認するには、次のいずれかの方法を使用します。

Amazon S3 コンソールを使用してオブジェクトの暗号化設定を変更するには、S3 オブジェクトに暗号化を追加する方法を参照してください。

AWS CLI を使用してオブジェクトの暗号化設定を変更するには、まずオブジェクトのバケットにデフォルトの暗号化が設定されていないことを確認します。バケットにデフォルトの暗号化が設定されていない場合は、次のコマンドを実行してオブジェクトをそれ自体に上書きすることで、そのオブジェクトの暗号化を削除します。

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html

警告: オブジェクトを上書きコピーすると、storage-classwebsite-redirect-location の設定が削除されます。これらの設定を新しいオブジェクトで維持するには、コピーリクエストで storage-class または website-redirect-location の値を明示的に指定してください。

バケットポリシーは s3:GetObject へのアクセスを許可することが必要

S3 ウェブサイトのエンドポイントでディストリビューションを使用するには、バケットポリシーに s3:GetObject アクションへのパブリック読み取りアクセスをブロックする拒否ステートメントを含めないでください。

バケットポリシーに s3:GetObject に対する明示的な許可ステートメントがある場合でも、競合する明示的な拒否ステートメントがないことを確認してください。明示的な拒否ステートメントは常に明示的な許可ステートメントを上書きします。

s3:GetObject のバケットポリシーを確認するには、次の手順に従います。

1.    Amazon S3 コンソールから S3 バケットを開きます。

2.    [アクセス許可] タブを選択します。

3.    [バケットポリシー] を選択します。

4.    "Action": "s3:GetObject" または "Action": "s3:*" のステートメントのバケットポリシーを確認します。

次のポリシー例では、明示的なステートメントにより、s3:GetObject へのパブリックアクセスを許可しています。また、リクエストが特定の Amazon Virtual Private Cloud (Amazon VPC) からのものでない限り、明示的な拒否ステートメントにより s3:GetObject へのアクセスをブロックすることもできます。

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "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.    バケットポリシーを修正して、s3:GetObject へのパブリック読み取りアクセスをブロックするステートメントを削除または編集します。

注: CloudFront はエラーキャッシュ最小 TTL で指定された時間だけ Access Denied エラーの結果をキャッシュします。デフォルト値は 1 分です。バケットポリシーから拒否ステートメントを削除した後、配信に対して無効化を実行することで、オブジェクトをキャッシュから削除できるようになります。

バケットポリシーがパブリック読み取りアクセスを許可する場合、バケットを所有する AWS アカウントでオブジェクトも所有している必要があります

オブジェクトへのパブリック読み取りアクセスを許可するバケットポリシーの場合、バケットを所有する AWS アカウントでオブジェクトも所有する必要があります。バケットまたはオブジェクトは、そのバケットまたはオブジェクトを作成した AWS Identity and Access Management (IAM) ID のアカウントによって所有されます。

注: オブジェクト所有権の要件は、バケットポリシーによって付与されたパブリック読み取りアクセスに適用されます。オブジェクトのアクセスコントロールリスト (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.    オブジェクトの所有者のアカウントから、次のコマンドを実行して、オブジェクトに割り当てられている 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

リクエストされたオブジェクトはバケットに存在することが必要

ユーザーに s3:ListBucket のアクセス許可がない場合、ユーザーには「404 Not Found」エラーの代わりに、存在しないオブジェクトに対し、Access Denied エラーが表示されます。head-object AWS CLI コマンドを実行して、オブジェクトがバケットに存在するかどうかを確認します。

注: CloudFront に送信されたオブジェクトリクエストが S3 オブジェクト名と正確に一致することを確認してください。S3 オブジェクト名では大文字と小文字が区別されます。リクエストが正しいオブジェクト名を持っていない場合、Amazon S3 はオブジェクトが見つからないかのように応答します。CloudFront が Amazon S3 からリクエストしているオブジェクトを特定するには、サーバーアクセスログを使用します。

バケットにオブジェクトが存在する場合は、Access Denied エラーが「404 Not Found」エラーを隠すことはありません。アクセス拒否エラーを解決するには、他の設定要件を確認してください。

オブジェクトがバケット内にない場合は、アクセス拒否エラーは「404 Not Found」エラーを隠します。存在しないオブジェクトに関連する問題を解決します。

注: パブリック s3:ListBucket アクセスを有効にすることは、セキュリティ上のベストプラクティスではありません。パブリック s3:ListBucket アクセスを有効にすると、ユーザーはバケット内のすべてのオブジェクトを表示およびリスト化できます。これにより、ユーザーがオブジェクトをダウンロードするアクセス許可を持っていない場合でも、オブジェクトのメタデータの詳細 (キーやサイズなど) がユーザーに公開されます。

Amazon S3 ブロックパブリックアクセスを無効にする必要がある

バケットに Amazon S3 ブロックパブリックアクセス設定が適用されていないことを確認します。これらの設定は、パブリック読み取りアクセスを許可するアクセス権限を上書きできます。Amazon S3 ブロックパブリックアクセス設定は、個々のバケットまたは AWS アカウントに適用できます。

リクエスタ支払いが有効になっている場合、リクエストには request-payer パラメータを含めることが必要

バケットでリクエスタ支払いが有効になっている場合、バケットへの匿名アクセスは許可されません。他のアカウントのユーザーは、バケットにリクエストを送信するときに request-payer パラメータを指定する必要があります。それ以外の場合は、それらのユーザーに、Access Denied エラーが表示されます。

Referer ヘッダーを使用して CloudFront から S3 オリジンへのアクセスを制限している場合は、カスタムヘッダーを確認します

Referer ヘッダーを使用して CloudFront から S3 ウェブサイトエンドポイントオリジンへのアクセスを制限する場合は、S3 バケットポリシーに設定されたシークレット値またはトークンを確認してください。次に、シークレット値またはトークンが CloudFront オリジンのカスタムヘッダーの値と一致することを確認します。

バケットポリシーで明示的な deny ステートメントを使用している場合は、Referer ヘッダーに基づいてアクセスを許可する allow ステートメントも存在することを確認します。明示的な deny ステートメントのみを使用してアクセスを許可することはできません。

たとえば、次のバケットポリシーは、リクエストに "aws:Referer":"MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER"という文字列が含まれている場合、S3 オリジンへのアクセスを許可します。

{
  "Version":"2012-10-17",
  "Id":"http referer policy example",
  "Statement":[
    {
      "Sid":"Allow get requests originating from my CloudFront with referer header",
      "Effect":"Allow",
      "Principal":"*",
      "Action":"s3:GetObject",
      "Resource":"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
      "Condition":{
        "StringLike":{"aws:Referer":"MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER"}
      }
    }
  ]
}

このバケットポリシーの例では、CloudFront オリジンのカスタムヘッダーは次のようになります。

  • ヘッダー: Referer
  • 値: MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER

注: このバケットポリシー例では、Principal がワイルドカード値 ("Principal":"*") であるため、バケットへのパブリック (匿名) アクセス権を付与します。ただし、条件ステートメントのため、S3 オリジンへのアクセスが許可されるのは、リクエストに Referer ヘッダーが含まれ、ヘッダー値がバケットポリシーの値と一致する場合のみです。