# 機能設計書 79-Azure Cloud Shell接続

## 概要

本ドキュメントは、Windows TerminalにおけるAzure Cloud Shell接続機能の設計を記述する。Azure Cloud Shellへの認証・接続・通信を管理する接続レイヤーである。

### 本機能の処理概要

AzureConnectionは、Azure Cloud Shellサービスへの接続を管理するクラスである。デバイスフローによるAzure AD認証、テナント選択、Cloud Shellインスタンスの作成、WebSocket経由のターミナル通信を一連のフローとして実装する。

**業務上の目的・背景**：Azure Cloud Shellはブラウザベースのシェル環境だが、Windows Terminal内から直接アクセスできるようにすることで、ローカルターミナルとクラウドシェルをシームレスに切り替えて使用できる。Azure リソースの管理作業を効率化する。

**機能の利用シーン**：Azure リソースの管理をターミナルから直接行いたい場合、ブラウザを開かずにCloud Shellにアクセスしたい場合に利用される。Azure CLIやPowerShellベースのCloud Shellが利用可能。

**主要な処理内容**：
1. Azure AD デバイスフロー認証
2. テナント選択（複数テナント所属時）
3. アクセストークンの取得と管理
4. Cloud Shell インスタンスの作成
5. WebSocket 接続によるターミナル通信
6. トークンのWindows資格情報ボールト保存

**関連システム・外部連携**：Azure AD（認証）、Azure Cloud Shell REST API、WebSocket（WinHTTP）、Windows資格情報マネージャー。

**権限による制御**：Azure ADアカウントへの認証が必要。テナントへのアクセス権限が必要。AzureClientIDが設定されていない場合（ローカルビルド）は接続不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | TermControl（ターミナル表示） | 主画面 | Azure Cloud Shellからの入出力表示 |

## 機能種別

接続管理 / 認証 / クラウド連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| initialRows | uint32_t | Yes | 初期行数 | 正の整数 |
| initialCols | uint32_t | Yes | 初期列数 | 正の整数 |
| sessionId | guid | No | セッションGUID（未指定時は自動生成） | 有効なGUID |

### 入力データソース

プロファイル設定（Azure Cloud Shellプロファイル）、Azure AD認証情報、ユーザーのインタラクティブ入力（テナント選択等）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| TerminalOutput | イベント | Cloud Shellからの出力（VTシーケンスを含む） |
| ConnectionState | ConnectionState | 接続状態 |

### 出力先

TerminalOutputイベント経由でTerminalControlへ

## 処理フロー

### 処理シーケンス

```
1. AzureConnection 作成と初期化
   └─ Initialize(settings) でパラメータ設定
2. Start() によるステートマシン開始
   └─ HTTPクライアント作成、出力スレッド開始
3. AccessStored 状態
   └─ 保存済みトークンの確認と検証
4. DeviceFlow 状態（トークンなしの場合）
   └─ Azure AD デバイスフロー認証
5. TenantChoice 状態
   └─ テナント一覧取得とユーザー選択
6. StoreTokens 状態
   └─ トークンをWindows資格情報ボールトに保存
7. TermConnecting 状態
   └─ Cloud Shellインスタンス作成、WebSocket接続
8. TermConnected 状態
   └─ WebSocket経由の双方向通信
```

### フローチャート

