S3静的ウェブサイトホスティングを2026年でも使い続けるため、セキュアに最適化してみた

S3静的ウェブサイトホスティングを2026年でも使い続けるため、セキュアに最適化してみた

S3ウェブサイトエンドポイントのOAC非対応やHTTP専用といった制約をCloudFrontとの組み合わせで補い、月額数ドルの配信コストでインデックスドキュメントやリダイレクトルールを活かし続ける構成と、GuardDuty・Cost Anomaly Detectionなどによる監視体制を整理しました。
2026.06.02

はじめに

本記事は2019年に公開した記事の改訂版にあたります。主な変更点は以下の通りです。

項目 2019年版 2026年版(本記事)
S3直接アクセス対策 Refererヘッダー制限 カスタムオリジンヘッダー条件
監視 なし GuardDuty + SecurityHub
通知 なし CloudTrail → EventBridge → Chatbot
コスト監視 なし Cost Anomaly Detection + Billing Alarm
アクセス制御 IAMユーザー + アクセスキー IAMロール + MFA必須

7年間でOACの登場、SecurityHub・EventBridge・Chatbotの成熟など周辺環境が大きく変化したため、2026年時点の実践構成として書き直しました。

https://dev.classmethod.jp/articles/cloudfront-with-s3-hosting/

2026年6月時点、S3静的ウェブサイトホスティングの設定画面を開くと、以下のメッセージが表示されます。

S3静的ウェブサイトホスティングの設定画面に表示されるAmplify推奨メッセージ

一方で、以下のようなケースではS3ウェブサイトエンドポイントに合理性があります。

  • ビルドやデプロイのパイプラインが不要で、ファイルを置くだけで公開したい
  • セミナー資料やPDFを期間限定で配布したい
  • S3のインデックスドキュメント・リダイレクトルール・ルーティングルールを活用したい
  • ファイル数が多く、Amplifyのビルド・デプロイに時間がかかりすぎる
  • 月額数ドルで運用中で、移行コストもかけられない

配信方式の比較

S3で静的コンテンツを配信する構成は大きく3パターンに分かれます。

方式 構成 適するケース
Amplify Hosting Amplifyコンソール / CLI CI/CD連携、フレームワークビルド、プレビュー環境が欲しい
CloudFront + S3オリジン + OAC S3バケットを非公開のままCloudFront経由に限定 S3への直接アクセスを完全に遮断したい場合。新規構築向け
CloudFront + S3ウェブサイトエンドポイント S3のindex document/redirect rules/routing rulesを活用 既存のS3ルーティング資産を活かしたい。本記事の対象

新規構築であれば、S3オリジン + OACのベストプラクティス構成を推奨します。

本記事は、S3ウェブサイトホスティングのインデックスドキュメントやリダイレクトルールを活用しており、CloudFront Functionsへの移植コストも合わない環境で実施している施策を紹介します。

S3ウェブサイトエンドポイント固有の制約

このエンドポイントには以下のセキュリティ制約があります。

制約 理由
ブロックパブリックアクセスを完全に有効化できない バケットポリシーでの公開が必要
OACが使えない OAC非対応。直接アクセスを完全に遮断できない
CloudFront → S3間のHTTPS通信ができない HTTP専用
SSE-KMSが使えない SSE-KMS非対応

これらの制約をどう補い、実用的かつ低コストに運用するかが本記事のテーマです。

アーキテクチャ

S3ウェブサイトエンドポイント + CloudFront構成図

閲覧者 → CloudFront (HTTPS) → S3ウェブサイトエンドポイント (HTTP)
                                  ├── インデックスドキュメント
                                  ├── リダイレクトルール
                                  └── ルーティングルール

CloudFrontをフロントに配置し、S3ウェブサイトエンドポイントをカスタムオリジン(HTTP-only)として設定しています。閲覧者 → CloudFront間はHTTPS、CloudFront → S3間はHTTP通信です。

セキュリティ: 制約への対策

静的ホスティング専用のAWSアカウントを用意しています。アカウント単位のブロックパブリックアクセスの必要性や、オペミスのリスクを抑制しました。

ブロックパブリックアクセスの部分的適用

S3のブロックパブリックアクセスは、バケットの意図しない公開を防ぐための4つの設定です。しかしウェブサイトエンドポイントではバケットポリシーによる公開が必要なため、アカウントレベルでの BlockPublicPolicyRestrictPublicBuckets の有効化ができません。代わりに有効化できる2項目をアカウントレベルで設定しました。

設定 効果
BlockPublicAcls true ACLによる公開を防止
IgnorePublicAcls true 既存のパブリックACLを無視
BlockPublicPolicy false バケットポリシーによる公開を許可(ウェブサイトエンドポイントに必要)
RestrictPublicBuckets false 同上

非公開バケット(ログ等)では、バケット単位でブロックパブリックアクセスをすべて有効化しています。

なお、S3ウェブサイトエンドポイントの仕様上、バケットポリシーにパブリックアクセス許可を含める必要があるため、SecurityHubやIAM Access Analyzerで検出される可能性があります。対象バケットについてはリスク受容または抑制ルールの対象としています。

S3バケットポリシーの設定

S3バケットポリシーでCloudFront経由のアクセスのみを許可しています。CloudFrontのカスタムオリジンヘッダーで User-Agent を任意の値に上書きし、バケットポリシーの aws:UserAgent 条件で一致するリクエストのみ許可する構成です。

