# 機能設計書 84-KMS暗号化

## 概要

本ドキュメントは、AWS KMSを利用した暗号化キー管理プラグイン（crypto-kms）の設計を記述する。

### 本機能の処理概要

crypto-kmsプラグインは、AWS Key Management Service（KMS）をマスターキープロバイダとして使用し、データ暗号化キーの生成・管理を行うCryptoKeyProviderPlugin実装である。CryptoHandlerRegistryと連携してEncryptedBlobStoreでの暗号化・復号化操作に必要なマスターキーを提供する。

**業務上の目的・背景**：クラウド環境でのデータ暗号化において、マスターキーの安全な管理はセキュリティの要である。AWS KMSを使用することで、マスターキーをAWSのマネージドサービスで管理し、キーのローテーションやアクセス制御をAWS IAMと統合できる。

**機能の利用シーン**：AWS環境でのOpenSearchクラスタにおいて、リモートストアやスナップショットデータをクライアントサイド暗号化する際に使用する。

**主要な処理内容**：
1. AWS KMSクライアントの構築（認証情報、リージョン、エンドポイント設定）
2. MasterKeyProviderの生成（KMS Key ARNと暗号化コンテキストの設定）
3. KMSクライアントのキャッシュ管理とリフレッシュ
4. セキュア設定のリロード対応

**関連システム・外部連携**：AWS KMS API、AWS IAM（認証）、CryptoHandlerRegistry（暗号化基盤）。

**権限による制御**：AWS IAM認証情報（アクセスキー、シークレットキー、セッショントークン）による認証。KMS Key ARNに対するkms:Encrypt/kms:Decrypt権限が必要。

## 関連画面

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

## 機能種別

データ連携 / セキュリティ / 外部API連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| kms.key_arn | String | Yes | AWS KMSのキーARN | 空文字でIllegalArgumentException |
| kms.encryption_context | String | No | 暗号化コンテキスト（Name1=Value1,Name2=Value2形式） | 不正形式でIllegalArgumentException |
| access_key | SecureSetting | No | AWSアクセスキー | - |
| secret_key | SecureSetting | No | AWSシークレットキー | - |
| session_token | SecureSetting | No | AWSセッショントークン | - |
| endpoint | String | No | KMSエンドポイントURL | - |
| region | String | No | AWSリージョン | - |
| proxy_host | String | No | プロキシホスト | - |
| proxy_port | int | No | プロキシポート | - |
| read_timeout | Duration | No | 読み取りタイムアウト | - |

### 入力データソース

- OpenSearchのセキュア設定（opensearch.yml / keystore）
- CryptoMetadataのsettings

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| MasterKeyProvider | MasterKeyProvider | KMSベースのマスターキープロバイダ |
| KmsClient | KmsClient | AWS KMSクライアント（内部使用） |

### 出力先

CryptoHandlerRegistryを経由してCryptoHandlerに提供される。

## 処理フロー

### 処理シーケンス

```
1. プラグイン初期化
   └─ CryptoKmsPlugin(settings)でKmsServiceを初期化し、クライアント設定をロード
2. MasterKeyProvider生成要求
   └─ createKeyProvider(cryptoMetadata)
       └─ KmsService.createMasterKeyProvider(cryptoMetadata)
3. KMS設定解決
   └─ CryptoMetadataのsettingsをkms.プレフィックスで正規化
4. Key ARN取得
   └─ kms.key_arn設定から取得（必須）
5. 暗号化コンテキスト解析
   └─ kms.encryption_contextをカンマ区切りで解析
6. KMSクライアント生成
   └─ client(cryptoMetadata)でキャッシュ付きKMSクライアントを取得
7. KmsMasterKeyProvider返却
   └─ 暗号化コンテキスト、Key ARN、クライアントサプライヤを含む
```

### フローチャート