```mermaid
flowchart TD
    A[AzureConnection Start] --> B[AccessStored]
    B --> C{保存トークンあり?}
    C -->|Yes| D{トークン有効?}
    C -->|No| E[DeviceFlow]
    D -->|Yes| F[TenantChoice]
    D -->|No| G[トークンリフレッシュ]
    G --> F
    E --> H[デバイスコード表示]
    H --> I[ユーザー認証待ち]
    I --> F
    F --> J{複数テナント?}
    J -->|Yes| K[テナント選択UI]
    J -->|No| L[唯一のテナント使用]
    K --> M[StoreTokens]
    L --> M
    M --> N[TermConnecting]
    N --> O[Cloud Shell作成]
    O --> P[WebSocket接続]
    P --> Q[TermConnected]
    Q --> R{入出力}
    R -->|入力| S[WebSocket送信]
    R -->|出力| T[TerminalOutput発行]
    S --> R
    T --> R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-79-01 | クライアントID検証 | AzureClientID != "0" の場合のみ接続可能 | IsAzureConnectionAvailable() |
| BR-79-02 | トークン有効期限 | トークンの残り有効期間が2700秒未満の場合はリフレッシュ | _expireLimit定数 |
| BR-79-03 | 資格情報保存 | トークンをWindows資格情報ボールトに保存 | StoreTokens状態 |
| BR-79-04 | カラー表示 | ユーザー入力部分は黄色（93）、情報は白色（97）で表示 | USER_INPUT_COLOR, USER_INFO_COLOR |
| BR-79-05 | WebSocket通信 | WebSocket接続確立後はUTF-8バッファで通信 | TermConnected状態 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

本機能にデータベース操作はない。ただし、Windows資格情報ボールトをトークン保存に使用する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | クライアントID未設定 | ローカルビルドでAzureClientIDが"0" | IsAzureConnectionAvailable()がfalseを返す |
| - | 認証失敗 | デバイスフロー認証のタイムアウトまたは拒否 | _WriteCaughtExceptionRecordでエラー表示 |
| - | テナント取得失敗 | Azure AD APIエラー | 例外をキャッチしてエラーメッセージ表示 |
| - | WebSocket接続失敗 | ネットワークエラー | 接続をCloseする |
| - | Cloud Shell作成失敗 | Azure APIエラー | 例外メッセージを表示 |

### リトライ仕様

デバイスフロー認証ではポーリング間隔（pollInterval）で自動リトライされる。その他のエラーでは手動での接続再起動が必要。

## トランザクション仕様

本機能にデータベーストランザクションはない。認証フローはステートマシンにより管理され、各状態遷移は順次実行される。

## パフォーマンス要件

WebSocket通信はリアルタイム性が求められる。出力スレッドは専用スレッドで実行される。HTTP通信はAzure APIの応答時間に依存する。

## セキュリティ考慮事項

- アクセストークンとリフレッシュトークンはWindows資格情報ボールトに暗号化保存される
- HTTPクライアントのUser-Agentは"Mozilla/5.0 (Windows NT 10.0) Terminal/1.0"に設定
- WebSocket通信はHTTPS経由で暗号化される
- デバイスフロー認証により、ターミナル自体にパスワードは入力されない

## 備考

- AzureClientIDはリリースパイプラインでのみ設定される（ローカルビルドでは"0"）
- 接続タイプGUID: {d9fcfdfa-a479-412c-83b7-c5640e61cd62}
- 資格情報ボールトのリソース名: "Terminal"
- Cloud Shell REST APIバージョン: 2019-01-01

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AzureConnection.h | `src/cascadia/TerminalConnection/AzureConnection.h` | AzureState列挙型（35-43行目）: 6つの状態定義。_accessToken, _refreshToken, _cloudShellUri, _terminalID等のメンバー |
| 1-2 | AzureClient.h | `src/cascadia/TerminalConnection/AzureClient.h` | Azure::Tenant構造体、APIクライアント定義 |

**読解のコツ**: AzureConnectionは状態遷移マシンとして実装されている。AzureState列挙型の各状態に対応する_Run*Stateメソッドが存在する。InputModeは認証フロー中のユーザー入力モードを管理する。

#### Step 2: 初期化と認証フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AzureConnection.cpp | `src/cascadia/TerminalConnection/AzureConnection.cpp` | Initialize（78-91行目）、Start（132-158行目）、_OutputThread、各_Run*Stateメソッド |

**主要処理フロー**:
1. **65-76行目**: ConnectionType()/IsAzureConnectionAvailable() - 接続タイプGUIDとクライアントID検証
2. **78-91行目**: Initialize - パラメータ設定
3. **132-158行目**: Start - HTTPクライアント作成、出力スレッド開始
4. **160-187行目**: _ReadUserInput - ユーザー入力の待機（mutex/condition_variable）
5. **194-243行目**: WriteInput/_writeInput - 状態に応じた入力処理

#### Step 3: WebSocket通信を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AzureConnection.cpp | `src/cascadia/TerminalConnection/AzureConnection.cpp` | Resize（250-273行目）、Close（278-299行目） |

**主要処理フロー**:
- **250-273行目**: Resize - WebSocket接続後はREST APIでサイズ変更
- **278-299行目**: Close - WebSocketクローズ、出力スレッド待機

### プログラム呼び出し階層図

```
AzureConnection::Start (AzureConnection.cpp:132)
    │
    └─ _OutputThread()
           │
           ├─ _RunAccessState()    [保存トークン確認]
           │      └─ _StoreCredential() / _RemoveCredentials()
           │
           ├─ _RunDeviceFlowState()  [デバイスフロー認証]
           │      ├─ _GetDeviceCode()
           │      └─ _WaitForUser()
           │
           ├─ _RunTenantChoiceState()  [テナント選択]
           │      ├─ _PopulateTenantList()
           │      └─ _ReadUserInput(Line)
           │
           ├─ _RunStoreState()  [トークン保存]
           │      └─ _StoreCredential()
           │
           └─ _RunConnectState()  [Cloud Shell接続]
                  ├─ _GetCloudShellUserSettings()
                  ├─ _GetCloudShell()
                  ├─ _GetTerminal()
                  └─ WinHttpWebSocketReceive() [通信ループ]
```

### データフロー図

```
[入力]                         [処理]                          [出力]

Azure AD認証 ──────────────▶ デバイスフロー認証
(デバイスコード)                    │
                                   ▼
テナント選択 ──────────────▶ テナント一覧取得
(ユーザー入力)                     │
                                   ▼
                            Cloud Shell作成
                                   │
                                   ▼
ユーザー入力 ──────────────▶ WinHttpWebSocketSend ──▶ Cloud Shell
                                                          │
                                                          ▼
                            WinHttpWebSocketReceive ◀── Cloud Shell出力
                                   │
                                   ▼
                            TerminalOutput ──────────▶ TermControl
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AzureConnection.h | `src/cascadia/TerminalConnection/AzureConnection.h` | ヘッダー | AzureConnectionクラス定義 |
| AzureConnection.cpp | `src/cascadia/TerminalConnection/AzureConnection.cpp` | ソース | Azure接続実装 |
| AzureConnection.idl | `src/cascadia/TerminalConnection/AzureConnection.idl` | IDL | WinRTインターフェース定義 |
| AzureClient.h | `src/cascadia/TerminalConnection/AzureClient.h` | ヘッダー | AzureクライアントAPI |
| AzureClientID.h | `src/cascadia/TerminalConnection/AzureClientID.h` | ヘッダー | Azure クライアントID定義 |
| BaseTerminalConnection.h | `src/cascadia/TerminalConnection/BaseTerminalConnection.h` | ヘッダー | 基底接続クラス |
| AzureCloudShellGenerator.cpp | `src/cascadia/TerminalSettingsModel/AzureCloudShellGenerator.cpp` | ソース | Azure Cloud Shellプロファイル自動生成 |
