CloudFront ディストリビューションのオリジンとして S3 REST API エンドポイントを使用しています。「403 Access Denied」(403 アクセス拒否) エラーが発生するのはなぜですか?
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 ディストリビューションを選択します。その後、[Distribution Settings] (ディストリビューション設定) を選択します。
3. [オリジンとオリジングループ] タブを開きます。
4. [Origin Domain Name and Path] (オリジンドメイン名およびパス) の下のドメイン名を確認します。次に、ドメイン名の形式に基づいてエンドポイントタイプを決定します。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 REST API エンドポイントを使用しています。403 Access Denied エラーが発生するのはなぜですか?」を参照してください。
ディストリビューションが REST API エンドポイントを使用している場合は、Access Denied エラーを回避するために、設定が以下の要件を満たしていることを確認してください。
- オリジンアクセスコントロール (OAC) またはオリジンアクセスアイデンティティ (OAI) のいずれも設定しない場合、オブジェクトはパブリックにアクセス可能である必要があります。または、AWS 署名バージョン 4 を使用してオブジェクトをリクエストする必要があります。
- AWS Key Management Service (AWS KMS) によって暗号化されたオブジェクトが S3 バケットに含まれている場合は、OAI ではなく OAC を使用する必要があります。
- S3 バケットポリシーは s3:GetObject へのアクセスを許可する必要があります。
- バケットポリシーがアクセスを付与する場合、S3 バケットを所有する AWS アカウントはオブジェクトも所有する必要があります。
- リクエストされるオブジェクトは、対応する S3 バケット内に置く必要があります。
- クライアントが配信のルートをリクエストする場合は、デフォルトのルートオブジェクトを定義しておく必要があります。
- OAI を設定している場合、その OAI を S3 バケットポリシーに含める必要があります。
- OAC を設定している場合、CloudFront サービスプリンシパルを S3 バケットポリシーに含める必要があります。OAI を設定している場合、その OAI を S3 バケットポリシーに含める必要があります。
- OAI を設定していない場合、バケットで Amazon S3 パブリックアクセスブロックを無効にする必要があります。
解決方法
OAC と OAI のいずれも設定していない場合、オブジェクトはパブリックにアクセス可能であるか、AWS Signature Version 4 でリクエストする必要があります。
S3 バケット内のオブジェクトがパブリックにアクセス可能であるかどうかを判断するには、ウェブブラウザで S3 オブジェクトの URL を開きます。または、URL で curl コマンドを実行します。
以下は、S3 オブジェクトの URL の例です。
https://DOC-EXAMPLE-BUCKET.s3.amazonaws.com/index.html
ウェブブラウザまたは curl コマンドが Access Denied エラーを返した場合、そのオブジェクトはパブリックにアクセス可能ではありません。オブジェクトがパブリックにアクセス可能でない場合は、以下のいずれかの設定を行ってください。
- バケット内のすべてのオブジェクトに対してパブリック読み取りアクセスを許可するバケットポリシーを作成します。
- Amazon S3 コンソールを使用してオブジェクトに対するパブリック読み取りアクセスを許可します。
- REST API エンドポイントを使用するディストリビューションに OAC or OAI を設定します。
- AWS Signature Version 4 を使用して Amazon S3 へのリクエストを認証します。
AWS Key Management Service(AWS SSE-KMS)で暗号化されたオブジェクト
AWS Key Management Service (AWS SSE-KMS) によって暗号化されたオブジェクトが S3 バケットに含まれている場合は、OAI ではなく OAC を使用する必要があります。
AWS KMS で暗号化されたオブジェクトは、OAC を設定することで CloudFront で提供できます。これを行うには、CloudFront サービスプリンシパルにキーを使用するアクセス許可を付与する AWS KMS キーにポリシーステートメントを追加します。OAC を設定せずに暗号化されたオブジェクトを AWS KMS で提供するには、Lambda@Edge を使用して、暗号化された AWS KMS キーを S3 バケットから提供します。
バケット内のオブジェクトが AWS KMS で暗号化されているかどうかを確認するには、次のいずれかの方法を使用します。
- Amazon S3 コンソールを使用してオブジェクトのプロパティを表示します。暗号化ダイアログボックスを確認します。AWS KMS が選択されている場合、オブジェクトは AWS KMS で暗号化されています。
- AWS コマンドラインインターフェイス (AWS CLI) を使用して head-object コマンドを実行します。コマンドが aws:kms として ServerSideEncryption を返す場合、オブジェクトは AWS KMS で暗号化されています。AWS CLI コマンドの実行時にエラーが発生した場合は、使用している AWS CLI を最新のバージョンにしてください。注: OAI は AWS KMS で暗号化されたオブジェクトの提供をサポートしていません。
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 OAC に s3:GetObject へのアクセスを許可する許可ステートメントが含まれています。また、CloudFront OAI に s3:GetObject へのアクセスを付与するステートメントと、s3:GetObject へのパブリックアクセスを付与する許可ステートメントも含まれています。ただし、リクエストが特定の Amazon Virtual Private Cloud (Amazon VPC) からのものでない限り、s3:GetObject へのアクセスをブロックする明示的な拒否ステートメントがあります。
{ "Version": "2008-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. バケットポリシーを変更して、s3:GetObject への CloudFront OAI アクセスまたはパブリックアクセスをブロックするステートメントを削除または編集します。
注意: CloudFront は、Access Denied エラーの結果を最大 5 分間キャッシュします。バケットポリシーから拒否ステートメントを削除した後、ディストリビューションに対して無効化を実行してオブジェクトをキャッシュから削除できます。
S3 バケットとオブジェクトの所有権
外部のアカウントやサービスに適用されるバケットポリシーでは、バケットを所有する 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. オブジェクトの所有者の AWS アカウントで、このコマンドを実行して、オブジェクトに割り当てられているアクセスコントロールリスト (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 --storage-class STANDARD
注: サンプルコマンドの --storage-class 値を実際のユースケースに適用可能なストレージクラスに変更してください。
リクエストされたオブジェクトはバケット内に存在することが必要
ユーザーに 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 アクセスを許可すると、ユーザーはバケット内のすべてのオブジェクトを表示および一覧表示できます。これにより、ユーザーがオブジェクトをダウンロードする許可を持っていない場合でも、オブジェクトのメタデータの詳細 (キーやサイズなど) がユーザーに公開されます。
クライアントがディストリビューションのルートをリクエストする場合は、デフォルトのルートオブジェクトを定義しておく必要があります。
ディストリビューションにデフォルトのルートオブジェクトが定義されておらず、リクエスタが s3:ListBucket アクセス許可を持っていない場合、リクエスタはアクセス拒否エラーを受け取ります。ディストリビューションのルートをリクエストするとき、リクエスタは 404 Not Found エラーの代わりにこのエラーを受け取ります。
デフォルトのルートオブジェクトの定義方法については、「Specifying a default root object」(デフォルトのルートオブジェクトの指定) を参照してください。
注: パブリック 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. [Origin Access Identity] (オリジンアクセスアイデンティティ) で、既存のアイデンティティを選択するか、新規に作成します。
6. [バケットに対する読み取りアクセス許可を付与する] で、[はい、バケットポリシーを更新します] を選択します。
7. [Yes, Edit] (はい、編集します) を選択します。
OAC や OAI なしでのディストリビューションへのパブリックアクセスを許可する
ディストリビューションで OAC や OAI が使用されておらず、オブジェクトが AWS Signature Version 4 でリクエストされない場合は、オブジェクトへのパブリックアクセスを許可する必要があります。これは、REST API エンドポイントを含むディストリビューションがパブリックに読み取り可能なオブジェクトのみをサポートしているためです。この場合、バケットに Amazon S3 パブリックアクセスブロックが適用されていないことを確認する必要があります。これらの設定は、パブリック読み取りアクセスを可能にする許可を上書きします。Amazon S3 パブリックアクセスブロック設定は、個々のバケットまたは AWS アカウントに適用できます。
関連情報

関連するコンテンツ
- 質問済み 5日前lg...
- 質問済み 3年前lg...
- 質問済み 5年前lg...
- 質問済み 7ヶ月前lg...