# 機能設計書 46-Restore-DbaDbCertificate

## 概要

本ドキュメントは、.cerおよび.pvkファイルからSQL Serverデータベースに証明書をリストアするdbatools PowerShellコマンド `Restore-DbaDbCertificate` の機能設計書である。

### 本機能の処理概要

この機能は、データベース証明書とその関連秘密鍵をバックアップファイルからSQL Serverデータベースにリストアする。TDE（Transparent Data Encryption）、バックアップ暗号化、Always Encrypted、その他のSQL Serverセキュリティ機能で使用される証明書の復旧に不可欠である。

**業務上の目的・背景**：データベースマイグレーション、災害復旧、サーバー再構築後に、暗号化に使用される証明書を復元する必要がある。証明書がないとTDE暗号化されたデータベースのリストアや、暗号化されたバックアップの復号ができない。

**機能の利用シーン**：
- TDE暗号化データベースの別サーバーへのリストア準備
- 災害復旧時の証明書復元
- サーバー移行時の証明書移行
- 暗号化バックアップの復号準備

**主要な処理内容**：
1. 証明書ファイル（.cer）のパス検証
2. 秘密鍵ファイル（.pvk）の自動検出または明示的指定
3. 証明書名の決定（ファイル名からの派生またはName指定）
4. SMO Certificate.Create()による証明書作成
5. 秘密鍵の復号とオプションの再暗号化

**関連システム・外部連携**：ファイルシステム上の証明書ファイル（.cer, .pvk）

**権限による制御**：対象データベースでのCREATE CERTIFICATE権限、masterデータベースの場合はCONTROL DATABASE権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIベースのセキュリティ管理コマンド |

## 機能種別

証明書リストア / セキュリティ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter | Yes | リストア先SQL Serverインスタンス | - |
| SqlCredential | PSCredential | No | 代替認証情報 | - |
| Path | string[] | Yes | 証明書ファイル（.cer）パスまたはディレクトリ | パイプライン入力可能 |
| KeyFilePath | string[] | No | 秘密鍵ファイル（.pvk）パス | 未指定時は自動検出 |
| DecryptionPassword | SecureString | Yes* | 秘密鍵復号パスワード | *未指定時はプロンプト |
| EncryptionPassword | SecureString | No | 新しい秘密鍵暗号化パスワード | - |
| Database | string | No | リストア先データベース。デフォルト: master | - |
| Name | string | No | 証明書名の明示指定 | - |
| EnableException | switch | No | 例外を有効にするスイッチ | - |
| WhatIf | switch | No | 実行せずに何が起きるか表示 | - |
| Confirm | switch | No | 確認プロンプト表示 | - |

### 入力データソース

ファイルシステム（.cerおよび.pvkファイル）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なインスタンス名 |
| Database | string | 証明書が作成されたデータベース |
| Name | string | 証明書名 |
| Subject | string | 証明書のサブジェクト |
| StartDate | DateTime | 証明書有効開始日 |
| ActiveForServiceBrokerDialog | bool | Service Broker使用フラグ |
| ExpirationDate | DateTime | 証明書有効期限 |
| Issuer | string | 証明書発行者 |
| LastBackupDate | DateTime | 最終バックアップ日時 |
| Owner | string | 証明書所有者 |
| PrivateKeyEncryptionType | string | 秘密鍵暗号化タイプ |
| Serial | string | 証明書シリアル番号 |

### 出力先

PowerShellパイプライン（Microsoft.SqlServer.Management.Smo.Certificate）

## 処理フロー

### 処理シーケンス

