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

最終更新日: 2019 年 7 月 30 日

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

簡単な説明

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

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

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

awsexamplebucket.s3.amazonaws.com

静的ウェブサイトエンドポイントは次のフォーマットを使用します。

awsexamplebucket.s3-website-us-east-1.amazonaws.com

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

ディストリビューションが REST API エンドポイントを使用している場合は、Access Denied エラーを回避するために、設定が以下の要件を満たしていることを確認してください。

  • オリジンアクセスアイデンティティ (OAI) を設定しない場合、オブジェクトは公開されているか、AWS 署名バージョン 4 でリクエストする必要があります。
  • AWS Key Management Service (AWS KMS) で暗号化を使用している場合、設定は KMS 暗号化オブジェクトをサポートしている必要があります。
  • S3 バケットポリシーは、s3:GetObject へのアクセスを許可する必要があります。
  • バケットポリシーがアクセスを許可する場合、S3 バケットを所有する AWS アカウントもオブジェクトを所有する必要があります。
  • リクエストされたオブジェクトは S3 バケットに存在しなければなりません。
  • クライアントがディストリビューションのルートをリクエストする場合は、デフォルトのルートオブジェクトを定義する必要があります。
  • OAI を設定した場合は、OAI を S3 バケットポリシーに含める必要があります。
  • OAI を設定しなかった場合は、Amazon S3 ブロックパブリックアクセス設定を無効にする必要があります。

解決方法

OAI を設定しない場合、オブジェクトは公開されているか、AWS 署名バージョン 4 でリクエストする必要がある

OAI を設定しない場合、REST API エンドポイントを使用するディストリビューションは、パブリックオブジェクト、または AWS 署名バージョン 4 認証でリクエストされたオブジェクトのみをサポートします。

S3 バケット内のオブジェクトが公開されているかどうかを判断するには、ウェブブラウザで S3 オブジェクトの URL を開きます。または、URL に対して curl コマンドを実行することもできます。

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

http://awsexamplebucket.s3-website-us-east-1.amazonaws.com/index.html

ウェブブラウザまたは curl コマンドが Access Denied エラーを返した場合、オブジェクトは公開されていません。オブジェクトが公開されていない場合は、以下のいずれかの設定を使用してください。

AWS KMS で暗号化を使用している場合、設定は KMS 暗号化オブジェクトをサポートしている必要がある

ディストリビューションが REST API エンドポイントと OAI を使用している場合、ディストリビューションは KMS 暗号化オブジェクトをサポートしません。ディストリビューションが REST API エンドポイントを使用しているが OAI を使用していない場合、ディストリビューションは AWS 署名バージョン 4 のリクエストに対してのみ KMS 暗号化オブジェクトをサポートします。リクエスタは、オブジェクトの暗号化に使用された KMS キーへのアクセス許可も持っている必要があります。

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

  • オブジェクトのプロパティを表示するには、Amazon S3 コンソールを使用します。[暗号化] ダイアログボックスを確認します。[AWS-KMS] が選択されている場合、オブジェクトは KMS 暗号化されています。
  • AWS コマンドラインインターフェイス (AWS CLI) を使用して head-object コマンドを実行します。コマンドが ServerSideEncryptionaws:kms として返す場合、オブジェクトは KMS 暗号化されています。

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

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

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

aws s3 cp s3://awsexamplebucket/index.html s3://awsexamplebucket/index.html

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

S3 REST API エンドポイントでディストリビューションを使用するには、バケットポリシーで s3:GetObject をパブリックユーザーまたは CloudFront の OAI のいずれかに許可する必要があります。

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

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

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

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

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

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

次のポリシー例では、CloudFront OAI に s3:GetObject へのアクセスを許可する許可ステートメントがあります。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 OAI EAF5XXXXXXXXX"
      },
      "Action": "s3:GetObject",
      "Resource": [
        "arn:aws:s3:::awsexamplebucket/*"
      ]
    },
    {
      "Sid": "Allow-Public-Access-To-Bucket",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": [
        "arn:aws:s3:::awsexamplebucket/*"
      ]
    },
    {
      "Sid": "Access-to-specific-VPCE-only",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": [
        "arn:aws:s3:::awsexamplebucket/*"
      ],
      "Condition": {
        "StringNotEquals": {
          "aws:sourceVpce": "vpce-1a2b3c4d"
        }
      }
    }
  ]
}

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

