# 機能設計書 85-アイデンティティ管理

## 概要

本ドキュメントは、OpenSearchにおけるユーザー・サブジェクトの認証・識別を行うアイデンティティ管理機能の設計を記述する。

### 本機能の処理概要

IdentityServiceを中心としたユーザー・プロセス・デバイスの識別と認証基盤である。IdentityPluginインターフェースを通じてSubject（主体）の管理、TokenManager（トークン管理）、PluginSubject（プラグイン用主体）の機能を提供する。デフォルトではNoopIdentityPluginが使用され、セキュリティプラグインにより認証機能が拡張される。

**業務上の目的・背景**：OpenSearchクラスタへのアクセス制御の基盤として、誰が（Subject）どのような権限で操作を行っているかを識別する必要がある。本機能はその識別・認証の共通フレームワークを提供する。

**機能の利用シーン**：ユーザーリクエストの認証処理、プラグインの識別とアクセス制御、On Behalf Ofトークンの発行、サービスアカウントトークンの発行。

**主要な処理内容**：
1. IdentityPluginの初期化（0個の場合はNoopIdentityPlugin、1個のみ許可）
2. getCurrentSubject()で現在のリクエスト主体（Subject）の取得
3. getTokenManager()でトークン管理機能の取得
4. initializeIdentityAwarePlugins()でIdentityAwarePluginへのSubject割り当て

**関連システム・外部連携**：セキュリティプラグイン（IdentityPlugin実装）、IdentityAwarePlugin（アイデンティティ情報を利用するプラグイン）。

**権限による制御**：Subject.runAs()により、別のSubjectとして処理を実行する機能を提供。Principalを通じてアプリケーション全体で一意な識別子を取得。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は内部API基盤であり、直接的なREST APIエンドポイントを持たない |

## 機能種別

セキュリティ基盤 / 認証・識別

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| settings | Settings | Yes | OpenSearch設定 | - |
| threadPool | ThreadPool | Yes | スレッドプール | - |
| identityPlugins | List<IdentityPlugin> | Yes | IdentityPlugin実装のリスト | 2つ以上でOpenSearchException |

### 入力データソース

- ノード起動時のプラグインロード結果
- リクエストコンテキスト（認証トークン等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Subject | Subject | 現在のリクエスト主体 |
| TokenManager | TokenManager | トークン管理インスタンス |
| PluginSubject | PluginSubject | プラグイン用主体 |
| AuthToken | AuthToken | 発行されたトークン |

### 出力先

各サブシステム（認証チェック、プラグインアクセス制御等）に提供される。

## 処理フロー

### 処理シーケンス

```
1. IdentityService初期化
   └─ IdentityPluginが0個ならNoopIdentityPlugin、1個ならそのプラグイン、2つ以上はエラー
2. getCurrentSubject()
   └─ IdentityPlugin.getCurrentSubject()に委譲
3. getTokenManager()
   └─ IdentityPlugin.getTokenManager()に委譲
4. initializeIdentityAwarePlugins()
   └─ 各IdentityAwarePluginに対してPluginSubjectを割り当て
```

### フローチャート