```
1. SQL Server接続
   └─ Connect-DbaInstanceで接続確立
2. パス検証
   └─ Test-DbaPathでSQL Serverからのアクセス確認
3. ディレクトリ判定
   └─ xp_fileexistでディレクトリかファイルか判定
4. 証明書ファイル列挙
   └─ ディレクトリの場合はGet-DbaFileで.cerファイル取得
5. 各証明書ファイルを処理
   ├─ 秘密鍵ファイルパス決定
   ├─ 証明書名決定（タイムスタンプ除去等）
   └─ SMO Certificate.Create()実行
6. 結果取得
   └─ Get-DbaDbCertificateで作成済み証明書を取得
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Connect-DbaInstance]
    B --> C{接続成功?}
    C -->|No| D[Stop-Function]
    C -->|Yes| E[Test-DbaPath]
    E --> F{アクセス可能?}
    F -->|No| G[Stop-Function Continue]
    F -->|Yes| H{ディレクトリ?}
    H -->|Yes| I[Get-DbaFile .cer]
    H -->|No| J[単一ファイル処理]
    I --> K[各ファイルループ]
    J --> K
    K --> L{KeyFilePath指定?}
    L -->|No| M[同名.pvk自動検出]
    L -->|Yes| N[指定パス使用]
    M --> O[証明書名決定]
    N --> O
    O --> P[タイムスタンプ除去等]
    P --> Q{Name指定?}
    Q -->|Yes| R[指定名使用]
    Q -->|No| S[派生名使用]
    R --> T{ShouldProcess確認}
    S --> T
    T -->|No| K
    T -->|Yes| U[SMO Certificate作成]
    U --> V{EncryptionPassword?}
    V -->|Yes| W[新パスワードで暗号化]
    V -->|No| X[MasterKeyで暗号化]
    W --> Y[Get-DbaDbCertificate]
    X --> Y
    Y --> K
    K --> Z[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-46-01 | デフォルトデータベース | Database未指定時はmasterを使用 | Database未指定時 |
| BR-46-02 | 秘密鍵自動検出 | KeyFilePath未指定時は同名の.pvkを検索 | KeyFilePath未指定時 |
| BR-46-03 | 証明書名派生 | ファイル名からインスタンス/DB接頭辞とタイムスタンプを除去 | Name未指定時 |
| BR-46-04 | 秘密鍵暗号化 | EncryptionPassword未指定時はMasterKeyで暗号化 | EncryptionPassword未指定時 |

### 計算ロジック

**証明書名決定ロジック（163-175行目）**:
```powershell
$certname = $certname.Replace("$fileinstance-$Database-", "")
if ($certname -match "-$Database-") {
    $tempcertname = $certname -split "-" | Select-Object -First 1 -Skip 2
    if ($tempcertname) {
        $certname = $tempcertname
    }
}
# タイムスタンプパターン除去
if ($certname -match '([0-9]{4})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])(2[0-3]|[01][0-9])([0-5][0-9])([0-5][0-9])') {
    $certname = $certname.Replace($matches[0], "")
}
$certname = $certname.TrimEnd("-")
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 証明書作成 | sys.certificates | INSERT | 証明書メタデータ登録 |

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

#### sys.certificates

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name, subject, start_date, expiry_date等 | ファイルから読込 | SMO Certificate.Create経由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | SQL Serverへの接続失敗 | Stop-Functionで終了 |
| - | アクセスエラー | SQL Serverがファイルにアクセスできない | Stop-Function Continueで継続 |
| - | 作成エラー | 証明書作成失敗（権限不足等） | Stop-Function Continueで継続 |

### リトライ仕様

SMO Certificate.Create()が失敗した場合、異なるオーバーロード（CertificateSourceType指定）で再試行する（195-204行目）。

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

SMOのCertificate.Create()メソッド内部でトランザクション管理される。

## パフォーマンス要件

特になし。証明書は通常小さいファイルであり、パフォーマンス上の懸念は少ない。

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

- DecryptionPasswordはSecureString型で安全に扱われる
- EncryptionPasswordもSecureString型
- 秘密鍵ファイルはSQL Serverサービスアカウントがアクセス可能である必要がある
- ConfirmImpact = "High"で確認プロンプトがデフォルト表示

## 備考

