# 機能設計書 607-New-DbaDbEncryptionKey

## 概要

本ドキュメントは、Transparent Data Encryption（TDE）用のデータベース暗号化キーを作成する`New-DbaDbEncryptionKey`機能の設計書である。

### 本機能の処理概要

`New-DbaDbEncryptionKey`は、masterデータベースの証明書または非対称キーを使用して、Transparent Data Encryptionに必要なデータベース暗号化キー（DEK）を作成する機能である。これは、データベースでTDEを有効にする前に不可欠な最初のステップである。この機能は、暗号化キーを作成する前に証明書がバックアップされていることを自動的に検証し、潜在的なデータ損失シナリオを防止する。

**業務上の目的・背景**：TDEは、データベースファイル（データファイル、ログファイル、バックアップファイル）を暗号化することで、物理的なメディア盗難やバックアップファイルの不正アクセスからデータを保護する。データベース暗号化キー（DEK）は対称キーで、masterデータベースの証明書または非対称キーで保護される。本機能は、TDE実装の自動化を支援し、証明書バックアップの検証により運用上のミスを防止する。

**機能の利用シーン**：
- TDE実装のためのデータベース準備
- コンプライアンス要件（PCI-DSS、HIPAA等）への対応
- 機密データを含むデータベースのセキュリティ強化
- 複数データベースへのTDE一括適用

**主要な処理内容**：
1. ターゲットデータベースへの接続（Get-DbaDatabase経由）
2. 既存のDEK存在チェック
3. 暗号化証明書/非対称キーの自動選択または指定値の使用
4. 証明書バックアップ状態の検証（Forceフラグがない場合）
5. SMO DatabaseEncryptionKeyオブジェクトの作成と設定
6. DEKの作成と結果取得

**関連システム・外部連携**：SQL Server SMO、SQL Server暗号化階層（TDE）

**権限による制御**：データベースに対するCONTROL権限、masterデータベースの証明書/非対称キーへのアクセス権が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | なし | - | CLIベースの機能のため関連画面なし |

## 機能種別

オブジェクト作成（INSERT相当） / TDE暗号化キー管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No | ターゲットSQL Serverインスタンス | なし |
| SqlCredential | PSCredential | No | SQL Server接続用の代替資格情報 | なし |
| Database | String[] | No | DEKを作成するデータベース（デフォルト: master） | なし |
| EncryptorName | String | No | masterデータベースの証明書または非対称キー名 | なし |
| Type | String | No | 暗号化子の種類（デフォルト: Certificate） | Certificate, AsymmetricKey |
| EncryptionAlgorithm | String | No | 暗号化アルゴリズム（デフォルト: Aes256） | Aes128, Aes192, Aes256, TripleDes |
| InputObject | Database[] | No | Get-DbaDatabase からパイプライン入力 | なし |
| Force | Switch | No | 証明書バックアップ検証をバイパス | なし |
| EnableException | Switch | No | 例外処理の有効化フラグ | なし |

### 入力データソース

- SQL Server SMO
- masterデータベースの証明書または非対称キー

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | String | SQL Serverインスタンスのコンピュータ名 |
| InstanceName | String | SQL Serverインスタンス名 |
| SqlInstance | String | 完全なSQL Serverインスタンス名（コンピュータ\インスタンス形式） |
| Database | String | DEKが作成されたデータベース名 |
| CreateDate | DateTime | DEKの作成日時 |
| EncryptionAlgorithm | String | 使用された暗号化アルゴリズム |
| EncryptionState | String | 暗号化状態（Encrypted, EncryptionInProgress等） |
| EncryptionType | String | 暗号化子タイプ（ServerCertificate, ServerAsymmetricKey） |
| EncryptorName | String | 保護に使用された証明書/非対称キー名 |
| ModifyDate | DateTime | DEKの最終更新日時 |
| OpenedDate | DateTime | DEKが最後に開かれた日時 |
| RegenerateDate | DateTime | DEKが最後に再生成された日時 |
| SetDate | DateTime | DEKが最後に設定された日時 |
| Thumbprint | String | 証明書のサムプリント |

### 出力先

PowerShellパイプライン（Microsoft.SqlServer.Management.Smo.DatabaseEncryptionKey オブジェクト）

## 処理フロー

### 処理シーケンス

