CloudFront で単一ディストリビューションでのホストベースルーティングが出来るのかを確認してみた

2022.09.21

いわさです。

CloudFront ではディストリビューションに複数のオリジンを割り当てることが出来ます。
オリジンを切り替えるには基本的にはビヘイビアでパスベースのルールを設定します。

パスベースで切り替える方法はデフォルトで用意されているのですが、ホストベースで切り替える方法は用意されていないようです。
実現方法のひとつとして Lambda@Edge を使って対象オリジンを動的に設定する方法が DevelopersIO で紹介されています。

Lambda@Edge 使わずにどうにか実現出来る方法ないかなーと思ってビヘイビアを眺めていたところ、パスパターンに以下のような形で入力することが出来ました。
これはもしかしてホストベースルーティング出来る...?念の為確かめてみることにしました。

先にまとめ

やはり出来ませんでした。
パスがマッチせずにすべてデフォルトビヘイビアで動作していました。

しかし前述の Lambda@Edge の必要性が再認識出来たので試してよかったのと、Lambda@Edge でも難しい場合がわかったので確認して良かったというところです。
結果を先に紹介したので以降はあまり意味がないですが記録として残しておきます。

Lambda@Edge などを使ってカスタムせずにホストベースルーティング出来ないのか?という方の参考になれば。

S3 にて静的コンテンツをホスティング

まずは S3 バケットを作成し適当な静的コンテンツをアップしておきます。

% aws s3 mb s3://hoge0921bucket1 --profile hoge
make_bucket: hoge0921bucket1
% aws s3 mb s3://hoge0921bucket2 --profile hoge
make_bucket: hoge0921bucket2
% aws s3 mb s3://hoge0921bucket3 --profile hoge
make_bucket: hoge0921bucket3

% aws s3 cp ./hoge1.html s3://hoge0921bucket1/hoge1.html --profile hoge
upload: ./hoge1.html to s3://hoge0921bucket1/hoge1.html
% aws s3 cp ./hoge2.html s3://hoge0921bucket2/hoge2.html --profile hoge
upload: ./hoge2.html to s3://hoge0921bucket2/hoge2.html
% aws s3 cp ./hoge3.html s3://hoge0921bucket3/hoge3.html --profile hoge
upload: ./hoge3.html to s3://hoge0921bucket3/hoge3.html

作成した各バケットの静的ウェブサイトホスティングを有効化し、バケットポリシーでパブリックアクセス出来る状態にします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            "Resource": [
                "arn:aws:s3:::hoge0921bucket1/*"
            ]
        }
    ]
}

S3 静的ウェブサイトホスティングはこれで準備が出来たのでまずリクエストを送信してみます。

% curl http://hoge0921bucket1.s3-website-ap-northeast-1.amazonaws.com
bucket1
% curl http://hoge0921bucket2.s3-website-ap-northeast-1.amazonaws.com
bucket2
% curl http://hoge0921bucket3.s3-website-ap-northeast-1.amazonaws.com
bucket3

良いですね。

CloudFront 作成

CloudFront ディストリビューションを作成し、先程作成した 3 つのエンドポイントをターゲットにしたオリジンを作成します。

CloudFront ではビヘイビアごとにオリジンを紐付ける形となります。
ここでパスパターンに以下の 3 つを入力します。

  • https://aaa.example.com/
  • https://bbb.example.com/
  • https://ccc.example.com/

続いて HTTPS でアクセスするので ACM パブリック証明書を作成します。
後述しますが、ディストリビューションにはひとつのカスタム SSL 証明書のみ関連付け出来るのでワイルドカードで定義します。

CloudFron の代替ドメイン名を定義することで複数のサブドメインでアクセス出来るように定義します。
この段階で気がついたのですが、ディストリビューションあたり関連付け出来るカスタム SSL 証明書は一つまでですね。
なので、冒頭の Lambda@Edge で実現するものも、代替ドメインとカスタム SSL 証明書で設定出来る範囲から外れるものは実現が難しそうです。サブドメインまででしょうかね。

最後にホストゾーンでディストリビューションを設定します。

確認してみる

では CloudFront 経由でアクセスしてみましょう。

% curl https://aaa.tak1wa.com/
bucket2
% curl https://bbb.tak1wa.com/
bucket2
% curl https://ccc.tak1wa.com/
bucket2

すべてbucket2がレスポンスされています。
これはデフォルトビヘイビアで設定したオリジンです。

つまり、パスベースで設定したどのビヘイビアにも該当せずにデフォルトビヘイビアが動作しています。

パスベースも再確認

念の為パスベースルーティングも試してみます。
パスパターンを正しい形に変更します。

% curl https://aaa.tak1wa.com/aaa/
bucket1
% curl https://aaa.tak1wa.com/bbb/
bucket2
% curl https://aaa.tak1wa.com/ccc/ 
bucket3

期待どおり、パスに応じてビヘイビアとオリジンが選択されていますね。

さいごに

本日は CloudFront で単一ディストリビューションでホストベースルーティングが出来るのかを確認してみました。

まず CloudFront 標準機能では Application Load Balancer のようなホストベースルーティングが出来ないので気をつけましょう。
Lambda@Edge を使うことでオリジン切り替えを行う方法もありますが、今回確認したようにカスタム SSL 証明書の関係で実現が難しいケースがあります(全然別のドメインとか)

冒頭の記事でもまとめにて「個人的にはこのようなケースでは2つディストリビューションを用意してアクセスするドメインと使用するオリジンごとにディストリビューションを分けてしまうほうがシンプルになるかなと考えています。」と締められています。
基本的にはディストリビューションを分ける方向で考えるのが良さそうですね。