SREチームマネージャーの藤原です。
本エントリでは、現在構築中の新サービスにて利用する予定の CloudFrontおよびVPC Originの活用と、CloudFrontを経由した静的リソース配信について解説します。
シンプルな構成へのCloudFrontの導入
まずは非常にシンプルなアプリケーションを考えてみます(図1)。
単一のバックエンドのコンピューティングリソースに外部向けのAPIと内部向けのAPIがある場合、インターネットからアクセス可能な外部向けのロードバランサーと、内部からのみアクセス可能な内部向けのロードバランサーを分けて設定するパターンがあります。

このような構成の場合、静的リソース(画像やjs, cssなど)はバックエンドのコンピューティングリソースから配信することになります。静的リソースはコンピューティングリソースを消費しない形で配信したいところです。
そこで、CDNとオブジェクトストレージを活用します。AWSの場合、CloudFrontとS3を利用することになります。この場合、インターネットと外部向けアプリケーションロードバランサーの間にCloudFrontのディストリビューションを配置、静的リソース配信用のS3バケットを作成することになります(図2)。

CloudFrontと静的リソース配信用バケットの間については、OAC(Origin Access Control)を利用することでセキュアに接続できます1。
図2の構成では静的リソースをCDNを用いてコンピューティングリソースを使用することなく効率的に配布することができます。 さらに、外部向けアプリケーションロードバランサーからの動的リソース配信と同じドメイン名を使って静的リソースを配信できるため、CORS2などを意識する必要もありません。
ただし、この構成では、CloudFrontディストリビューションと外部向けアプリケーションロードバランサーの間に課題が埋まっています。
外部向けアプリケーションロードバランサーの抱える課題
外部向けアプリケーションロードバランサーはパブリックIPアドレスを持っています。 また、AWSマネージドなFQDNも持つため、CloudFrontを経由せずに直接アクセスが可能です(図3)。

一定以上の利用があるサービスを運用したことのある方にはわかると思いますが、ロードバランサーのIPアドレスやAWSマネージドなFQDNを直接指定したHTTPリクエストは、想像以上に多く発生します3。
ロードバランサーへの直接アクセスをブロックしつつ、CloudFrontを経由したアクセスを通したい場合、次のような対策が基本として考えられます。
- CloudFrontでHTTPヘッダを追加し、ロードバランサのリスナールールで特定のヘッダがある場合のみリクエストをフォワードする4
- CloudFrontのAWSマネージドプレフィックスリストをロードバランサーのセキュリティグループに適用する5
それでも、外部向けアプリケーションロードバランサーにはパブリックなIPアドレス(やAWSマネージドなFQDN)が割り当てられたままです。そこで「パブリックIPアドレスもFQDNも持たないロードバランサーをCloudFrontのオリジンとして使えないだろうか」と考えたくなります。この考えを実現してくれるのがCloudFrontのVPC Originです。
CloudFrontのVPC Origin
CloudFrontのVPC Origin機能を利用すると、プライベートサブネット内にENI(Elastic Network Interface)が作成されます。このENIを経由して、CloudFrontディストリビューションとアプリケーションロードバランサー間の通信が行われます(図4)。

VPC Originを利用することで、CloudFrontディストリビューションのオリジンを、パブリックサブネットに配置された外部向けロードバランサーではなく、プライベートサブネットに配置されたロードバランサー(以前の図における内部向けロードバランサー)とすることができます。
プライベートサブネットに配置されたアプリケーションロードバランサーは内部向けのため、パブリックIPアドレスを持ちません。これにより、CloudFrontディストリビューションを経由しないインターネットからの直接アクセスを完全に排除できます。
VPC Originを導入した後の構成
VPC Originを導入した後の構成としては図5のようになりました。

図1と図5を比較すると、以下の機能的な違いがあります。
- 静的リソースを配信用バケットで提供することで、コンピューティングリソースを消費せずに配布できるようになった
図2と図5を比較すると、主な差分は次の2点です。
単純な構成の差分としてはここまでです。運用時も見据えると以下の観点でメリデメが生じます。
- メリット
- デメリット
- アプリケーションロードバランサーの設定が複雑化する可能性(構成管理上顕在化する可能性のあるもの)
- 外部向けと内部向けのリスナールール両方を一つのリスナー設定に含める必要がある
- アプリケーションロードバランサーの設定が複雑化する可能性(構成管理上顕在化する可能性のあるもの)
アプリケーションロードバランサーのリスナールールは外部向けと内部向けの両方を単一の場所にまとめて記述する必要があるため、複雑なルールを設定する場合は注意が必要です。
一方で、設定が一箇所にまとまることで「あれ、これはどのロードバランサに含まれていたっけ?」といった混乱が起きにくくなるため、リスナー設定がシンプルな場合はデメリットは最小化できます。
今回設計したサービスではリスナールールに複雑な要素がほとんどなかったため、外部向けと内部向けのロードバランサーを一つに統合した際のデメリットの顕在化はほぼなく、直接アクセス経路の排除というメリットのみを実質的に得ることができました。
まとめ
本エントリでは、CloudFrontのVPC Originの利用による構成への影響、CloudFrontを使った静的リソースの配信について触れました。 特にCloudFrontのVPC Originを利用することでパブリックサブネットの利用を最小化することはセキュリティ観点でポジティブに捉えて良いでしょう。 今後はCloudFront + VPC Origin + ロードバランサーの組み合わせがAWSの構成のデファクトスタンダードとなる可能性もあるかもしれないとも感じました。
また、静的リソース配信についてはCloudFront + S3の組み合わせが大量アクセスを捌くといった観点でも非常に重要なので設定しない手はないと言えるでしょう。
- Amazon CloudFront オリジンアクセスコントロール(OAC)のご紹介↩
- オリジン間リソース共有 (CORS) - HTTP | MDN↩
- これは一種の攻撃に類するものではあるので、何かしらの対策はした方が良いでしょう。前職にて対策において参考となりそうな情報を提示しています。WAFを活用する上で入れておきたいファイアウォールのルール定義 - STORES Product Blog↩
- Application Load Balancer へのアクセスを制限する - Amazon CloudFront↩
- Amazon CloudFront用のAWS マネージドプレフィックスリストを使用したオリジンへのアクセス制限 | Amazon Web Services ブログ↩