ドメインから S3 バケットへのアクセスが拒否されました

ドメインから S3 バケットへのアクセスが拒否されました

こんにちは、私のドメインでAccessDeniedを受信しました。

自分のサイトを AWS S3 バケットにアップロードし、公開して静的ページを作成しましたが、domain.com/mypage 経由でアクセスすると、AccessDenied が発生します。

aws からは、mydomain.s3.amazonaws.com/mypage は正常に動作します。

私のドメインDNSはこのように設定されています

;; ANSWER SECTION:
mydomain.com. 2101 IN CNAME mydomain.s3.amazonaws.com.
mydomain.s3.amazonaws.com. 41342 IN CNAME s3-1-w.amazonaws.com.
s3-1-w.amazonaws.com.   219 IN  CNAME   s3-w.us-east-1.amazonaws.com.
s3-w.us-east-1.amazonaws.com. 3 IN  A   52.217.69.36

これを解決するためのアドバイスはありますか?

答え1

これはAmazonのサポートドキュメントより:

簡単な説明:

アクセス拒否エラーのトラブルシューティングを行うには、ディストリビューションのオリジンドメイン名が 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 アクセス拒否エラーが発生するのはなぜですか?

ディストリビューションで Web サイトのエンドポイントを使用している場合は、アクセス拒否エラーを回避するために次の要件を確認してください。

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

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

解決

バケット内のオブジェクトはパブリックにアクセス可能である必要があります

ウェブサイトエンドポイントを使用するディストリビューションは、パブリックにアクセス可能なコンテンツのみをサポートします。S3 バケット内のオブジェクトがパブリックにアクセス可能かどうかを確認するには、Web ブラウザでオブジェクトの URL を開きます。または、URL に対して curl コマンドを実行することもできます。

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

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

Web ブラウザまたは curl コマンドがアクセス拒否エラーを返す場合、オブジェクトはパブリックにアクセスできません。

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

  1. バケット内のすべてのオブジェクトに対するパブリック読み取りアクセスを許可するバケット ポリシーを作成します。
  2. Amazon S3 コンソールを使用して、オブジェクトへのパブリック読み取りアクセスを許可します。
  3. バケット内のオブジェクトはAWS KMSで暗号化できません
  4. CloudFront ディストリビューションは、AWS KMS で暗号化されたオブジェクトをサポートしていません。ディストリビューションを使用して提供する S3 オブジェクトから KMS 暗号化を削除する必要があります。

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

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

Amazon S3 コンソールを使用して、オブジェクトのプロパティを表示します。[暗号化] ダイアログボックスを確認します。AWS-KMS が選択されている場合、オブジェクトは KMS で暗号化されています。AWS コマンドラインインターフェイス (AWS CLI) を使用して、head-object コマンドを実行します。コマンドが ServerSideEncryption を aws:kms として返す場合、オブジェクトは KMS で暗号化されています。注: AWS CLI コマンドの実行時にエラーが発生した場合は、最新バージョンの AWS CLI を使用していることを確認してください。Amazon S3 コンソールを使用してオブジェクトの暗号化設定を変更するには、「S3 オブジェクトに暗号化を追加するにはどうすればよいですか?」を参照してください。

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

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

警告: オブジェクトをコピーすると、ストレージ クラスと
website-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"
                }
            }
        }
    ]
  }
  1. バケット ポリシーを変更して、s3:GetObject へのパブリック読み取りアクセスをブロックするステートメントを削除または編集します。

注記: CloudFront は、エラー キャッシュの最小 TTL で指定された時間、アクセス拒否エラーの結果をキャッシュします。デフォルト値は 1 分です。バケット ポリシーから拒否ステートメントを削除した後、ディストリビューションで無効化を実行して、キャッシュからオブジェクトを削除できます。

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

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

バケットとオブジェクトの所有者が同じかどうかを確認するには、次の手順に従います。

  1. バケット所有者の S3 正規 ID を取得するには、次の AWS CLI コマンドを実行します。
aws s3api list-buckets --query Owner.ID
  1. このコマンドを実行して、オブジェクト所有者の S3 正規 ID を取得します。

注: この例では 1 つのオブジェクトを示していますが、list コマンドを使用して複数のオブジェクトをチェックすることもできます。

aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html
  1. 正規 ID が一致しない場合は、バケットとオブジェクトの所有者が異なります。

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

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

  1. オブジェクト所有者のアカウントから次のコマンドを実行して、オブジェクトに割り当てられている ACL 権限を取得します。
aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name
  1. オブジェクトにバケット所有者フルコントロール ACL 権限がある場合は、手順 3 に進みます。オブジェクトにバケット所有者フルコントロール ACL 権限がない場合は、オブジェクト所有者のアカウントから次のコマンドを実行します。
aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name --acl bucket-owner-full-control
  1. バケット所有者のアカウントから次のコマンドを実行し、オブジェクトをそれ自体にコピーしてオブジェクトの所有者を変更します。
aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html

要求されたオブジェクトはバケット内に存在する必要がありますユーザーに s3:ListBucket 権限がない場合、404 Not Found エラーではなく、見つからないオブジェクトに対するアクセス拒否エラーが表示されます。head-object AWS CLI コマンドを実行して、バケット内にオブジェクトが存在するかどうかを確認します。

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

オブジェクトがバケット内に存在する場合、アクセス拒否エラーは発生しません。 404 Not Found エラーをマスクするアクセス拒否エラーを解決するには、その他の構成要件を確認してください。

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

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

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

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

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

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

例えば次のバケットポリシーは、リクエストに文字列が含まれている場合にS3オリジンへのアクセスを許可します。 "aws: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"}
      }
    }
  ]
}

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

  • ヘッダ: リファラー
  • 価値:MY_SECRET_TOKEN_CONFIGURED_ON_CLOUDFRONT_ORIGIN_CUSTOM_HEADER

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

関連情報