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

最終更新日: 2022 年 10 月 12 日

Amazon CloudFront ディストリビューションのオリジンとして Amazon Simple Storage Service (Amazon S3) バケットを使用しています。403 Access Denied (403 アクセス拒否) エラーをトラブルシューティングする方法を教えてください。

簡単な説明

Access Denied エラーをトラブルシューティングするには、まずディストリビューションのオリジンドメイン名が S3 ウェブサイトのエンドポイントか S3 REST API エンドポイントかを確認します。次に、ディストリビューションがウェブサイトエンドポイントを使用している場合は、トラブルシューティングのセクションを確認します。

解決方法

ディストリビューションオリジンドメイン名のエンドポイントタイプを決定する

1.    CloudFront コンソールを開きます。

2.    CloudFront ディストリビューションを選択します。その後、[Distribution Settings] (ディストリビューション設定) を選択します。

3.    [オリジンとオリジングループ] タブを開きます。

4.    [Origin Domain Name and Path] (オリジンドメイン名およびパス) の下のドメイン名を確認します。次に、以下のように、ドメイン名の形式に基づいてエンドポイントタイプを決定します。

REST API エンドポイントは次の形式を使用します。

DOC-EXAMPLE-BUCKET.s3.amazonaws.com

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

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) を使用して暗号化されていないことを確認します

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

オブジェクトが AWS KMS で暗号化されているかどうかを判断する

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

Amazon S3コンソールを使用してオブジェクトのプロパティを表示します[Encryption] (暗号化) ダイアログボックスを確認します。[AWS-KMS] が選択されている場合、オブジェクトは AWS KMS 暗号化されています。

-または-

AWS コマンドラインインターフェイス (AWS CLI) を使用して head-object コマンドを実行します。コマンドが ServerSideEncryptionaws:kms として返す場合、オブジェクトは AWS KMS 暗号化されています。

注: AWS CLI コマンドの実行中にエラーが発生した場合は、AWS CLI の最新バージョンを使用していることを確認してください

オブジェクトの暗号化設定を変更する

Amazon S3 コンソールを使用してオブジェクトの暗号化設定を変更するには、「AWS KMS (SSE-KMS) によるサーバー側の暗号化の指定」を参照してください。

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

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

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

s3:GetObject アクションのバケットポリシーに明示的な「拒否」がないことを確認する

バケットポリシーには、s3:GetObject アクションへのパブリック読み取りアクセスをブロックする拒否ステートメントがあってはなりません。

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

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

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

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

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

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

5.    バケットポリシーを変更して、s3:GetObject へのパブリック読み取りアクセスをブロックするステートメントを削除または編集します。

例えば、次のポリシーでは、明示的なステートメントにより、s3:GetObject へのパブリックアクセスを許可しています。ただし、リクエストが特定の Amazon Virtual Private Cloud (Amazon VPC) からのものでない限り、s3:GetObject アクセスに対する明示的な拒否ステートメントも含まれています。このポリシーは、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"
        }
      }
    }
  ]
}

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

オブジェクトへのパブリック読み取りアクセスを許可するバケットポリシーの場合、バケットを所有する AWS アカウントでオブジェクトも所有する必要があります。デフォルトのオブジェクト所有権設定を持つ既存の Amazon S3 バケットの場合、オブジェクト所有者は、オブジェクトをバケットにアップロードした AWS Identity and Access Management (IAM) アイデンティティの AWS アカウントです。

: オブジェクト所有権の要件は、バケットポリシーによって付与されたパブリック読み取りアクセスに適用されます。オブジェクトのアクセスコントロールリスト (ACL) によって許可されたパブリック読み取りアクセスには適用されません。

バケットとオブジェクトの所有者が同じであることを確認する

バケットとオブジェクトの所有者が同じかどうかを確認するには、次の手順に従います。Amazon S3 コンソールを使用してバケットとオブジェクトの所有者を確認することもできます。所有者は、それぞれのバケットまたはオブジェクトの [Permissions] (許可) タブで確認できます。

