Amazon ECS で動作する OpenAI Realtime API を使った ChatBot を ロードバランサー で TLS 対応にする

# 1. はじめに

Amazon ECS を利用して OpenAI の Realtime API（WebSocket）を動作させ、ALB を使って TLS（WSS）対応した セキュアな WebSocket チャットボットを構築する。

前回の記事では [Amazon ECS で OpenAI Realtime API (WebSocket) を使った ChatBot を構築](https://qiita.com/rairaii/items/0c2518a2b3e0060d4c42)した。この ChatBot に対して **テキスト** だけではなく **音声** で会話ができるように拡張する。

ところで、**ChatBot** の **Webブラウザで動作するサンプルアプリケーション** が音声入出力をサポートしたい場合に、Webブラウザは **ChatBotサーバーとの接続にHTTPS/WSS（TLS）接続** を要求する。これは、マイクなどのデバイスを安全に利用するためのセキュリティ要件になっている。

Webブラウザは、マイクを利用するWebアプリに対し、以下の条件を求める。

- **HTTPS（TLS）接続で配信されていること**
- **信頼できる認証機関（CA）発行の証明書を使用していること（自己署名証明書は不可）**

これを満たさない場合、ブラウザはマイクの利用を許可しない


そこで、今回は **ChatBot サーバー** を ALB（Application Load Balancer）を使って WebSocket の TLS（WSS）に対応させる。



# 2. ALB を使って TLS をサポートする理由

ALB を使うことで、TLS 証明書の管理が容易になり、負荷分散やスケーリングが簡単になる。AWS Certificate Manager（ACM）を利用すれば、証明書の取得や更新が自動化され、運用負担を大幅に軽減できる。

また、ALB は複数の ECS タスクにリクエストを分散できるため、負荷分散が自動で行われ、トラフィックの急増にも対応しやすくなる。スケールアウト時も ALB が新規タスクに自動でルーティングするため、手動で設定を変更する必要がない。

一方、ECS 内で TLS を処理する場合、各コンテナで個別に証明書を管理する必要があり、手動更新や設定変更の手間が増えます。スケール時には新たにデプロイされるタスクごとに証明書を適用する必要があり、管理が煩雑になりがちです。特に大規模環境では、証明書管理の負担とスケーリングの課題から ALB の利用したほうがよい。

# 3. システム構成

- クライアントから WebSocket/TLS（WSS）で ALB に接続
- ALB から WebSocket (WS) で ECS に接続
- ECS から WebSocket/TLS (WSS) で OpenAI に接続

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/2aaa4171-9a46-4f9e-acb1-b727e13f62cd.png)



# 4. 必要な AWS リソース

| サービス・機能 | 役割・説明 |
|--------------|-----------|
| **Amazon ECS（Fargate）** | ChatBot を動作させる |
| **Application Load Balancer（ALB）** | WebSocket（WSS）経由の通信を処理 |
| **AWS Certificate Manager（ACM）** | TLS（SSL）証明書を取得し ALB に適用 |
| **Amazon Route 53** | カスタムドメインで WebSocket にアクセスする場合に必要 |






# 5. ChatBot を ALB で TLS (WSS) に対応させる