```
1. 各InputObject（データベース）に対して処理（processブロック）
   ├─ SqlInstanceが指定された場合はGet-DbaDatabase で取得
   ├─ HasDatabaseEncryptionKeyで既存DEKチェック
   ├─ EncryptorName未指定時
   │   ├─ Type = Certificate: masterの証明書を自動選択
   │   └─ Type = AsymmetricKey: masterの非対称キーを自動選択
   ├─ 証明書バックアップ状態検証（Type = Certificateの場合）
   │   ├─ LastBackupDate.Year == 1 かつ Force未指定: エラー
   │   └─ Force指定時: 証明書が存在しない場合は自動作成
   ├─ SMO DatabaseEncryptionKeyオブジェクトの作成と構成
   └─ Create()でDEKを作成し、Get-DbaDbEncryptionKeyで結果取得
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[データベースループ開始]
    B --> C{既存DEK存在?}
    C -->|存在| D[エラー出力してスキップ]
    C -->|存在しない| E{EncryptorName指定?}
    E -->|No| F{Type = Certificate?}
    F -->|Yes| G[masterの証明書を自動選択]
    G --> H{証明書数}
    H -->|0| I[エラー: 証明書なし]
    H -->|2以上| J[エラー: 名前指定必要]
    H -->|1| K[自動選択完了]
    F -->|No| L[masterの非対称キーを選択]
    L --> M{非対称キー存在?}
    M -->|No| N[エラー: キーなし]
    M -->|Yes| O[自動選択完了]
    E -->|Yes| P[指定名を使用]
    K --> Q{LastBackupDate検証}
    O --> R[DEK作成処理]
    P --> Q
    Q --> S{バックアップ済み?}
    S -->|No| T{Force指定?}
    T -->|No| U[エラー: バックアップ必要]
    T -->|Yes| V{証明書存在?}
    V -->|No| W[証明書を自動作成]
    V -->|Yes| R
    W --> R
    S -->|Yes| R
    R --> X[SMO DatabaseEncryptionKey作成]
    X --> Y[プロパティ設定]
    Y --> Z[Create実行]
    Z --> AA[Get-DbaDbEncryptionKey]
    AA --> AB{次のデータベース?}
    D --> AB
    I --> AB
    J --> AB
    N --> AB
    U --> AB
    AB -->|Yes| B
    AB -->|No| AC[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-607-01 | デフォルトデータベース | Database未指定時はmasterを使用 | Database未指定時 |
| BR-607-02 | デフォルト暗号化子タイプ | Type未指定時はCertificateを使用 | Type未指定時 |
| BR-607-03 | デフォルトアルゴリズム | EncryptionAlgorithm未指定時はAes256を使用 | EncryptionAlgorithm未指定時 |
| BR-607-04 | 既存DEK禁止 | データベースに既にDEKが存在する場合はエラー | 常時 |
| BR-607-05 | 証明書自動選択 | EncryptorName未指定でType=Certificateの場合、masterに1つだけ非システム証明書が必要 | EncryptorName未指定時 |
| BR-607-06 | 証明書バックアップ検証 | 証明書のLastBackupDateが未設定の場合、Forceなしではエラー | Type=Certificate時 |
| BR-607-07 | 証明書自動作成 | Force指定時、指定された証明書が存在しない場合は自動作成 | Force指定時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| DEK作成 | sys.dm_database_encryption_keys | INSERT | データベース暗号化キーの作成 |

### テーブル別操作詳細

#### sys.dm_database_encryption_keys

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | database_id | 対象データベースのID | システムにより設定 |
| INSERT | encryption_algorithm | 指定されたアルゴリズム | AES_128, AES_192, AES_256, TRIPLE_DES_3KEY |
| INSERT | encryption_state | 暗号化状態 | 作成直後は1（Unencrypted） |
| INSERT | encryptor_type | 暗号化子タイプ | CERTIFICATE, ASYMMETRIC KEY |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 既存DEKエラー | データベースに既にDEKが存在 | 既存DEKを削除するか別のデータベースを指定 |
| - | 証明書なしエラー | masterに使用可能な証明書がない | 証明書を作成（New-DbaDbCertificate） |
| - | 証明書複数エラー | masterに複数の証明書が存在 | EncryptorNameで証明書名を指定 |
| - | 非対称キーなしエラー | masterに使用可能な非対称キーがない | 非対称キーを作成（New-DbaDbAsymmetricKey） |
| - | バックアップ未実施エラー | 証明書がバックアップされていない | 証明書をバックアップするか-Forceを使用 |
| - | 作成失敗 | SMO操作でエラー発生 | エラーメッセージを確認 |

### リトライ仕様

特になし

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

SMOによるDEK作成は暗黙のトランザクション内で実行される

## パフォーマンス要件

特に規定なし

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

- データベースに対するCONTROL権限が必要
- masterデータベースの証明書/非対称キーへのアクセス権が必要
- 証明書のバックアップを確実に行い、安全に保管することが重要（バックアップなしでは復旧不可）
- Forceフラグは開発環境でのみ使用を推奨
- Aes256が最も強力な暗号化を提供し、本番環境で推奨
- TripleDesはレガシーであり、新規実装には推奨されない

## 備考

- DEK作成後、ALTER DATABASE ... SET ENCRYPTION ON でTDEを有効にする
- 非対称キーはEKM（Extensible Key Management）プロバイダー（Azure Key Vault、HSM等）と組み合わせて使用
- 証明書バックアップの重要性：バックアップなしでは暗号化されたデータベースを復元できない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | New-DbaDbEncryptionKey.ps1 | `public/New-DbaDbEncryptionKey.ps1` | 65-86行目のコメントで出力オブジェクト（DatabaseEncryptionKey）の構造を確認 |
| 1-2 | New-DbaDbEncryptionKey.ps1 | `public/New-DbaDbEncryptionKey.ps1` | 106-121行目のparamブロックで入力パラメータ定義を確認 |

**読解のコツ**: Get-DbaDbEncryptionKeyを呼び出して結果を取得している点に注目。DEK作成後のRefresh処理も重要。

#### Step 2: processブロックの主処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | New-DbaDbEncryptionKey.ps1 | `public/New-DbaDbEncryptionKey.ps1` | 122-197行目で暗号化キー作成処理を確認 |

**主要処理フロー**:
- **127-129行目**: 既存DEKの存在チェック（HasDatabaseEncryptionKey）
- **132-152行目**: EncryptorName未指定時の自動選択ロジック
- **156-167行目**: 証明書バックアップ検証とForce時の自動作成
- **175-181行目**: SMO DatabaseEncryptionKeyオブジェクトの作成と設定
- **182-188行目**: Refresh処理と結果取得

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

```
New-DbaDbEncryptionKey
    │
    └─ [process]
        │
        ├─ Get-DbaDatabase (SqlInstance指定時)
        │      └─ 対象データベースオブジェクトの取得
        │
        ├─ $db.HasDatabaseEncryptionKey
        │      └─ 既存DEKの存在確認
        │
        ├─ Get-DbaDbCertificate (Type = Certificate時)
        │      └─ master内の証明書取得/選択
        │
        ├─ Get-DbaDbAsymmetricKey (Type = AsymmetricKey時)
        │      └─ master内の非対称キー取得/選択
        │
        ├─ New-DbaDbCertificate (Force指定時、証明書自動作成)
        │      └─ 証明書の自動生成
        │
        ├─ Microsoft.SqlServer.Management.Smo.DatabaseEncryptionKey
        │      └─ SMOオブジェクト作成
        │
        ├─ DatabaseEncryptionKey.Create()
        │      └─ DEK作成実行
        │
        └─ Get-DbaDbEncryptionKey
               └─ 作成結果の取得
