【イチから学ぶ! 初めての Azure と生成 AI】Azure App Service / Container Apps を用いた生成AIアプリケーション開発 - 安全なコード実行編

# はじめに

本記事は、【イチから学ぶ! 初めての Azure と生成 AI】セミナーのセッション『AI アプリのクラウド運用入門 ～App Service と Container Apps の選び方と管理のポイント』の解説記事です。

Azure を活用した生成 AI アプリケーション開発の際に役立つポイントをご紹介します。実装時に直面しがちなハマりどころやその解決策を、全 5 回に分けてお届けします。

本記事では、AI が生成したコードを安全に実行する方法についてご紹介します。

本記事でご紹介するサンプルアプリケーションのソースコードは、以下のリポジトリで公開しています。

https://github.com/kohei3110/azure-101-day

# AI が生成したコードを隔離した環境で実行する

AI が生成したコードは、必ずしも安全とは言い切れません。例えば、生成したコードで使用しているライブラリに脆弱性が含まれている可能性は否定できません。

よって、実開発においては、「メインアプリケーションと隔離されたサンドボックス環境」を用意し、その環境の中で AI が生成したコードを実行するアプローチを取ることも選択肢に入れる必要があります。

Azure の場合、Container Apps で「動的セッション」という機能が用意されており、これを使うことで AI が生成したコードを実行するためのサンドボックス環境を一時的に払い出すことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/289eb36b-0173-416b-b894-832a398920c2.png)

https://learn.microsoft.com/ja-jp/azure/container-apps/sessions?tabs=azure-cli

# Container Apps 動的セッションでコードを実行する方法

上図にある通り、Container Apps 動的セッションの実体は、Hyper-V サンドボックス環境です。このサンドボックス環境は、「動的」という名の通り、Container Apps によって一時的に払い出され、割り当てが完了すると削除されるものです。

予め「セッションプール」が内部的に用意されており、REST API を通じて Container Apps 動的セッションに対してセッション割り当てリクエストが送信されると、プールからセッションが割り当てられます。マネージドサービスなので、開発者側で割り当て・削除等のセッション管理を行う必要はありません。

## セッションの種類

セッションには２種類あり、Microsoft がマネージドで提供する `コードインタープリター`、開発者がランタイム・処理内容をカスタマイズする `カスタムコンテナー` です。

| 種類 | 概要 | 課金モデル |
|:-|:-|:-|
| コードインタープリター  | フルマネージドなコード インタープリター。アプリケーションのユーザーによって提供されるコードや、大規模言語モデル (LLM) によって生成されたコードなど、信頼されないコードを実行するのに最適。  |  セッションごと (従量課金) | 
| カスタムコンテナー   |  独自のコンテナーを使用。既定ではサポートされていない言語のカスタム コード インタープリターの実行や、強力な分離を必要とするワークロードの実行を想定。 |  Container Apps 専用プラン |

いずれの場合も、アプリケーションから Container Apps 動的セッションへのリクエストは、HTTP リクエストを通じて行われます。カスタムコンテナーの場合、REST API 等でエンドポイントを作成しておく必要があります。

## Container Apps 動的セッションリソースの作成

2025年2月27日時点では、Azure CLI 経由でのみContainer Apps 動的セッションリソースの作成が可能です。

```shell
az containerapp sessionpool create \
    --name my-session-pool \
    --resource-group <RESOURCE_GROUP> \
    --location westus2 \
    --container-type PythonLTS \
    --max-sessions 100 \
    --cooldown-period 300 \
    --network-status EgressEnabled
```

リソースを作成すると、プレイグラウンドで動的セッションの検証を行うこともできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/4766f26b-12e8-488a-9009-cb7ed9a25258.png)


https://learn.microsoft.com/ja-jp/azure/container-apps/sessions-code-interpreter#create-a-session-pool-with-azure-cli

## 呼び出しコード例

以下は、コードインタープリターセッションを例として解説します。

なお、LangChain、LlamaIndex、Semantic Kernel を使って実装しているアプリケーションの場合、公開されているパッケージを使って実装する方法が一番手っ取り早いです。

- LangChain: https://pypi.org/project/langchain-azure-dynamic-sessions/
- LlamaIndex: https://pypi.org/project/llama-index-tools-azure-code-interpreter/
- Semantic Kernel: https://pypi.org/project/semantic-kernel/

今回は、上記のフレームワークを使わずに、素で実装することで、内部の挙動をより詳細に把握します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/b85e0243-94e0-4cc1-b326-1acf9709c13b.png)

先ほど、「アプリケーションから Container Apps 動的セッションへのリクエストは、HTTP リクエストを通じて行われる」と記載しました。つまり、Web API へのリクエストを送るための認証情報（アクセストークン）を取得する必要があります。
Container Apps 動的セッションの場合、Entra ID から取得したトークンをもとに、Container Apps 動的セッションの呼び出しに必要なアクセストークンを取得します。

まず、セッション プール上の Azure ContainerApps Session Executor および "共同作成者" ロールに属する ID を持つエンティティ（マネージド ID など）で、Entra ID に対して認証します。

```python
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
```

次に、Entra ID から払い出された資格情報を使って、'https://dynamicsessions.io/.default` にアクセストークン取得リクエストを送信します。

```python
token = credential.get_token("https://dynamicsessions.io/.default")
access_token = token.token
```

ここで得られた `access_token` を `Authorization` ヘッダに、実行したいコードをリクエストボディにセットして、Container Apps 動的セッションに対して HTTP リクエストを送信することにより、Container Apps 動的セッションを使用することができます。

```python
url = f"{base_url}/code/execute?api-version=2024-02-02-preview&identifier={session_id}"
headers = {
    "Authorization": f"Bearer {access_token}",
    "Content-Type": "application/json"
}
payload = {
    "properties": {
        "codeInputType": "inline",
        "executionType": "synchronous",
        "code": code
    }
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
```

余談ですが、ここで得られたアクセストークン（JWT）の有効期限は既定で60分です。アクセストークンを https://jwt.ms/ を使って確認してみると、トークンには、値 `https://dynamicsessions.io` を持つ対象者 (`aud`) クレームが含まれていることもわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248756/3edc0ac4-313b-42bd-a206-0cd527a1f696.png)


https://learn.microsoft.com/ja-jp/azure/container-apps/sessions-code-interpreter#authentication

https://github.com/kohei3110/azure-101-day/blob/main/app/backend/api/src/repositories/dynamic_sessions_repository.py

# おわりに

本記事では、Azure の Container Apps を活用して、AI が生成したコードを安全に実行するためのサンドボックス環境を構築する方法について解説しました。

動的セッション機能を利用することで、Hyper-V サンドボックス上に一時的な実行環境を払い出し、メインアプリケーションから分離された状態で AI コードを実行できる点が大きなメリットとなります。

今回ご紹介した構成例では、セッションプールの作成、Entra ID を用いたアクセストークンの取得、HTTP リクエストを通じたコード実行のプロセスなど、具体的な手順を示しました。これにより、生成されたコードが安全な環境内で実行され、予期せぬ脆弱性やリスクを回避できるようになります。

また、Azure Container Apps の動的セッションは、サンドボックス環境を柔軟かつ自動的に管理するため、開発者は複雑なセッション管理の負担から解放され、アプリケーション開発に専念できる点も魅力です。今後、さらなるセキュリティ強化や運用自動化の取り組みを通じて、より高品質な生成 AI アプリケーションの運用が実現されることが期待されます。

ぜひ本記事を参考に、安全かつ効率的な AI コード実行環境の構築に挑戦し、運用の最適化を図ってください。