CloudFront ディストリビューションのオリジンとして S3 REST API エンドポイントを使用しています。403 アクセス拒否エラーが表示されるのはなぜですか?
私は Amazon CloudFront ディストリビューションのオリジンとして Amazon Simple Storage Service (Amazon S3) バケットを使用しています。私は S3 REST API エンドポイントをオリジンドメイン名として使用しています。CloudFront は Amazon S3 から 403 アクセス拒否エラーを返しています。
簡単な説明
Access Denied エラーのトラブルシューティングを行うには、ディストリビューションのオリジンドメイン名が 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 Access Denied エラーが表示されることがあります。詳細については、「CloudFront ディストリビューションのオリジンとして S3 ウェブサイトエンドポイントを使用しています」を参照してください。403 アクセス拒否エラーが表示されるのはなぜですか?
ディストリビューションが REST API エンドポイントを使用している場合は、アクセル拒否エラーを回避するために、構成が次の要件を満たしていることを確認します。
- オリジンアクセス制御 (OAC) またはオリジンアクセスアイデンティティ (OAI) のいずれも設定しない場合、オブジェクトはパブリックにアクセスできる必要があります。または、AWS 署名バージョン 4 でオブジェクトをリクエストする必要があります。
- S3 バケットに AWS キー管理サービス (AWS KMS) で暗号化されたオブジェクトが含まれている場合は、OAI の代わりに OAC を使用する必要があります。
- S3 バケットポリシーでは s3:GetObject へのアクセスを許可する必要があります。
- バケットポリシーでアクセスが許可される場合、S3 バケットを所有する AWS アカウントもオブジェクトを所有する必要があります。
- リクエストされたオブジェクトは S3 バケットに存在する必要があります。
- クライアントがディストリビューションのルートを要求する場合は、デフォルトのルートオブジェクトを定義する必要があります。
- OAI を設定した場合は、その OAI を S3 バケットポリシーに含める必要があります。
- OAC を設定した場合は、CloudFront サービスプリンシパルを S3 バケットポリシーに含める必要があります。OAI を設定した場合は、その OAI を S3 バケットポリシーに含める必要があります。
- OAC も OAI も設定しない場合は、バケットの Amazon S3 ブロックパブリックアクセスをオフにする必要があります。
解決策
OAC と OAI のいずれも設定しない場合、オブジェクトはパブリックにアクセス可能であるか、AWS 署名バージョン 4 でリクエストする必要があります。
S3 バケット内のオブジェクトがパブリックにアクセスできるかどうかを確認するには、S3 オブジェクトの URL をウェブブラウザで開きます。または、URL で curl コマンドを実行します。
S3 オブジェクトの URL の例を次に示します。
https://DOC-EXAMPLE-BUCKET.s3.amazonaws.com/index.html
Web ブラウザまたは curl コマンドで Access Denied エラーが返る場合、そのオブジェクトはパブリックにアクセスできません。オブジェクトがパブリックにアクセスできない場合は、次のいずれかの構成を使用してください。
- バケット内のすべてのオブジェクトにパブリック読み取りアクセスを許可するバケットポリシーを作成します。
- Amazon S3 コンソールを使用して、オブジェクトへのパブリック読み取りアクセスを許可します。
- REST API エンドポイントを使用して、ディストリビューションの OAC または OAI のいずれかを設定します。
- AWS 署名バージョン 4 を使用して Amazon S3 へのリクエストを認証します。
AWS キー管理サービス (AWS SSE-KMS) によって暗号化されたオブジェクト
s3 バケットに AWS キー管理サービス (AWS SSE-KMS) によって暗号化されたオブジェクトが含まれている場合は、OAI の代わりに OAC を使用する必要があります。
AWS KMS で暗号化されたオブジェクトは、OAC を設定することで CloudFront で提供できます。これを行うには、CloudFront サービスプリンシパルにキーの使用権限を付与するステートメントを AWS KMS キーポリシーに追加します。OAC を設定せずに AWS KMS で暗号化されたオブジェクトを提供するには、Lambda @Edge を使用して S3 バケットから暗号化された AWS KMS キーを提供します。
バケット内のオブジェクトが AWS KMS で暗号化されているかどうかは、次のいずれかの方法で確認します。
- Amazon S3 コンソールを使用してオブジェクトのプロパティを表示します。[暗号化] ダイアログボックスを確認します。AWS KMS を選択すると、オブジェクトは AWS KMS で暗号化されます。
- AWS コマンドラインインターフェイス (AWS CLI) を使用して head-object コマンドを実行します。コマンドで ServerSideEncryption が aws:kms として返る場合、オブジェクトは 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 へのパブリックアクセスを許可する許可ステートメントも含まれています。ただし、リクエストが特定の Amazon 仮想プライベートクラウド (Amazon VPC) からのものでない限り、アクセスをブロックする明示的な拒否ステートメントが s3:GetObject にはあります。
{ "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 は、アクセス拒否エラーの結果を最長 5 分間キャッシュします。バケットポリシーから拒否ステートメントを削除したら、ディストリビューションで無効化を実行してオブジェクトをキャッシュから削除できます。
S3 バケットとオブジェクトの所有権
バケットポリシーを外部アカウントまたはサービスに適用するには、バケットを所有する AWS アカウントがオブジェクトも所有している必要があります。バケットまたはオブジェクトは、バケットまたはオブジェクトを作成した AWS ID とアクセス管理 (IAM) ID のアカウントが所有します。
注: オブジェクト所有権の要件は、バケットポリシーで許可されるアクセスに適用されます。オブジェクトのアクセスコントロールリスト (ACL) によって許可されたアクセスには適用されません。
以下の手順に従って、バケットとオブジェクトの所有者が同じかどうかを確認してください。
1. 次の AWS CLI コマンドを実行して、バケット所有者の S3 正規 ID を取得します。
aws s3api list-buckets --query Owner.ID
2. 次のコマンドを実行して、オブジェクト所有者の S3 正規 ID を取得します。
注: この例ではオブジェクトは 1 つですが、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. オブジェクトにバケット所有者フルコントロール ACL 権限がある場合は、ステップ #3 に進んでください。オブジェクトにバケット所有者フルコントロール 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 見つかりません」エラーの代わりにこのエラーが表示されます。
デフォルトルートオブジェクトを定義するには、「デフォルトルートオブジェクトの指定」を参照してください。
注: パブリック s3:ListBucket アクセスを許可することは、セキュリティ上のベストプラクティスではありません。s3:ListBucket へのパブリックアクセスを許可すると、ユーザーはバケット内のすべてのオブジェクトを表示して一覧表示できます。これにより、ユーザーがオブジェクトをダウンロードする権限を持っていなくても、キーやサイズなどのオブジェクトメタデータの詳細がユーザーに公開されます。
OAC または OAI の権限
OAC を設定した場合は、CloudFront サービスプリンシパルを S3 バケットポリシーに含める必要があります。OAI を設定した場合は、その OAI を s3 バケットポリシーに含める必要があります。
バケットポリシーで OAI が許可されているかどうかを確認するには、Amazon S3 コンソールで S3 バケットを開きます。次に、[権限] タブを選択し、バケットポリシーを確認します。以下のポリシー例では、最初のステートメントは、OAC が設定されている場合の CloudFront サービスプリンシパルの許可ステートメントです。2 番目のステートメントは 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 Signature Version 4 でリクエストされていない場合は、オブジェクトへのパブリックアクセスを許可する必要があります。これは、REST API エンドポイントを含むディストリビューションでサポートされているのは、パブリックに読み取り可能なオブジェクトのみのためです。この場合、バケットに Amazon S3 ブロックパブリックアクセス設定が適用されていないことを確認する必要があります。これらの設定は、パブリック読み取りアクセスを許可するアクセス権限をオーバーライドできます。Amazon S3 ブロックパブリックアクセス設定は個々のバケットまたは AWS アカウントに適用できます。
関連情報
関連するコンテンツ
- 質問済み 6年前lg...
- 質問済み 1ヶ月前lg...
- 質問済み 5ヶ月前lg...
- AWS公式更新しました 9ヶ月前
- AWS公式更新しました 2年前