{
  "Condition": {
    "StringEquals": {
      "aws:UserAgent": "<任意の値>"
    }
  }
}

無条件のPublic Readは付与していません。CloudFrontを経由しないリクエストは条件に合致せず拒否されます。

また、ListBucket権限を付与していないため、バケット内オブジェクトの一覧は返りません。S3ウェブサイトエンドポイントではインデックスドキュメントが発動するため、ディレクトリアクセス時にファイル一覧が漏洩するリスクはありません。

クロール・インデックスの抑制

検索エンジンに拾われたくないコンテンツには以下を設定しました。

  • robots.txt によるクロールの抑制
  • CloudFront Response Headers Policyの X-Robots-Tag: noindex による検索エンジンへのインデックス登録の抑制

これらも検索結果への露出を抑制する施策です。

通信と暗号化

CloudFront → 閲覧者間は ViewerProtocolPolicy: redirect-to-https でHTTPS通信を強制しています。CloudFront → S3間はHTTP通信ですが、公開前提の静的コンテンツであり、経路もAWSネットワーク内で完結するため影響は限定的です。

暗号化はSSE-S3(AES256)をデフォルトで有効化し、SSE-Cは攻撃対策としてブロックしています。SSE-KMSは匿名配信に適さないため使用していません。

セキュリティ: 横断的な統制

IAMロール・CloudTrail等の設定

予防的対策

  • IAMロールの最小権限化: 操作対象S3バケット・リソースARN・権限を限定
  • アクセスキー禁止: IAMロールのみ提供し、スイッチ時のMFAを必須化
  • CloudTrailの有効化(S3データイベントの記録を含む。書き込み系イベントに限定しコストを抑制)

検知的対策

  • GuardDuty + SecurityHubによる継続的監視を有効化しています

アカウントレベルの統制(クラスメソッドメンバーズ)

当環境のAWSアカウントは、クラスメソッドメンバーズを利用しています。

https://classmethod.jp/aws/services/invoice/

サービスに付随するセキュアアカウント機能とインシデント自動調査を利用しています。

  • リージョン制限: SCPで未使用リージョンを制限し、攻撃面を縮小
  • 設定維持: セキュアな設定の維持
  • 自動調査: GuardDuty連携によるインシデント発生時の迅速な調査

運用監視

S3オブジェクト操作の変更通知

以下のパイプラインでS3オブジェクト操作をSlackに通知しています。

CloudTrail → EventBridge → Firehose → S3 → EventBridge → Lambda → SNS → Chatbot → Slack

これは必須構成ではなく追加構成です。本構成ではCloudTrailをオブジェクトログを利用してIAMロールの引受元(操作者)の特定を可能にし、Firehosを経由させる事で一括更新時(数百ファイル同時アップロード等)の通知スパイク対策としています。

更新頻度が少ない場合はS3イベント通知 → SNS → Chatbotのようなシンプルな仕組みで十分対応できます。

コスト・セキュリティ監視

コストとセキュリティの異常を早期に検知するため、以下を設定しています。

  • Cost Anomaly Detection: 異常なコスト増加を検知
  • Billing Alarm: 月額上限を超過した場合に通知
  • GuardDuty Finding → Chatbot → Slack通知

コスト実績

CloudFrontの配信コスト実績です(2026年3月〜5月)。

転送量 CloudFront費用
3月 14.8 GB $1.31
4月 12.0 GB $1.02
5月 17.6 GB $1.45

月間転送量15GB前後、CloudFrontの配信コストは月$1〜1.5程度です。

2025年11月に登場したCloudFront定額プランのFree枠(100万リクエスト/100GB)に収まる規模ですが、イベント告知などで一時的にトラフィックが増加した際にCDNの無料枠制限でサイトが停止するリスクを避けるため、従量課金のまま利用しています。平時の配信コストが月$1〜1.5でProプラン($15/月)を選ぶ理由もありません。

定額プランの売りの一つにWAFの標準付帯がありますが、平時はWAFの必要性を感じていません。Cost Anomaly Detectionで転送費用の異常な高騰を検知した場合に、アクセスログを解析して対処療法的にWAFを導入すれば間に合う想定です。

https://dev.classmethod.jp/articles/aws-flat-rate-pricing-plans/

S3設定とログ

S3ウェブサイトエンドポイント構成においても、適用可能なベストプラクティスは踏襲しています。

  • バージョニング: 全ウェブホスティング用バケットで有効化
  • 旧バージョンの自動削除: NoncurrentVersionExpirationでストレージ肥大化を防止
  • SSE-S3デフォルト暗号化・SSE-Cブロック: 全バケットで有効
  • 非公開バケット: ブロックパブリックアクセス全有効

ログは以下を取得しています。

  • CloudFrontアクセスログ: 標準ログでS3に出力
  • S3サーバーアクセスログ
  • CloudTrail: S3オブジェクト操作を記録(変更操作者の特定が目的)

ログ保持はバケットごとにライフサイクル設定で自動削除しています。

まとめ

S3静的ウェブサイトホスティングは2026年時点ではベストプラクティスとは言えない構成ですが、用途を限定し制約を正しく補えば、運用負荷が低く実用的な配信基盤として機能します。ただし、エンドツーエンドの暗号化通信が必須など、本構成を採用できない要件にはご留意ください。

CloudFront Functionsを無理なく運用できる場合には、ベストプラクティス構成のS3オリジン + OACを利用することをおすすめします。

https://dev.classmethod.jp/articles/amazon-cloudfront-origin-access-control/

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事