```mermaid
flowchart TD
    A[ノード起動] --> B[IdentityService初期化]
    B --> C{IdentityPlugin数}
    C -->|0| D[NoopIdentityPlugin使用]
    C -->|1| E[指定プラグイン使用]
    C -->|2+| F[OpenSearchException]
    D --> G[IdentityService準備完了]
    E --> G
    G --> H[initializeIdentityAwarePlugins]
    H --> I[各プラグインにPluginSubject割当]
    J[リクエスト受信] --> K[getCurrentSubject]
    K --> L[Subject返却]
    M[トークン要求] --> N[getTokenManager]
    N --> O[TokenManager返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | IdentityPlugin単一制約 | IdentityPluginは0個（Noop）または1個のみ許可 | 初期化時 |
| BR-02 | Noop デフォルト | IdentityPluginが未設定の場合はNoopIdentityPluginが使用される | IdentityPlugin数=0時 |
| BR-03 | Subject一意性 | SubjectはPrincipalを通じてアプリケーション全体で一意に識別される | Subject.getPrincipal() |
| BR-04 | runAs委譲 | Subject.runAs()はデフォルトではCheckedRunnableをそのまま実行する | Subject.runAs()デフォルト実装 |

### 計算ロジック

特になし。

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

本機能はデータベースを直接操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 500 | OpenSearchException | IdentityPluginが2つ以上 | セキュリティプラグインを1つのみにする |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

IdentityServiceは軽量なファサードであり、実際の認証処理はIdentityPlugin実装に委譲されるため、オーバーヘッドは最小限。

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

- 本機能自体がセキュリティ基盤である
- @ExperimentalApiアノテーションにより実験的APIとして提供（Subject, TokenManager）
- @InternalApiアノテーションによりIdentityServiceは内部API
- NoopIdentityPluginは認証を行わないため、本番環境ではセキュリティプラグインの導入が必須
- OnBehalfOfClaimsによる委任トークンの発行機能

## 備考

本機能はOpenSearch 2.x系で導入された実験的な機能である。@ExperimentalApiアノテーションが付与されており、将来のバージョンでAPIが変更される可能性がある。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Subject.java | `server/src/main/java/org/opensearch/identity/Subject.java` | @ExperimentalApi。getPrincipal()とrunAs()の2メソッド。runAs()のデフォルト実装はそのまま実行 |
| 1-2 | TokenManager.java | `server/src/main/java/org/opensearch/identity/tokens/TokenManager.java` | @ExperimentalApi。issueOnBehalfOfToken()とissueServiceAccountToken()の2メソッド |
| 1-3 | AuthToken.java | `server/src/main/java/org/opensearch/identity/tokens/AuthToken.java` | トークンの基本インターフェース |
| 1-4 | NamedPrincipal.java | `server/src/main/java/org/opensearch/identity/NamedPrincipal.java` | 名前付きPrincipal実装 |

**読解のコツ**: Subject, TokenManagerは@ExperimentalApiで実験的API。将来変更の可能性あり。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IdentityService.java | `server/src/main/java/org/opensearch/identity/IdentityService.java` | @InternalApi。コンストラクタ（35-49行目）でIdentityPlugin初期化ロジック |

**主要処理フロー**:
1. **38-40行目**: IdentityPlugin数0でNoopIdentityPlugin
2. **41-43行目**: IdentityPlugin数1で指定プラグイン使用
3. **44-48行目**: IdentityPlugin数2以上でOpenSearchException
4. **55-57行目**: getCurrentSubject()で委譲
5. **62-64行目**: getTokenManager()で委譲
6. **66-73行目**: initializeIdentityAwarePlugins()で各プラグインにSubject割当

#### Step 3: Noop実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NoopIdentityPlugin.java | `server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java` | デフォルトの無操作IdentityPlugin実装 |
| 3-2 | NoopSubject.java | `server/src/main/java/org/opensearch/identity/noop/NoopSubject.java` | 認証を行わないSubject実装 |
| 3-3 | NoopTokenManager.java | `server/src/main/java/org/opensearch/identity/noop/NoopTokenManager.java` | 無操作のTokenManager実装 |

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

```
Node起動
    |
    +-- IdentityService(settings, threadPool, identityPlugins)
            |
            +-- identityPlugin.getCurrentSubject()
            |       +-- NoopSubject / 実プラグインSubject
            |
            +-- identityPlugin.getTokenManager()
            |       +-- NoopTokenManager / 実プラグインTokenManager
            |               +-- issueOnBehalfOfToken(subject, claims)
            |               +-- issueServiceAccountToken(audience)
            |
            +-- initializeIdentityAwarePlugins(plugins)
                    +-- identityPlugin.getPluginSubject(plugin)
                    +-- plugin.assignSubject(pluginSubject)
```

### データフロー図

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

IdentityPlugin(s) ─────> IdentityService
                              |
リクエスト ──────────────> getCurrentSubject() ────────> Subject
                              |                          (Principal)
トークン要求 ─────────> getTokenManager()
                              +-- issueOnBehalfOfToken ──> AuthToken
                              +-- issueServiceAccountToken > AuthToken

IdentityAwarePlugin ──> initializeIdentityAwarePlugins
                              +-- getPluginSubject ──────> PluginSubject
                              +-- assignSubject ──────────> プラグインに割当
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IdentityService.java | `server/src/main/java/org/opensearch/identity/IdentityService.java` | ソース | アイデンティティサービス本体 |
| Subject.java | `server/src/main/java/org/opensearch/identity/Subject.java` | ソース | 主体インターフェース |
| UserSubject.java | `server/src/main/java/org/opensearch/identity/UserSubject.java` | ソース | ユーザー主体 |
| PluginSubject.java | `server/src/main/java/org/opensearch/identity/PluginSubject.java` | ソース | プラグイン主体インターフェース |
| NamedPrincipal.java | `server/src/main/java/org/opensearch/identity/NamedPrincipal.java` | ソース | 名前付きPrincipal |
| TokenManager.java | `server/src/main/java/org/opensearch/identity/tokens/TokenManager.java` | ソース | トークン管理インターフェース |
| AuthToken.java | `server/src/main/java/org/opensearch/identity/tokens/AuthToken.java` | ソース | 認証トークンインターフェース |
| BasicAuthToken.java | `server/src/main/java/org/opensearch/identity/tokens/BasicAuthToken.java` | ソース | Basic認証トークン |
| BearerAuthToken.java | `server/src/main/java/org/opensearch/identity/tokens/BearerAuthToken.java` | ソース | Bearerトークン |
| OnBehalfOfClaims.java | `server/src/main/java/org/opensearch/identity/tokens/OnBehalfOfClaims.java` | ソース | OBO トークンのクレーム |
| NoopIdentityPlugin.java | `server/src/main/java/org/opensearch/identity/noop/NoopIdentityPlugin.java` | ソース | デフォルトNoop実装 |
| NoopSubject.java | `server/src/main/java/org/opensearch/identity/noop/NoopSubject.java` | ソース | Noop Subject |
| NoopTokenManager.java | `server/src/main/java/org/opensearch/identity/noop/NoopTokenManager.java` | ソース | Noop TokenManager |
| NoopPluginSubject.java | `server/src/main/java/org/opensearch/identity/noop/NoopPluginSubject.java` | ソース | Noop PluginSubject |