1.    バケット所有者の S3 正規 ID を取得するには、次の AWS CLI コマンドを実行します。

aws s3api list-buckets --query Owner.ID

2.    オブジェクト所有者の S3 正規 ID を取得するには、次のコマンドを実行します。

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

この例は単一のオブジェクトを示していますが、list コマンドを使用して複数のオブジェクトを確認することができます。

3.    正規 ID が一致しない場合、バケットとオブジェクトの所有者が異なります。

オブジェクトの所有権をアップデートする

バケット所有者は、S3 オブジェクト所有権を使用してオブジェクトの所有権を管理できます。すべての新しい S3 バケットでは、bucket owner enforced 設定がデフォルトでオンになっています。既存のバケットを更新するには、「既存のバケットでのオブジェクト所有権の設定」を参照してください。bucket owner enforced がオンになっている場合、バケット所有者がバケット内のすべてのオブジェクトのオブジェクト所有者です。また、bucket owner enforced 設定をオンにすると、バケットとそのオブジェクトの ACL はすべて非アクティブ化されます。

バケット所有者は、すべてのバケットに bucket owner enforced 設定を使用し、IAM およびバケットポリシーを介してアクセス許可を管理することをお勧めします。

バケットの ACL を削除し、バケット内のすべてのオブジェクトの所有権を取得するには、次のコマンドを実行します。

aws s3api put-bucket-ownership-controls --bucket example-bucket --ownership-controls 'Rules=[{ObjectOwnership=BucketOwnerEnforced}]'

S3 バケットで ACL をオフにしたくない場合は、次のステップに従ってオブジェクトの所有者をバケット所有者に変更することもできます。

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 アクセス許可がない場合は、オブジェクトの所有者のアカウントから次のコマンドを実行します。DOC-EXAMPLE-BUCKET をバケットの名前に置き換えます。

aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name --acl bucket-owner-full-control

3.    次のコマンドをバケット所有者のアカウントから実行して、オブジェクトをそれ自体に上書きコピーし、そのオブジェクトの所有者を変更します。次のように、DOC-EXAMPLE-BUCKET をバケットの名前に置き換えます。

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

リクエストされたオブジェクトがバケットに存在することを確認する

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

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

デフォルトのルートオブジェクトに関するエラーが表示された場合は、オブジェクト名に余分な文字が含まれていないことを確認してください。例えば、index.html/index.html ではなく、[Default Root Object] (デフォルトルートオブジェクト) フィールドに入力する必要があります。詳細については、「デフォルトのルートオブジェクトを指定する方法」を参照してください。

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

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

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

バケットの Amazon S3 ブロックパブリックアクセスがオフになっていることを確認する

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

バケット内のオブジェクトが公開されていることを確認する

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

例:

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

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

パブリック読み取りアクセスを許可するには、次の手順を実行します。

バケット内のすべてのオブジェクトに対してパブリック読み取りアクセスを許可するバケットポリシーを作成する。

- または -

Amazon S3 コンソールを使用してオブジェクトに対するパブリック読み取りアクセスを許可する。

[Requester Pays] (リクエスタ支払い) がオンになっている場合、リクエストに request-payer パラメータが含まれていることを確認する

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

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

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

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

例えば、次のバケットポリシーは、リクエストに "aws:Referer":"MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER"という文字列が含まれている場合、S3 オリジンへのアクセスを許可します。
CloudFront オリジンカスタムヘッダーは次のようにする必要があります。

  • ヘッダー: Referer
  • : MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER
{
  "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"}
      }
    }
  ]
}

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

組織の管理アカウントによって明示的な「拒否」サービスコントロールポリシー (SCP) がアタッチされていないことを確認する

サービスコントロールポリシー (SCP) は、組織内のアクセス許可を管理するために使用できる組織ポリシーの一種です。AWS Organizations で組織の管理アカウントを使用して、組織のルート、組織単位 (OU)、または AWS アカウントに直接アタッチされている (s3:GetObject アクション用の) 拒否ポリシーがあるかどうかを確認します。