こんにちは、株式会社インゲージでSREを担当しているanecho108と申します。
2025年4月28日に CloudFront のマルチディストリビューションがリリースされました。呼び方としては、CloudFront SaaS Manager が全体を指し、その中の機能のひとつが CloudFront マルチディストリビューションという位置づけになりそうですね。
Amazon CloudFront 向け SaaS Manager の発表
AWSコンソールのCloudFront画面でいうと、下記の箇所です。
- Amazon CloudFront 向け SaaS Manager の発表
- 何が嬉しいの?
- CloudFront Saas Manager
- CloudFront Saas Managerの作成
- ハマったところ
- CloudFront Saas ManagerのTerraformは未GA
- さいごに
何が嬉しいの?
静的ページでのSaasアプリケーションを例に
例えば、このブログのドメイン blog.hatena.ne.jp を使ってSaaSアプリケーションを構築するとしましょう。
AWSでSaaSアプリケーションを静的ページで構築する場合、基本的なアーキテクチャは CloudFront + S3 となります。
マルチテナント対応にしたいので、*.blog.hatena.ne.jp という証明書を使い、アスタリスク部分にテナントごとのサブドメインを割り当てる構成になります。
お客様のドメインでSaasアプリケーションを使いたい
通常のSaaSアプリケーションであれば特に問題はありませんが
例えば、お客様のサイト内にFAQやチャットボットを埋め込む、あるいは専用ページに遷移させる といったケースでは、
「お客様が保有する独自ドメインでアクセスさせたい」というニーズが出てきます。
このとき一見すると「お客様ドメインのCNAMEをCloudFrontに向ければよい」と思えます。 しかし実際にアクセスすると、CloudFront側の証明書(例: *.blog.hatena.ne.jp)とお客様ドメインが一致しないため、TLS証明書エラーになってしまいます。
そのため、従来はお客様ごとにCloudFrontディストリビューションを用意し、さらにお客様専用の証明書をACMで発行・関連付ける必要がありました。
IaC管理として考えると、Terraformでお客様ごとにCloudFrontを作りたくないです。管理が煩雑化しそうですね。
また、AWSアカウント単位で作成できるCloudFron ディストリビューションのクォータは100に制限されています。
そのため、お客様ごとにCloudFrontを個別作成する方式では、最大でも100ドメイン分までしか対応できません。
成長を見込んだマルチテナント型SaaSアプリケーションにおいては、この制約では明らかに不足してしまいます。
クォータ - Amazon CloudFront
そこでCloudFront Saas Managerが嬉しい
新たにGAされたCloudFront SaaS Managerを使うと、お客様側の作業はDNSに使用したいドメインをCloudFrontマルチディストリビューションのドメインに向けるだけ で済みます。
CloudFront SaaS Manager では、テナント用のディストリビューション(Distribution Tenant)を作成するだけで、裏側でACM証明書を自動的に作成・検証してくれます。 そのため、従来のようにお客様ごとにCloudFron と証明書を個別に管理する必要がなくなります。
さらに、ディストリビューションテナントは最大10,000まで作成可能です。 ただし、ACM証明書のデフォルト上限は2,500であるため、多数のテナントを想定する場合は上限引き上げの申請が必要になる可能性があります。 docs.aws.amazon.com クォータ - AWS Certificate Manager
CloudFront Saas Manager
AWSでは、CloudFront SaaS Manager を下記のように紹介しています。
https://aws.amazon.com/jp/blogs/news/reduce-your-operational-overhead-today-with-amazon-cloudfront-saas-manager/
キーワードとしてはマルチディストリビューション、ディストリビューションテナント、コネクショングループ の3つがあります。 ざっくり言うと以下の通りです:
マルチディストリビューション
従来のCloudFron ディストリビューションをテンプレート化したものです。 ここで共通のオリジン設定、キャッシュビヘイビア、WAF設定などを定義します。
ディストリビューションテナント
マルチディストリビューションを継承して作成され、お客様のドメインを割り当てます。 WAFルールのオーバーライドは可能。お客様ドメインを使わず、マルチディストリビューションで定義したドメインのまま利用することも可能。 オリジンやキャッシュビヘイビアの設定は親のマルチディストリビューションから継承され、テナント側では変更できません。
コネクショングループ
CloudFrontのドメインを表し、ディストリビューションテナントと紐づけます。 複数のコネクショングループを利用することで、IPv4 / IPv6などのIP設定が可能です(詳細は後述しますが、重要なポイントです)。
CloudFront Saas Managerの作成
クラスメソッドさんの記事で CloudFront SaaS Managerの作成手順が紹介されていますので、具体的な設定方法や手順はそちらを参考にしていただければと思います。
※僕自身も記事を参考にさせていただきました。ありがとうございます。 dev.classmethod.jp
ハマったところ
ここでは、僕が実際にハマったところだけ載せておきます。
パラメータ
マルチディストリビューション側のテンプレートでは、各テナントごとに値を持てる変数を定義することができます。 ディストリビューションテナントを作成する際に、その変数に具体的な値を埋め込む仕組みです。
この仕組みの利点は、例えばS3にテナントごとに階層が分かれたディレクトリ構成がある場合などに非常に役立つことです。
変数を使うことで、テンプレートを使い回しつつ、各テナント固有の設定を簡単に反映できます。
CloudFrontでは、URI にテンプレートパラメータがどのように付与されてオリジンに渡るか を確認してみました。
おおよその流れは以下の通りです:
キャッシュビヘイビア ↓ CloudFront Function(Viewer Request) ↓ 各ディストリビューションテナントのパラメータ付与 ↓ オリジンにリクエスト
たとえば、キャプチャのように
subdomain パラメータの前段に /emacs/{subdomain} を設定し、
オリジン: S3 キャッシュビヘイビア: /ingage* テナントパラメータ: subdomain = testdomain
とした場合、実際にオリジンに渡されるパスは以下のようになります:
/emacs/testdomain/ingage*
つまり、URIの先頭にパラメータが付与された形で S3にアクセスされそうです。
この仕様のため、S3の階層設計が影響しそうです。 私も最初、この仕様に気づかずにバケットポリシーを何度も見直し、「Access Denied」に悩まされました。
もしS3のディレクトリ構造を変えられない場合は、CloudFront Function(Viewer Request)でURIを加工して調整する必要があります。
初回のディストリビューションテナントで作成されるACM証明書のHTTP検証にクセがある
ディストリビューションテナントを作成した直後、裏側ではACM(検証中)が作られています。
リンク押下先のACM証明書が作成されていることがわかります。
すぐにHTTP検証してくれない
初回に作成されたディストリビューションテナントのACM証明書についてですが、 WAFのログを見る限り、すぐにはHTTP検証が実行されていないように見えました。
そこで、一度ACM証明書を削除し、キャプチャの "Complete domain setup" から再作成したところ、 HTTP検証が1〜3分程度で完了することを確認しました。
ACM証明書のHTTP検証はWAFを通過する
運用が始まり、CloudFrontマルチディストリビューションの設定が完了している状態を想定します。 この時点では、WAFとキャッシュビヘイビアからCloudFront Functionが設定されているとします。
この状態で、新たにディストリビューションテナントを追加すると、 WAFのログにACM証明書のHTTP検証リクエストが流れていることが確認できました。
ACM証明書の更新時も同様にHTTP検証が行われるため、 誤ってこれらのリクエストをブロックしないよう注意が必要です。
お客様にご登録いただくDNSのCNAMEレコードについて
私が検証中にRoute53を利用していたことも影響しているのですが、 「CNAMEレコードを登録すればいいでしょ」と思い、いつもの感覚でエイリアスレコードを登録しました。
しかし、ディストリビューションテナント上では有効になりませんでした。 CloudFront SaaS Manager では、CNAMEとしてレコードを登録する必要があります。
もしエイリアスなら、_cf-challenge.を先頭に付与してTXTレコードが必要になるようです。 docs.aws.amazon.com
コネクショングループのIPv6について
デフォルトで作られるCreateBy〜というコネクショングループですが、digで名前解決がうまくいきませんでした。 そのため、個別にコネクショングループを作成しました。
コネクショングループではIPv4とIPv6のどちらかを選択できます。 私の環境では、CloudFront FunctionでIP制限を作成していましたが、WAFのログを見るとクライアントからIPv6でアクセスされていることを確認しました。
推測ですが、CNAMEレコードに登録したCloudFrontのコネクショングループでIPv6が有効になっており、 クライアント側もIPv6を持っていたため、通信がIPv6経由で行われたという流れだと思われます。 コネクショングループをIPv4に変更することで、クライアントのアクセスもIPv4で統一されました。
補足として、AWSコンソールのCloudFront画面左下部のSettingsを有効にすると、コネクショングループの設定が画面上に表示されます。
CloudFront Saas ManagerのTerraformは未GA
こちらのIssueを確認する限り、まだ完全にはリリースされていないようです。
現状の運用イメージとしては、マルチディストリビューションやコネクショングループ側のみをTerraformで作成し、 ディストリビューションテナント自体はIaC管理外として、テナント作成時にAPI経由で作成する流れになるのではないかと思います。 github.com
さいごに
Saasアプリケーションの悩みどころを解決するCloudFront Saas Managerは非常に魅力的でした。 弊社では実際に運用していこうと考えていますので、また新たなハマりどころがありましたら、こちらの記事をアップデートしていきたいと思います。