注: CloudFront は、Access Denied エラーの結果を最大 5 分間キャッシュします。バケットポリシーから拒否ステートメントを削除した後、ディストリビューションに対して無効化を実行してオブジェクトをキャッシュから削除できます。

バケットポリシーがアクセスを許可する場合、S3 バケットを所有する AWS アカウントもオブジェクトを所有する必要がある

バケットポリシーを外部のアカウントまたはサービス (パブリックアクセス、OAI など) に適用するには、バケットを所有する 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 awsexamplebucket --prefix index.html

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

注: Amazon S3 コンソールを使用してバケットとオブジェクトの所有者を確認することもできます。所有者はそれぞれのバケットまたはオブジェクトの [アクセス許可] タブにあります。

オブジェクトの所有者をバケットの所有者に変更するには、次の手順に従います。

1.    オブジェクト所有者の AWS アカウントから次のコマンドを実行して、オブジェクトに割り当てられているアクセスコントロールリスト (ACL) のアクセス許可を取得します。

aws s3api get-object-acl --bucket awsexamplebucket --key object-name

2.    オブジェクトに bucket-owner-full-control の ACL アクセス許可がある場合は、手順 3 に進みます。オブジェクトに bucket-owner-full-control の ACL アクセス許可がない場合は、オブジェクトの所有者のアカウントから次のコマンドを実行します。

aws s3api put-object-acl --bucket awsexamplebucketname --key object-name --acl bucket-owner-full-control

3.    このコマンドを実行して、オブジェクトを自分自身にコピーしてオブジェクトの所有者を変更します。

aws s3 cp s3://awsexamplebucket/index.html s3://awsexamplebucket/index.html

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

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

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

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

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

注: セキュリティ上のベストプラクティスではないため、s3:ListBucket の公開を有効にすることはお勧めしません。

クライアントがディストリビューションのルートをリクエストする場合は、デフォルトのルートオブジェクトを定義する必要がある

ディストリビューションにデフォルトのルートオブジェクトが定義されておらず、リクエスタが s3:ListBucket アクセス許可を持っていない場合、リクエスタはアクセス拒否エラーを受け取ります。ディストリビューションのルートをリクエストするとき、リクエスタは 404 Not Found エラーの代わりにこのエラーを受け取ります。

デフォルトのルートオブジェクトを定義するには、「デフォルトのルートオブジェクトの指定」を参照してください。

注: セキュリティ上のベストプラクティスではないため、s3:ListBucket の公開を有効にすることはお勧めしません。

OAI を設定した場合は、OAI を S3 バケットポリシーに含める必要がある

CloudFront ディストリビューションに OAI を追加した場合は、S3 バケットポリシーに OAI の許可ステートメントも含める必要があります。

バケットポリシーで OAI が許可されているかどうかを確認するには、Amazon S3 コンソールで S3 バケットを開きます。次に、[アクセス許可] タブを選択してバケットポリシーを確認します。以下は、OAI の許可ステートメントの例です。

{
  "Sid": "1",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::cloudfront:user/CloudFront OAI EAF5XXXXXXXXX"
  },
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::awsexamplebucket/*"
}

CloudFront コンソールを使用してバケットポリシーを更新するには、次の手順に従ってください。

  1. [CloudFront コンソール] を開き、ディストリビューションを選択します。
  2. [オリジン] タブを選択します。
  3. S3 オリジンを選択して [編集] を選択します。
  4. [バケットアクセス制限] では、[はい] を選択します。
  5. [Origin Access Identity] では、既存の ID を選択するか、新しい ID を作成します。
  6. バケットに対する読み取りアクセス許可を付与するには、[はい、バケットポリシーを更新します] を選択します。
  7. [はい、編集します] を選択します。

OAI を設定しなかった場合は、Amazon S3 ブロックパブリックアクセス設定を無効にする必要がある

ディストリビューションが OAI を使用しておらず、オブジェクトが AWS 署名バージョン 4 でリクエストされていない場合、REST API エンドポイントを持ったディストリビューションはパブリックオブジェクトのみをサポートします。つまり、バケットに Amazon S3 ブロックパブリックアクセス設定が適用されていないことを確認する必要があります。これらの設定は、パブリックアクセスを許可するアクセス許可を上書きできます。ブロックパブリックアクセス設定は、個々のバケットまたは AWS アカウントに適用できます。