CloudRunのカスタムドメインとCloudflareでオリジンを保護する方法

- この記事は、 [Cloudflare Advent Calendar 2023](https://qiita.com/advent-calendar/2023/cloudflare) 11日目の記事です。

# はじめに
- Google CloudのサービスであるCloud Runは、サーバーレスアーキテクチャを提供し、コンテナ化されたアプリケーションを簡単かつ柔軟にデプロイできる素晴らしいプラットフォームです。
- Cloud Runでは通常、GCPのロードバランサを使用する構成が一般的ですが、Cloudflareを使用することでコストメリットがあるだけでなくCloudflareのセキュリティメリットを享受することが可能です。
- Cloud Runのカスタムドメインを設定し、Cloudflareを利用してオリジンを保護する方法を残しておきます。

### ※注意点
- Cloud Runのカスタムドメインマッピングは現時点でプレビューとなっております。
- この内容をそのまま本番のサービスには適用しないでください。
https://cloud.google.com/run/docs/mapping-custom-domains?hl=ja
- カスタムドメインを設定してもCloud RunのデフォルトのURLは生きたままになります。

# 1. Cloud Runへのアプリケーションのデプロイ
まず初めに、Cloud Runにアプリケーションをデプロイします。
このステップでは、Google Cloud Consoleを使用して、Cloud Runサービスにアプリケーションをデプロイします。

簡単なFlaskのアプリケーションをデプロイしましょう。

```app.py
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0', port=8080)
```
Dockerfileも準備しておきましょう。
```Dockerfile
FROM python:slim

ADD app.py .
RUN pip install flask

CMD ["python3", "app.py"]
```

デプロイはこれだけです。簡単ですね。
```bash
gcloud run deploy [Cloud Runサービス名] --source .
```
※CLIのバージョン456.0.0を使用している場合、Cloud Buildで`
(gcloud.run.deploy) FAILED_PRECONDITION: failed precondition: due to quota restrictions, cannot run builds in this region. Please contact support
`というエラーが出ます。 455.0.0に戻すことで正常に実行可能です。

- デプロイされたらCloud RunのURLが表示されるので、正常にアクセスできることを確認しましょう。

# 2. カスタムドメインの設定
ここからが本番ですね。
アプリケーションにカスタムドメインを設定します。以下の手順に従ってください。

- Cloud Runのコンソールに移動します。
- 「カスタム ドメインを管理」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/243654fd-c474-3dc2-ee62-67b83e86477c.png)
- 「マッピングを追加」をクリックします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/606689f0-2fec-8d83-23f9-aaa1fff28a91.png)
- 先ほど作成したCloud Runサービスを選択します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/61504021-30ef-9e9e-2953-c7af4d6fe3a0.png)
- Cloud Runのドメインマッピングを選択します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/996cd09b-1db8-5e21-74c5-a8eaa6bbfa7f.png)
- Google Cloudで検証させるドメインを指定します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/86e42f64-74da-0fe1-ba30-1752fc94d008.png)
- Cloud Runに割り当てるサブドメインを入力して続行します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/e6e49fba-b00d-eade-06a8-3f3a634150dc.png)


# 3. Cloudflareのセットアップ
アプリケーションのカスタムドメインが設定されたら、次にCloudflareを使用してオリジンを保護します。

- Cloudflareにサインアップまたはログインします。
- CloudflareのDNSに先ほど割り当てたサブドメインをCNAMEレコードで追加します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/94c0d4b0-37f1-9e0d-d9ab-3323dfd40165.png)
    ※SSL 証明書のプロビジョニングには通常 15 分ほどかかりますが、場合によっては最長で 24 時間ほどかかることがあります。

- DNS設定が確認されたら、Cloudflareのダッシュボードで「SSL/TLS」セクションに移動し、「SSL/TLSの設定」を「完全（Full）」に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33070/8265dac9-34ee-fe28-11d3-b04b37bbb460.png)

同じセクションで、「常にHTTPSを使用する」を「オン」に設定します。

# 4. セキュリティの向上
アプリケーションがセキュリティで保護されるようになりましたが、さらなるセキュリティ向上のために、Cloudflareの「ページ ルール」を使用してセキュリティポリシーを設定することも検討するとよさそうですね。
たとえば、特定のパスに対してアクセス制限をかけたり、セキュリティヘッダーを追加したりできます。

# 5. 残念な点
カスタムドメインを設定してもCloud RunのデフォルトのURLは生きたままになります。
直接アクセスされると意味がないので、コンテナ内のアプリケーション自体に認証機能を持たせたり、カスタムヘッダで簡易的にCloudflareとCloud Run間を認証するなどの工夫は必要となります。

オリジンの保護については、６日の@kanishさんの記事が大変勉強になるのでぜひご覧ください！
https://qiita.com/kanish/items/906adcab92088f29681e

# まとめ
これで、Cloud Runのカスタムドメイン機能とCloudflareを使用して、アプリケーションのオリジンをセキュアに保つ方法を学びました。
現段階ではプレビュー機能ですが、GAの際は選択肢の一つとなると思うので、ぜひ今のうちに試してみてください。