```mermaid
flowchart TD
    A[createKeyProvider要求] --> B[CryptoMetadataからsettings取得]
    B --> C[kms.プレフィックスで正規化]
    C --> D{key_arn設定あり?}
    D -->|No| E[IllegalArgumentException]
    D -->|Yes| F[encryption_context解析]
    F --> G[KMSクライアント生成/キャッシュ取得]
    G --> H[クライアント接続テスト]
    H --> I[KmsMasterKeyProvider生成]
    I --> J[返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | Key ARN必須 | kms.key_arn設定は必須 | createMasterKeyProvider時 |
| BR-02 | 暗号化コンテキスト形式 | Name1=Value1,Name2=Value2のカンマ区切り | encryption_context設定時 |
| BR-03 | クライアントキャッシュ | 同一KmsClientSettingsに対するクライアントはキャッシュされる | client()呼出時 |
| BR-04 | リトライポリシー | KMS APIコールは最大10回リトライ | buildRetryPolicy() |
| BR-05 | プロバイダ名 | type()は"aws-kms"を返す | CryptoKeyProviderPlugin.type() |

### 計算ロジック

特になし。暗号化・復号化の計算はAWS KMS APIに委譲される。

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

本機能はデータベースを直接操作しない。AWS KMS APIを呼び出してキー操作を行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IllegalArgumentException | key_arn設定が未設定 | CryptoMetadata設定にkey_arnを追加 |
| - | IllegalArgumentException | encryption_contextの形式不正 | Name=Value形式で設定 |
| - | SdkException | KMSクライアント構築失敗（認証エラー等） | AWS認証情報を確認 |
| - | SdkException | プロキシURL不正 | プロキシ設定を確認 |

### リトライ仕様

AWS SDK v2のRetryPolicyにより最大10回のリトライが設定される（147-148行目）。TokenBucketRetryConditionにより連続失敗時はリトライが制限される。

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

KMSクライアントキャッシュの更新はsynchronizedブロックで排他制御される。

## パフォーマンス要件

KMSクライアントはclientsCacheにキャッシュされ、同一設定でのクライアント再生成を回避する。参照カウント（tryIncRef/incRef/decRef）によりクライアントの安全なライフサイクル管理が行われる。

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

- AWS認証情報はSecureSettingとして管理され、keystoreに保存される
- SpecialPermission.check()によるセキュリティマネージャチェック
- AccessController.doPrivilegedでAWS SDK呼び出しを実行
- デフォルトAWSプロファイルパスをOpenSearch設定ディレクトリに制限（setDefaultAwsProfilePath）
- ReloadablePluginインターフェースでセキュア設定のホットリロードに対応

## 備考

本プラグインはCryptoKeyProviderPlugin実装であり、暗号化の具体的な実装はCryptoPluginが提供する。KMSはマスターキーの管理のみを行う。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | KmsClientSettings.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/KmsClientSettings.java` | AWS認証情報・リージョン・エンドポイント等の設定をまとめたデータクラス |
| 1-2 | AmazonKmsClientReference.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/AmazonKmsClientReference.java` | 参照カウント付きKMSクライアントラッパー |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CryptoKmsPlugin.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/CryptoKmsPlugin.java` | PROVIDER_NAME="aws-kms"。createKeyProvider()（49-51行目）でKmsService.createMasterKeyProviderに委譲 |

**主要処理フロー**:
1. **37-46行目**: コンストラクタでKmsServiceを初期化し、reload()で設定ロード
2. **49-51行目**: createKeyProvider()でMasterKeyProvider生成
3. **59-73行目**: getSettings()でセキュア設定一覧を定義
4. **77-81行目**: reload()でクライアントキャッシュのリフレッシュ

#### Step 3: KMSサービスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | KmsService.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/KmsService.java` | createMasterKeyProvider()（245-272行目）がメイン処理。client()（156-176行目）でキャッシュ付きクライアント取得 |

**主要処理フロー**:
- **245-272行目**: createMasterKeyProvider - settings正規化、key_arn取得、暗号化コンテキスト解析、KmsMasterKeyProvider返却
- **73-118行目**: buildClient - KMSクライアントの構築（認証、リトライ、プロキシ設定）
- **156-176行目**: client - synchronizedでキャッシュ付きクライアント取得
- **208-214行目**: refreshAndClearCache - キャッシュクリアと設定更新

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

```
CryptoKmsPlugin
    |
    +-- createKeyProvider(cryptoMetadata)
    |       +-- KmsService.createMasterKeyProvider(cryptoMetadata)
    |               +-- settings(cryptoMetadata) [設定解決]
    |               +-- client(cryptoMetadata) [クライアント取得]
    |               |       +-- buildClient(clientSettings)
    |               |               +-- buildCredentials()
    |               |               +-- buildOverrideConfiguration()
    |               |               +-- buildProxyConfiguration()
    |               +-- KmsMasterKeyProvider(encCtx, keyArn, clientSupplier)
    |
    +-- reload(settings)
            +-- KmsClientSettings.getClientSettings(settings)
            +-- KmsService.refreshAndClearCache(clientSettings)
```

### データフロー図

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

opensearch.yml ──────────> CryptoKmsPlugin
  + keystore                    |
                            KmsService
CryptoMetadata ──────────>   |
  (key_arn,                  +-- buildClient() ──────> KmsClient
   encryption_context)       +-- createMasterKeyProvider()
                                    |
                                    v
                             KmsMasterKeyProvider ──────> CryptoHandlerRegistry
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CryptoKmsPlugin.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/CryptoKmsPlugin.java` | ソース | プラグインエントリーポイント |
| KmsService.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/KmsService.java` | ソース | KMSクライアント管理・MasterKeyProvider生成 |
| KmsClientSettings.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/KmsClientSettings.java` | ソース | KMSクライアント設定データクラス |
| KmsMasterKeyProvider.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/KmsMasterKeyProvider.java` | ソース | KMSベースのMasterKeyProvider実装 |
| AmazonKmsClientReference.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/AmazonKmsClientReference.java` | ソース | 参照カウント付きKMSクライアント |
| CredentialProviderFactory.java | `plugins/crypto-kms/src/main/java/org/opensearch/crypto/kms/CredentialProviderFactory.java` | ソース | AWS認証プロバイダファクトリ |
