Cloudfrontの動作確認を行っていたところ、HTTPS通信周りでハマったのでメモ。
#1.ユースケース
今回の構成は以下の通りです。
①:アプリケーションとしてのエンドポイントはCloudfrontに統一
②:キャッシュさせたいbahavior、キャッシュさせたくないbehaviorを持つ
③:CloudfrontとOrigin間の通信はHTTPSにする
このパターン自体はよくあるユースケースだと思います。
■構成例
この構成で問題となったのは、「キャッシュさせたくないbehavior」の設定です。
#2.キャッシュ対象外のbahavior設定(Forward Headers = ALL)
Cloudfrontでキャッシュさせたくない設定を実現する場合は、
Forward Headers = All
にするのが手っ取り早い設定になります。
実際、アプリケーションがどんなheaderを使っているかを洗い出す作業は面倒ですし、
ある程度大きい組織やプロジェクトだと、アプリケーション側の挙動まで把握できていないことも多く、
アプリケーション側の担当者の協力が不可欠ですし、色々な政治的な理由も相まって、
no-cache,no-store
ヘッダーを埋め込むこともできないこともあり、こうするケースが多いです。
この設定を行ったとき、CloudrontとOrigin間のHTTPS通信に罠がありました。
#3.SSLハンドシェイクに失敗する
Cloudfrontは、Defaultではhostヘッダーを削除しますが、
Froward headers = All
にすると、当然hostヘッダーも透過させることになります。
この設定を行うと、Cloudfront経由でOriginにアクセスした場合、
CloudfrontはHostヘッダーにCloudfront自身のDNS名をセットしてOriginにアクセスすることになります。
この状態で通信すると、SSLハンドシェイクに失敗し、502:Bad Gatewayエラーが返されます。
Cloudfrontによる証明書の検証に失敗してしまうのです。。。
#4.対応策
対処策は明白で「Hostヘッダーを透過させない」ということになります。
#5.Forward HeadersのBlack List設定はできない
ただ、Forward Headers = All
にしていたせいで、
Hostヘッダーだけ透過させない、という設定が簡単にはできませんでした。。。
CloudfrontのForward HeadersはWhite Listしか設定できません。。。
結果、必要なヘッダーを洗い出してWhite Listに設定するハメに。。。
安易にForward Headers = All
にしてしまうと、こんな状態に陥ってしまいますので、
アプリケーションとして透過すべきHeaderを明示的に洗い出す作業は、逃げずに事前にやっておいた方がよいですね
(当たり前と言えば当たり前なのですが)。。。
というか、CloudfrontのForward Headersの設定で、Black Listの設定ができればいいのにーーーー
と痛感しました(HostヘッダーだけBlack Listに登録できれば万事OKな事象なので)。
#6.まとめ
そもそも、キャッシュコンテンツとキャッシュ対象外コンテンツの両方をCloudfront経由にする
という構成自体が無しなのかもしれません。
キャッシュ対象だけCloudfrontを経由させるのが定石なので、それに倣った方が無難だということを痛感しました。
(CloudfrontとOrigin間の余計な通信が発生しないので、通信料も節約できるし。。。)
最後に、、、これはあくまで私的なメモですので、
特定の環境の情報を公開するものではありません(お約束)。