前回の記事の **4. Amazon ECSで ChatBot の Docker を起動する** の [**(2) タスク定義を作成**](https://qiita.com/rairaii/items/0c2518a2b3e0060d4c42#2-%E3%82%BF%E3%82%B9%E3%82%AF%E5%AE%9A%E7%BE%A9%E3%82%92%E4%BD%9C%E6%88%90) まで作業を進めたあと、次のようなステップで TLS (WSS) に対応する。

1. Amazon Route 53 でドメインを取得 (有料)
2. AWS Certificate Manager（ACM）で証明書を発行（無料） 
3. Application Load Balancer（ALB）に証明書を適用
3. ALB に Route 53 で取得したドメインを設定する

https://qiita.com/rairaii/items/0c2518a2b3e0060d4c42#4-amazon-ecs%E3%81%A7-chatbot-%E3%81%AE-docker-%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B


## (1) Route 53 でドメインを取得

[Route 53 のコンソール](https://us-east-1.console.aws.amazon.com/route53/) でドメインを取得する。Route 53 でのドメインの取得方法は下記の記事を参考に実施すれば良い。

https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/registrar.html

https://qiita.com/mksamba/items/e50a423b8ab12271eb73



## (2) AWS Certificate Manager (ACM) で証明書を作成する

[ACM のコンソール](https://us-east-1.console.aws.amazon.com/acm) で証明書をリクエストする。証明書の発行はこちらのサイトの通り行えば良い。AWS Certificate Manager (ACM) を通じてプロビジョニングされたパブリック SSL/TLS 証明書は無料だ。

https://zenn.dev/mn87/articles/90609fffd8c634


## (3) ALB に TLS（WSS）対応を設定

[Amazon ECS](https://us-east-1.console.aws.amazon.com/ecs) のコンソールでクラスタにサービスを作成する

1. **[クラスター]** のページで **[作成したクラスタ名]** を選択する
1. **[サービス]** の **[作成]** を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/fc7305ff-cd91-4d9f-bec4-caef2ac36aa4.png)

**[作成]** のページが開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/aaa5b021-0757-423b-995c-1ef1891f0a03.png)

1. **[デプロイ設定]** までスクロール
1. **[ファミリー]** と **[リビジョン]** であらかじめ作成しておいたタスクを設定する
1. **[サービス名]** を設定する (任意の名称)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/63077532-4ec5-421e-840c-514ed6ed1fa4.png)




1. **[ロードバランシング]** までスクロール
1. **[ロードバランサー名]** を設定する  (任意の名称)
1. **[リスナー]** の **[ポート]** に 443 を設定する
1. **[リスナー]** の **[プロトコル]** に HTTPS を設定する
1. **[リスナー]** の **[証明書]** に **ACM 証明書から選択** を選択し、 **ACM で作成しておいた証明書** を選択する
1. 一番下までスクロールして **[作成]** ボタンを選択肢サービスを作成する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/49ec4f89-30f3-4f60-b363-93bc6262edae.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/6ba28768-dfff-4522-a2cb-2f2114871c2f.png)




## (4) ALB に Route 53 で取得したドメインを設定する

サービスを作成すると、ALBには独自のDNS名が設定される。例えば、先ほど作成したALBのDNS名を確認するには次のコマンドを実行する

```bash
aws elbv2 describe-load-balancers --names "<your_alb_name>" --query 'LoadBalancers[0].DNSName' --output text
```


```bash:出力例
xxxxx-xxxxxxxx-xxxx-xxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com
```

このままの状態では、証明書に設定されたドメイン名とALBのDNS名が異なるため、エラーが発生する。

```bash
wscat -c xxxxx-xxxxxxxx-xxxx-xxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com
```
```bash:エラー例
error: Hostname/IP does not match certificate's altnames: Host: xxxxx-xxxxxxxx-xxxx-xxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com. is not in the cert's altnames: DNS:xxx-xxxxxx-xxxxxxxxxx.com, DNS:*.xxx-xxxxxx-xxxxxxxxxx.com
```

この問題を解決するため、**Route 53** を使用して独自ドメインをALBに割り当てる。


1. [**Route 53** のコンソール](https://us-east-1.console.aws.amazon.com/route53) を開く
1. **[レコード作成]** ボタンを選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/3e056132-ba48-4fd3-960f-0f03d01358de.png)

1. **[レコードを作成]**　ページに移動する
1. **[レコード名]** を設定する (任意の名称)
1. **[エイリアス]** を Enable にする
1. **[トラフィックのルーティング先]** に ALB と ALBを作成したリージョン を設定する
1. **[ロードバランサー]** を設定する
1. **[レコードを作成]** を選択する


この手順で設定した **レコード名** がDNSに登録され、そのドメイン名を使ってALBにアクセスできるようになります。




# 5. クライアントから WSS で接続して動作確認

##  wscat で動作確認

テキストで ChatBot と会話できることを確かめた

```bash
wscat  -c wss://<your_chatbot_domain_name>/ws
```
```bash:出力例
Connected (press CTRL+C to quit)
> Hi ChatGPT
< Hello! How can I assist you today?
> What is AWS?
< AWS, or Amazon Web Services, is a comprehensive cloud computing platform provided by Amazon. It offers a range of services including computing power, storage, databases, machine learning, analytics, and more, enabling businesses to deploy and manage applications and infrastructure in the cloud.
```

## Webブラウザ で動作確認

音声で ChatBot と会話できることを確かめた

Webブラウザで **`https://<your_chatbot_domain_name>`** に接続すると下記のUIが表示される。
**[Start Audio]** を選択すると、音声で **ChatBot** と会話ができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017489/c4b704a2-8cf0-46d4-aff3-e45ac793b791.png)



# 参考サイト

https://qiita.com/ksawada1979/items/90de16b5622ab04e19f3