```

### データフロー図

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

SqlInstance ───────▶ Get-DbaDatabase ──────────▶ Databaseオブジェクト
      │                  │
Database ─┼──────────────┘
      │
      │                  ▼
      │          HasDatabaseEncryptionKey チェック
      │                  │
EncryptorName ──────────▶ 暗号化子選択
      │                  │     ├─ Get-DbaDbCertificate
Type ──────────────────┘     └─ Get-DbaDbAsymmetricKey
      │                        │
      │                        ▼
      │               証明書バックアップ検証
      │                        │
Force ────────────────────────▶│
      │                        │
EncryptionAlgorithm ──────────▶ SMO DatabaseEncryptionKey
      │                        │
      │                        ▼
      │                  Create()
      │                        │
      │                        ▼
      │                  Get-DbaDbEncryptionKey
      │                        │
      └──────────────────────▶ DatabaseEncryptionKey出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| New-DbaDbEncryptionKey.ps1 | `public/New-DbaDbEncryptionKey.ps1` | ソース | メイン機能実装 |
| Get-DbaDatabase.ps1 | `public/Get-DbaDatabase.ps1` | ソース | データベースオブジェクト取得 |
| Get-DbaDbCertificate.ps1 | `public/Get-DbaDbCertificate.ps1` | ソース | 証明書取得 |
| Get-DbaDbAsymmetricKey.ps1 | `public/Get-DbaDbAsymmetricKey.ps1` | ソース | 非対称キー取得 |
| New-DbaDbCertificate.ps1 | `public/New-DbaDbCertificate.ps1` | ソース | 証明書自動作成（Force時） |
| Get-DbaDbEncryptionKey.ps1 | `public/Get-DbaDbEncryptionKey.ps1` | ソース | 作成結果取得 |
| Test-Bound.ps1 | `private/functions/Test-Bound.ps1` | ソース | パラメータバインド状態確認 |
