[実践]CloudFront Functionsによるドメインリダイレクト

![001samune.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/9469f8b2-76d5-4214-9962-48eecfa11ed6.png)

# 概要
こちらの記事でAWSサービスを使ったドメインリダイレクト手法についてまとめました。
その中でCloudFront関連の方法を試していこうと思い記事にします。
今回は「CloudFront Functions」編です。

https://qiita.com/tyskJ/items/b0070eeeaa42813c3867

# 実践
### 構成図
* CloudFrontに代替ドメインでアクセス
* ビューワーリクエストに対してCloudFront Functionsで処理(後述)
* 特定のPathの場合にリダイレクト先のALBにリクエストを転送
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/f4d28a21-4db1-4f21-9f24-92f896006d7e.png)



### デプロイ
環境はGitHubで公開しています。
各コードとデプロイ方法を用意してますのでお試しください。

https://github.com/tyskJ/aws-cloudfront-functions-redirect


### 設定値
各ポイントとなる設定値を見ていきます。

#### CloudFront
##### ディストリビューションに代替ドメインを設定
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/d833653b-6041-477a-a809-526ab7e79df3.png)

##### オリジンはS3のリージョナルエンドポイント(REST API Endpoint)
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/d4658053-cad1-41bb-9549-9ed22c8829a6.png)

##### S3オリジンにOAC(Origin Access Control)を設定
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/a1f38420-d96e-42c9-8b75-73977c1b22a6.png)

##### デフォルトビヘイビアのビューワーリクエストにFunctionsを適用
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/6bd35e7f-c90d-4f62-881e-c58c44ed92a7.png)

##### Functionsコード
リクエストのURI(Path)が「/test1/」or「/test2/」の場合に、ALBに設定した独自ドメインにリダイレクトさせるコードです。

```javascript
function handler(event) {
  var request = event.request;
  var uri = request.uri;
  var newurl = `https://${リダイレクト先FQDN}/`;

  // Check uri
  if (uri === "/test1/") {
    newurl = `https://${リダイレクト先FQDN}/test1/`;
  }
  // Check uri
  else if (uri === "/test2/") {
    newurl = `https://${リダイレクト先FQDN}/test2/`;
  } else {
    return request;
  }
  var response = {
    statusCode: 301,
    statusDescription: "Moved Permanently",
    headers: {
      location: {
        value: newurl,
      },
    },
  };
  return response;
}
```

#### S3
##### バケットポリシーにCloudFront OACからのアクセス許可を追加

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::バケット名/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::アカウントID:distribution/ディストリビューションID"
                }
            }
        }
    ]
}
```

### 動作確認
まず、Functionsコードの条件にマッチしないリクエストを呼び出してみます。
ディストリビューションに設定したデフォルトルートオブジェクト(S3バケットにホストしたindex.html)がレスポンスとして返ってきます。

```shell-session
[cloudshell-user@ip-10-134-11-96 ~]$ curl -i https://ディストリビューション代替ドメイン/
HTTP/2 200 
content-type: application/octet-stream
content-length: 316
date: Mon, 10 Mar 2025 13:22:16 GMT
last-modified: Mon, 10 Mar 2025 12:50:35 GMT
etag: "0b51ba8caa5af4d214532a9912de1e23"
x-amz-server-side-encryption: AES256
accept-ranges: bytes
server: AmazonS3
x-cache: Miss from cloudfront
via: 1.1 6149f46c7356f1b6aa240cc7ba3d1060.cloudfront.net (CloudFront)
x-amz-cf-pop: NRT20-P1
x-amz-cf-id: MiduRvjAEhWmOJsnnIF3mWjekZN6Dty1F0fpQmBdU6_y_ja3JyVurw==

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>S3</title>
  </head>
  <body>
    <h1>S3 Default Page!</h1>
    <p>このページは S3 にホストされています。</p>
  </body>
</html>
```

続いて、Functionsコードの条件分岐にマッチするリクエストを送信してみます。

```shell-session
[cloudshell-user@ip-10-134-11-96 ~]$ curl -i -L https://ディストリビューション代替ドメイン/test1/
HTTP/2 301 
server: CloudFront
date: Mon, 10 Mar 2025 13:29:10 GMT
content-length: 0
location: https://リダイレクト先ドメイン/test1/
x-cache: FunctionGeneratedResponse from cloudfront
via: 1.1 829875449fd9f82be120d1fdf955d186.cloudfront.net (CloudFront)
x-amz-cf-pop: NRT20-P1
x-amz-cf-id: N9NH_JO3A9bCB_pqYfR40d-MxYi3ATFLsP0XfUi4r4GtNzAa7_y4Lg==

HTTP/2 200 
date: Mon, 10 Mar 2025 13:29:10 GMT
content-type: text/html; charset=UTF-8
content-length: 232
server: Apache/2.4.62 (Amazon Linux)
last-modified: Mon, 10 Mar 2025 12:52:26 GMT
etag: "e8-62ffc71bcbfa9"
accept-ranges: bytes

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>EC2</title>
</head>
<body>
    <h1>Web Server Test1 Page!</h1>
</body>
</html>
```

# まとめ
今回は「CloudFront Functions」を試してみました。
「CloudFront+S3リダイレクト機能」と比較し、セキュアに実装できる点はメリットだなと感じました。
次回は「CloudFront+Lambda@Edge」編を記事にしたいと思います。