- ConvertFrom-SecurePass内部関数で SecureString からプレーンテキストに変換（SMO APIが要求）
- Backup-DbaDbCertificateで作成されたファイル形式と互換性がある

---

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

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

### 推奨読解順序

#### Step 1: パラメータ定義を理解する

入力パラメータとエイリアスを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Restore-DbaDbCertificate.ps1 | `public/Restore-DbaDbCertificate.ps1` | 107-124行目のparam定義 |

**読解のコツ**: DecryptionPasswordはデフォルトでRead-Host -AsSecureStringを呼び出すため、実質必須。

#### Step 2: パス検証とディレクトリ処理を理解する

ファイルとディレクトリの処理分岐を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Restore-DbaDbCertificate.ps1 | `public/Restore-DbaDbCertificate.ps1` | 133-146行目 |

**主要処理フロー**:
- **134-136行目**: Test-DbaPathでアクセス確認
- **139行目**: xp_fileexistでディレクトリ判定
- **143-145行目**: ディレクトリの場合はGet-DbaFileで.cerファイル取得

#### Step 3: 秘密鍵検出と証明書名決定を理解する

自動検出ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Restore-DbaDbCertificate.ps1 | `public/Restore-DbaDbCertificate.ps1` | 148-180行目 |

**主要処理フロー**:
- **156-160行目**: KeyFilePath未指定時の.pvk自動検出
- **162-175行目**: 証明書名からインスタンス/DB接頭辞とタイムスタンプ除去
- **176-180行目**: Name指定時はそちらを優先

#### Step 4: 証明書作成処理を理解する

SMO Certificate.Create()の呼び出しを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Restore-DbaDbCertificate.ps1 | `public/Restore-DbaDbCertificate.ps1` | 182-207行目 |

**主要処理フロー**:
- **183-185行目**: SMO Certificateオブジェクト作成
- **189-194行目**: EncryptionPasswordあり/なしでCreate()呼び出し
- **195-204行目**: 最初の呼び出し失敗時のリトライ（CertificateSourceType指定）

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

```
Restore-DbaDbCertificate
    │
    ├─ Connect-DbaInstance
    │      └─ SQL Server接続確立
    │
    ├─ Test-DbaPath
    │      └─ ファイルアクセス検証
    │
    ├─ xp_fileexist
    │      └─ ディレクトリ判定
    │
    ├─ Get-DbaFile
    │      └─ ディレクトリ内.cerファイル取得
    │
    ├─ Join-DbaPath
    │      └─ 秘密鍵パス構築
    │
    ├─ SMO Certificate.Create()
    │      └─ 証明書作成
    │
    └─ Get-DbaDbCertificate
           └─ 作成済み証明書取得
```

### データフロー図

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

Path (.cer) ────────────────► Test-DbaPath ─────────────────────►
                                      │
                                      ▼
                              xp_fileexist
                                      │
                                      ├──► Get-DbaFile（ディレクトリ時）
                                      │
                                      ▼
KeyFilePath (.pvk) ─────────► または自動検出 ──────────────────►
                                      │
DecryptionPassword ─────────► ConvertFrom-SecurePass ─────────►
EncryptionPassword ─────────►         │
                                      ▼
                              SMO Certificate.Create()
                                      │
                                      ▼
                              Get-DbaDbCertificate ────► Certificate出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Restore-DbaDbCertificate.ps1 | `public/Restore-DbaDbCertificate.ps1` | ソース | メイン機能実装 |
| Restore-DbaDbCertificate.Tests.ps1 | `tests/Restore-DbaDbCertificate.Tests.ps1` | テスト | Pesterテストコード |
| Backup-DbaDbCertificate.ps1 | `public/Backup-DbaDbCertificate.ps1` | ソース | 証明書バックアップ（対となる機能） |
| Get-DbaDbCertificate.ps1 | `public/Get-DbaDbCertificate.ps1` | ソース | 証明書取得（依存コマンド） |
