CloudFront のキャッシュ・セキュリティヘッダ・SPA 設定

CloudFront の Distribution は設定項目が多く、初心者は何から手を付けて良いか迷います。本記事では、本シリーズで採用した マネージドポリシーの組み合わせ と、SPA 用の カスタムエラーレスポンス、その他のおすすめ設定をまとめます。

AWS マネージド Cache Policy

CloudFront には AWS が用意した Cache Policy が複数あり、自分で書かなくてもまずこれを使えば 7 割の用途で十分です:

ポリシー名ID用途
CachingOptimized658327ea-f89d-4fab-a63d-7e88639e58f6静的サイト(HTML/CSS/JS/画像)。最大 24h キャッシュ
CachingDisabled4135ea2d-6df8-44a3-9df3-4b5a84be39adAPI・動的レスポンス。キャッシュしない
CachingOptimizedForUncompressedObjectsb2884449-e4de-46a7-ac36-70bc7f1ddd6d圧縮済 (gzip 等) ファイル向け

本シリーズでは default_cache_behaviorCachingOptimized/api/* behavior に CachingDisabled を割り当てました。

マネージド Origin Request Policy

「オリジンに何を転送するか」のポリシー:

ポリシー名ID用途
AllViewer216adef6-5c7f-47e4-b989-5492eafa07d3全ヘッダ・クエリ・cookie を転送
AllViewerExceptHostHeaderb689b0a8-53d0-40ab-baf2-68738e2966acHost 以外を転送(API GW など Host 上書きが要らない時)
UserAgentRefererHeadersacba4595-bd28-49b8-b9fe-13317c0390faUA + Referer のみ

API Gateway を origin にする時は AllViewerExceptHostHeader を使います。Host を上書きされると API GW がリクエストを正しくルーティングできない問題を回避するため。

マネージド Response Headers Policy(セキュリティヘッダ)

AWS マネージドの SecurityHeadersPolicy(ID: 67f7725c-6f97-4210-82d7-5512b31e9d03)を割り当てるだけで、以下の主要セキュリティヘッダが すべてのレスポンスに自動付与 されます:

これを 1 行で全付与できるのは強い。手動で書くと環境ごとにブレるので、マネージド推奨。

本シリーズの default_cache_behavior

default_cache_behavior {
  target_origin_id           = "s3-${var.bucket_name}"
  viewer_protocol_policy     = "redirect-to-https"  # HTTP → HTTPS リダイレクト
  allowed_methods            = ["GET", "HEAD"]
  cached_methods             = ["GET", "HEAD"]
  compress                   = true                   # gzip/brotli 自動圧縮

  cache_policy_id            = "658327ea-f89d-4fab-a63d-7e88639e58f6"  # CachingOptimized
  response_headers_policy_id = "67f7725c-6f97-4210-82d7-5512b31e9d03"  # SecurityHeadersPolicy
}

SPA 用カスタムエラーレスポンス

SPA(Single Page Application)でクライアントサイドルーティングを使うと、/about 等は S3 に存在しない URL にアクセスする場合があり、403 や 404 が返ります。これを 200 + index.html に書き換え ると、JavaScript ルーティングが動くようになります:

custom_error_response {
  error_code         = 403
  response_code      = 200
  response_page_path = "/index.html"
}

custom_error_response {
  error_code         = 404
  response_code      = 200
  response_page_path = "/index.html"
}

Next.js の static export や Astro / Vue Router 等の SPA で必須の設定です。

HTTP/3 (QUIC) の有効化

http_version = "http2and3"

HTTP/3 はモバイルや不安定回線で速度向上が見込める。CloudFront のデフォルトは http2 ですが、最新 Chrome / Safari は HTTP/3 対応なので有効化すべき。コスト変動なし。

Geo Restriction

本シリーズでは個人サイトなので地理制限なし:

restrictions {
  geo_restriction {
    restriction_type = "none"
  }
}

クライアント案件で「日本国内のみ」要件があれば whitelist + locations = ["JP"] を指定。法令対応で必要になることがあります。

TLS 設定

viewer_certificate {
  acm_certificate_arn      = var.certificate_arn
  ssl_support_method       = "sni-only"             # SNI で複数ドメイン同居
  minimum_protocol_version = "TLSv1.2_2021"         # TLS 1.2+ 必須
}
項目意味
ssl_support_methodsni-only標準。月 0 円。vip にすると月 $600 だが、SNI 非対応の古いクライアント (IE6 等) も繋がる
minimum_protocol_versionTLSv1.2_2021TLS 1.2 以上を必須に。古いクライアント(PCI-DSS 準拠で SSLv3 / TLS 1.0 が NG)を切り捨て

Price Class の選び方

クラス範囲料金(無風時)用途
PriceClass_100北米・欧州のみ最安北米欧州ターゲットなら
PriceClass_200上 + アジア・中東・アフリカ日本ターゲットならこれ
PriceClass_All全世界最高南米・オセアニアもカバーしたい時

本シリーズは日本訪問者がメインなので PriceClass_200All との性能差は日本国内ではほぼない(同じ東京 Edge から配信される)のでコスト最適。

キャッシュ無効化(Invalidation)

新しい index.html を S3 にアップロードしても、CloudFront のキャッシュが残っていると古いまま。明示的に無効化が必要:

# 特定パスのみ
aws cloudfront create-invalidation \
  --distribution-id EXXXXXXXXXXXXX \
  --paths "/index.html"

# 全部
aws cloudfront create-invalidation \
  --distribution-id EXXXXXXXXXXXXX \
  --paths "/*"

料金は 月 1,000 paths まで無料、超過分は path あたり約 $0.005。/* は wildcard で 1 path カウント。リリース毎に /* 1 個なら無料枠で余裕。

キャッシュ無効化のハマり

本シリーズの GitHub Actions ワークフローは当初 --paths "/index.html" "/" と書いていましたが、新しく追加した learn.htmlblog/ は無効化されない ため反映が遅れる事故がありました。/* に変えて解決。

動作確認の見方

curl -sI https://lab.iigtn.com/

# 主要ヘッダ
Strict-Transport-Security: max-age=31536000     # ← SecurityHeadersPolicy
X-Frame-Options: DENY                            # ← 同上
X-Content-Type-Options: nosniff                  # ← 同上
Referrer-Policy: strict-origin-when-cross-origin
Server: AmazonS3
Via: 1.1 ...cloudfront.net (CloudFront)
X-Cache: Hit from cloudfront                     # ← 2 回目以降は Hit
X-Amz-Cf-Pop: NRT12-P4

次の記事

静的サイトが安定して配信できるようになったら、次は 「ローカル PC からの手動アップロードを自動化する」 ステップへ。git push したら GitHub Actions が自動デプロイする CI/CD を組みます。次の記事ではその要となる GitHub Actions OIDC の仕組みを解説します。

📚 用語集

Cache Policy (CloudFront)
「何をキーにキャッシュ、TTL いくつ、圧縮するか」を定義するポリシー。AWS マネージドの定番ポリシーがある。
CachingOptimized
静的コンテンツ向け AWS マネージド Cache Policy。最大 24h キャッシュ・gzip/brotli 受け入れ・Accept-Encoding ベースの分離キャッシュ。
CachingDisabled
キャッシュしない AWS マネージド Cache Policy。動的 API レスポンス向け。
Origin Request Policy
「オリジンに何を転送するか」を定義するポリシー。ヘッダ / クエリストリング / cookie の転送可否を制御。
AllViewerExceptHostHeader
AWS マネージドの Origin Request Policy。Host 以外すべてオリジンへ転送。API Gateway 等は Host を上書きされると混乱するので、これを使う。
Response Headers Policy
「レスポンスにどのヘッダを付けるか」を定義するポリシー。セキュリティヘッダの自動付与に便利。
SecurityHeadersPolicy
AWS マネージドの Response Headers Policy。X-Frame-Options / X-Content-Type-Options / Strict-Transport-Security 等を自動付与。
SPA (Single Page Application)
JavaScript で画面遷移する Web アプリ。React / Vue / Astro などが該当。CloudFront 配信時は 403/404 → /index.html のフォールバックが必要。
クライアントサイドルーティング
ブラウザの JavaScript で URL と表示内容を切替える方式。/about へのアクセスでもサーバには /index.html を返してもらう必要がある。
custom_error_response (CloudFront)
オリジンが特定のエラーコードを返した時の挙動を上書きする設定。SPA フォールバックで 403/404 → 200 + /index.html によく使う。
HTTP/3 (QUIC)
HTTP の最新版。UDP ベースで接続確立が速く、不安定回線でも切れにくい。Chrome / Safari 最新版が対応。
SNI (Server Name Indication)
1 つの IP アドレスで複数ドメインの TLS 証明書を出し分ける TLS 拡張。CloudFront sni-only はこれが前提。
HSTS (HTTP Strict Transport Security)
「このサイトは HTTPS のみ」をブラウザに記憶させるレスポンスヘッダ。中間者攻撃で HTTP に降格させられる事故を防ぐ。
X-Frame-Options: DENY
このページを iframe 内に表示することを禁止するヘッダ。クリックジャッキング攻撃の対策。
Geo Restriction
CloudFront の地理制限機能。国コード(ISO 3166-1 alpha-2)で whitelist / blacklist を指定。
Invalidation
CloudFront の Edge キャッシュを無効化する操作。新しいバージョンを即時反映させたい時に必要。月 1,000 paths まで無料。
wildcard path (/*)
Invalidation での全パス無効化。1 path カウントで全 path をクリアできるので、リリース毎に 1 回叩けば無料枠内に収まる。