テナントごとにサブドメインを割り当てるマルチテナントアーキテクチャの時に、CloudFront に適用する Web ACL をテナントごとに管理する
いわさです。
マルチテナント SaaS を構築する時、プール型モデルで同一の CloudFront や ALB を複数テナントで共用する場合があります。
同じドメインを使う場合もあれば、サブドメインでテナントを識別子して、リソースは同じものを使う方法などもあります。
後者の場合、エンドポイントをWAF で保護する際に、その WAF 要件にテナントごとのカスタマイズが必要になる場合があります。
よくあるのはテナント(サブドメイン)ごとに異なる IP アドレス許可セットを割り当てる方法です。
以下の記事では単一の Web ACL の中で、サブドメインごとに IP アドレスを判断する方法です。
単一の Web ACL で判定が出来るのでコスト最適化の観点からも有効な方法だと思います。
一方で、例えばテナント数が多くなりすぎた時にテナント追加や変更によって Web ACL 全体(テナント全体)に影響がでる場合がリスクになったり、プライシングの関係で特定テナントだけ Web ACL のルールを高度にカスタマイズしたくなる場合もあります。
今回はサブドメインごとに異なる Web ACL を使う方法を検討したので紹介します。
結論としてはマルチテナントディストリビューションに切り替えた上で、テナントディストリビューションごとにセキュリティ設定をオーバーライドしてやることで、ディストリビューションは共通のものを使いつつ、テナント固有の Web ACL を使うことができます。
マルチテナントディストリビューションを構成する
マルチテナントディストリビューションについては GA された時の以下の記事で解説していますのでこちらを見てください。
複数のドメインで一部設定が共通のディストリビューションを使いたい場合があるのですが、それを実現できる機能です。同じディストリビューション設定の複製を繰り返しているような方は採用できる場合があると思います。
今回はマルチテナントディストリビューションを新規構築します。

既存のディストリビューションをマルチテナントディストリビューションへ移行したい場合は次のドキュメントを事前に確認してください。
特に、通常のディストリビューションでサポートされているがマルチテナントディストリビューションでサポートされていない機能が存在しますのでそこは特に注意しましょう。ざっくり言うとレガシーや非推奨な機能はサポートされていないです。
マルチテナントディストリビューションが構築できたら、今回は次のように複数のテナントを作成しました。サブドメインの割り当てを変えていますが、ドメイン自体別のものを割り当てることも可能です。
SaaS のニーズによくある個別の顧客にカスタムドメインを提供したい場合などにも採用できます。

マルチテナントディストリビューションのテナントパラメータという機能を使っていて、同一オリジン(API Gateway)なんですけどレスポンスが変わるようになっています。
% curl https://hoge0429tenant1.tak1wa.com/
{
"path": "tenant1"
}
% curl https://hoge0429tenant2.tak1wa.com/
{
"path": "tenant2"
}
Web ACL をオーバーライドする
マルチテナントディストリビューション自体は次のようにセキュリティタブから AWS WAF を関連付けることができます。

一方でディストリビューションテナント自体にも次のようにセキュリティタブがあって、マルチテナントディストリビューションの設定を無視してテナントごとに個別の設定を行うことができます。

ということで、テナントAとテナントBでそれぞれ別の Web ACL を関連付けしてみます。

図で表すとこんな感じです。ディストリビューションが多段になっているわけではないのですが、マルチテナントディストリビューションがエンドポイントになりつつ、サブドメインごとにテナント設定が適用されるようなイメージです。

Web ACL のデフォルトアクションをブロックにしてやると、サブドメインごとに許可された IP アドレスでのみアクセスできるようになりました。
% curl https://hoge0429tenant1.tak1wa.com/
{
"path": "tenant1"
}
% curl https://hoge0429tenant2.tak1wa.com/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Request blocked.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: CJipqsMFKmgY-cHRg8rrIRwhehXAAyKlhjIQM2w1SYBXN3Lzl1RF1A==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>
さいごに
本日はテナントごとにサブドメインを割り当てるマルチテナントアーキテクチャの時に、CloudFront に適用する Web ACL をテナントごとに管理する方法を検討し試してみました。
課題はコスト感ですかね。
マルチテナントディストリビューションの料金は以下です。
CloudFront SaaS Manager という機能を使うことになるのですが、10 テナントまでは無料、11~200 テナントの場合は $20 で、以降は 1 テナントあたり $0.1 です。
そして、Web ACL がテナントごとに作成する形になると思うので最低 1 Web ACL が $5 からです。
複雑なルールの Web ACL がテナントごとに作成される場合、この Web ACL の料金が無視できなくなります。Bot Control とか使い始めるとなかなか。
SaaS のプライシングとして WAF 機能をオプション化することでマネタイズできそうであれば採用するのが良さそうですが。IP アドレスリストくらいであれば冒頭の 1 Web ACL で管理しても良い気がします。運用性とのトレードオフですかね。






