【AWS】CloudFrontとALBでリダイレクトさせてみた

この記事を書いたメンバー:

糸山和毅

【AWS】CloudFrontとALBでリダイレクトさせてみた

目次

1.はじめに

こんにちは、BeeXの糸山です。
本記事ではCloudFrontとALBの組み合わせによるリダイレトを検証してみます。

リダイレクトパターンについて

今回の検証ではドメインも新しいものにリダイレクトさせてみます。

  • https://test1_domain/beex-test/* のパスパターンにマッチした場合 
     パターン①:beex-test/redirect-{XXX}にマッチした場合 ※{XXX}は変数
       →https://www.beex-inc.com/blog/lightsail_{XXX}
     パターン②:/beex-testにマッチするが、/redirect-{XXX}にマッチしなかった場合
       →https://www.beex-inc.com/blog
  • https://test1_domain/beex-test/*のパスパターンにマッチしなかった場合
       →https://hrmos.co/pages/beex

2.CloudFrontによるリダイレクトについて

CloudFrontを使用したリダイレクトの場合は以下の2種類があります。
簡単にですが、違いをまとめてみます。

  • CloudFront Functions
  • Lambda@Edge

2.1CloudFront FunctionsとLambd@Edgeの違い[

この2つを使い分けを考えた場合は『実行時間』が特に大きな違いになるかと思います。
少しでも時間がかかる処理の場合はLambda@Edgeになります。
よく使いそうな項目を表にしましたが、さらに詳しい情報はこちらをご参照ください

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions.html


CloudFront FunctionsLambda@Edge
実行場所エッジロケーションエッジキャッシュ
リクエスト/レスポンスビューワーリクエスト
ビューワーレスポンス
ビューワーリクエスト
ビューワーレスポンス
オリジンリクエスト
オリジンレスポンス
ランタイムJavaScript
(ECMAScript5.1準拠)
Python
Node.js
最大実行時間1ミリ秒未満ビューワトリガー:5秒
オリジントリガー:30秒
スケール量毎秒1000万リクエスト毎秒1万リクエスト
処理可能データリクエスト
レスポンスヘッダ
リクエスト
レスポンスヘッダ
本文

■ビューワリクエストとは

キャッシュ内にリクエストされたオブジェクトがあるか確認する前に関数を実行します。

■ビューワレスポンスとは

リクエストされたファイルがビューワーに返される前に関数を実行します。
キャッシュ内にリクエストされたオブジェクトが既に存在したかどうかに関係なく、関数が実行されます。
以下の場合はビューワーレスポンスの関数が実行されないので注意が必要です。

  • オリジンが HTTP ステータスコードとして 400 以上を返した場合。
  • カスタムエラーページが返された場合。
  • ビューワーリクエストイベントによってトリガーされた関数からレスポンスが生成された場合。
  • CloudFront で HTTP リクエストが自動的に HTTPS にリダイレクトされる場合 ([ビューワープロトコルポリシー] の値が [Redirect HTTP to HTTPS] の場合)

■オリジンリクエストとは

現時点ではLambda@Edgeのみ使用可能です。
CloudFrontが受け付けたリクエストをオリジンに転送するタイミングで関数を実行します。
※リクエストをオリジンに転送する場合にのみ実行されます。そのため、キャッシュ内にデータがある場合はオリジンへの転送が行われないため関数も実行されません。

■オリジンレスポンスとは

現時点ではLambda@Edgeのみ使用可能です。
オリジンからのレスポンスをキャッシュする前に関数を実行します。

上記の通り、ビューワーリクエスト/レスポンス、オリジンリクエスト/レスポンスの計4種類を使用することができるのですが、今回はビューワーリクエストにCloudFront Functionsを関連付けてリダイレクトしてみます。

3.ALBによるリダイレクトについて

実はALB単体でもリダイレクトが行えます。
【リスナールール】で設定を行うことができます。

3.1ALBで指定可能な条件とアクション

リスナールールとして指定可能は条件タイプは以下の通りです。

  • ホストヘッダー
  • パス
  • HTTPリクエストメソッド
  • 送信元IP
  • HTTPヘッダー
  • 文字列のクエリ


さらに、各ルール内では最大5つまでの条件を定義できます。
(AまたはBまたはCまたはDまたはEの条件に合致した場合)

実行可能なアクションは以下の通りです。

  • ターゲットグループへの転送
  • 指定したURLへのリダイレクト
  • 固定レスポンスを返す


ターゲットグループへの転送には重みづけを定義することも可能です。
複数のターゲットグループを転送先に指定した際に、ターゲットグループAは20%、ターゲットグループBには80%のリクエストを送信する といった使い方も可能です。

4.ACMでCloudFront用の証明書を発行する

CloudFrontにHTTPSで接続するための証明書を発行します。
発行時の注意点があるのですが、リージョンは必ず「バージニア北部」を選択してください 
参考リンク

発行できたらRoute53にCNAMEレコードを追加します。

5.CloudFrontの作成

CloudFrontを作成していきます。
先にディストリビューションを作成し、次にCloudFrontFunctionsを設定します。

5.1ディストリビューションの作成

以下の内容でディストリビューションを作成します。
オリジンドメインはHTTPS接続可能なALBのドメインを指定してます。
作成方法は前回の記事をご参照ください

5.2Route53にCloudFrontドメインのレコードを追加する

CloudFrontドメインにHTTPS接続するためにRoute53にレコードを追加します。

5.3 稼動確認

CloudFrontの準備ができたので接続確認してみます。
繋がりませんでした...


実はこれALBのSGが原因です。
というわけでインバウンドルールを1つ追加します。
今回はCloudFrontのプレフィックスリストからのHTTPS接続を許可します。


今度は接続できました!!


6.CloudFront Functionsの構築

CloudFront経由の接続が確認できましたので、続いてCloudFront Functionsによるリダイレクトの設定を入れてみます。

本検証では以下のコードを使用します。

  function handler(event) {
    var request = event.request;
    var request_uri = request.uri;
    var redirect_URL ="";
    var xxx_ID = "";
    var searchString = "/beex-test/redirect_"
    
    //リクエストされたuriを出力
    console.log(request_uri);

    // beex-test/redirect_[XXX] に合致するか判定
    if (request_uri.includes(searchString)){
        console.log("beex-test/redirect_XXXの文字列を見つけました");
        xxx_ID = request_uri.substr(request_uri.indexOf('redirect_')+9);
        console.log(xxx_ID);
        
        // リダイレクト後のURLを構築
        redirect_URL = 'https://www.beex-inc.com/blog/lightsail_' + xxx_ID;
        
        console.log("リダイレクト後のURLはこちら")
        console.log(redirect_URL);

        return {
            statusCode: 302,
            statusDescription: 'Found',
            headers: {
                'location': {'value': redirect_URL}
                }
             };
    }else{
        console.log("redirect_XXXの文字列は見つかりませんでした");

        // リダイレクト後のURLを構築
        redirect_URL = 'https://www.beex-inc.com/blog' ;
        
        console.log("リダイレクト後のURIはこちら")
        console.log(redirect_URL);

        return {
            statusCode: 302,
            statusDescription: 'Found',
            headers: {
                'location': {'value': redirect_URL}
                }
             };
    }
    console.log(request);
    return request;
}

6.1 CloudFront Functionsの作成

関数にコードを記載して「変更を保存」をクリックします


6.2CloudFront Functionsのテスト

テストパターンに「/beex-test/redirect_[好きな文字]」を指定して実行してみてください
コード通りに動けばリダイレクトURL「https://www.beex-inc.com/blog/lightsail_' + [指定した値]」がログに出力されるはずです。


ログに出力されていることを確認できました!

次に、/redirect_XXXにマッチしないパターンも試してみます。
リダイレクトURL「https://www.beex-inc.com/blog/lightsail_' + [指定した値]」がログに出力されるはずです。

正しいリダイレクトURLがログに出力されました

6.3CloudFront Functionsの発行

稼動確認が取れたので関数を発行してCloudFrontで使用できるようにします。
「関数を発行」を選択すれば完了です。


7.CloudFrontリダイレクト設定の追加

CloudFront Functionsの作成が完了したので、パスパターンに関数を紐づけます。
/beex-test/ のパスパターンにマッチした場合にCloudFront Functionsを実行したいので
「パスパターン:beex-test/*」として作成し、関数はビューワーリクエストに紐づけます。


ビヘイビアの作成が完了したら接続し、テストで確認した通りにリダイレクトされるか確認します
https://beex-inc/com/blog/lightsail_XX にリダイレクトされれば成功です。

想定通りのURLにリダイレクトされてます!
コマンドでも確認してみました
redirect_03 の「03」の部分を抽出してリダイレクトできてそうです。


次に、/beex-test/にマッチするが、「redirect_XX」の条件にマッチしなかった場合を確認します。
「https://www.beex-inc.com/blog 」にリダイレクトされれば成功です。
うまくいってそうです!

念のためコマンドでも確認しておきます。

8.ALBのリダイレクト設定

CloudFrontのパスパターンにマッチしなかったものはデフォルトとしてALBにルーティングされます。
ALBではすべてのリクエストを「https://hrmos.co/pages/beex」にリダイレクトさせてみます。

8.1リダイレクト設定

HTTPSリスナールールのデフォルトルールを編集します。
アクションのルーティングで「URLにリダイレクト」を選択し、URLを記入します。

これでリダイレクトの設定は完了です。接続して確認してみます。

8.2 ALBリダイレクト稼働確認

「/beex-test/*」にマッチしないパスで接続してみます。
全てが「https://hrmos.co/pages/beex」にリダイレクトされればOKです

コマンドでも確認します。


ALBにルーティングされ、デフォルトルールによってリダイレクトされていることが確認できました!!

9.さいごに

ちょっと長くなりましたが、ALBとCloudFrontを使ったりリダイレクトの解説、実装をやってみました。
本記事内でALBのSGにCloudFrontのプレフィックスリストを追加しましたが、実はこれって問題点があります。

CloudFront→ALBの構成にした場合、ALBが受け取るIPアドレスはCloudFrontのものになります。
そのため、プレフィックスリストでCloudFront経由の接続を許可してしまうと、ALBのSGでIPを制限していても通信ができてしまうため、ALBのSGの意味がなくなってしまいます。

次回はこの構成にIPアドレス制限を加えるためWAFを使ってみます。
単純にルール追加すればいいかと思っていたのですが、意外な落とし穴があったのでそれも紹介してみようと思います。

最後まで読んでいただきありがとうございました!


カテゴリー
タグ

この記事を書いたメンバー

SAPシステムや基幹システムのクラウド移行・構築・保守、
DXに関して
お気軽にご相談ください

03-6260-6240 (受付時間 平日9:30〜18:00)