# 機能設計書 603-New-DbaComputerCertificate

## 概要

本ドキュメントは、SQL Serverの強制暗号化に使用できるコンピュータ証明書を作成する`New-DbaComputerCertificate`機能の設計書である。

### 本機能の処理概要

`New-DbaComputerCertificate`は、自己署名証明書またはActive Directory証明機関（CA）によって署名された証明書を作成する機能である。デフォルトで2048ビットのキー長と「SQL Server」というフレンドリ名で証明書が生成される。SSL証明書を利用した接続の強制暗号化プロセスを自動化するために設計されており、証明書の生成から各ノードへのインストールまでを一括で実行できる。

**業務上の目的・背景**：SQL Serverの接続暗号化を実装する際、適切なSSL/TLS証明書の作成と配布は複雑で手作業が多い。本機能は、Active DirectoryのWebサーバー証明書テンプレートを使用してローカルで証明書を生成し、WinRM経由でリモートマシンにコピーしてインポートするプロセスを自動化する。これにより、複数のSQL Serverインスタンスに対して一貫した証明書管理が可能になる。

**機能の利用シーン**：
- 新規SQL Server構築時のSSL証明書セットアップ
- 自己署名証明書による開発・テスト環境の暗号化構成
- SQL Serverフェイルオーバークラスタへの証明書配布
- 証明書の更新・ローテーション作業

**主要な処理内容**：
1. 証明書要求構成ファイル（.inf）の生成
2. certreqコマンドによる証明書署名要求（CSR）の作成
3. CAへの証明書要求の送信（CA署名の場合）または自己署名証明書の生成
4. 証明書のローカル証明書ストアへのインポート
5. リモートマシンへの証明書のエクスポートとインポート（必要な場合）

**関連システム・外部連携**：Active Directory Certificate Services、Windows証明書ストア、PowerShellリモーティング（WinRM）

**権限による制御**：管理者権限（RunAs Admin）が必要。CA署名証明書の場合、証明書の自動登録権限が必要。

## 関連画面

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

## 機能種別

オブジェクト作成（INSERT相当） / セキュリティインフラストラクチャ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ComputerName | DbaInstance[] | No | 証明書をインストールするターゲットコンピュータ（デフォルト: localhost） | なし |
| Credential | PSCredential | No | リモートコンピュータ接続用の代替資格情報 | なし |
| CaServer | String | No | 証明書を署名するCA サーバー（自動検出される） | なし |
| CaName | String | No | CAサーバー上のCA名（自動検出される） | なし |
| ClusterInstanceName | String | No | SQL Serverフェイルオーバークラスタの仮想クラスタ名 | なし |
| SecurePassword | SecureString | No | 証明書エクスポート/インポート時の秘密鍵保護用パスワード | なし |
| FriendlyName | String | No | 証明書ストアに表示されるフレンドリ名（デフォルト: "SQL Server"） | なし |
| CertificateTemplate | String | No | 証明書生成に使用するAD証明書テンプレート（デフォルト: "WebServer"） | なし |
| KeyLength | Int | No | 証明書の秘密鍵のRSAキーサイズ（ビット）（デフォルト: 2048） | なし |
| Store | String | No | 証明書ストアの場所（デフォルト: "LocalMachine"） | なし |
| Folder | String | No | 証明書ストアのフォルダ（デフォルト: "My"） | なし |
| Flag | String[] | No | 秘密鍵の取り扱い方法（デフォルト: "Exportable, PersistKeySet"） | EphemeralKeySet, Exportable, PersistKeySet, UserProtected, NonExportable |
| Dns | String[] | No | 証明書のSANに含める追加DNS名 | なし |
| SelfSigned | Switch | No | CAの代わりに自己署名証明書を作成 | なし |
| HashAlgorithm | String | No | 証明書署名に使用するハッシュアルゴリズム（デフォルト: "Sha256"） | Sha256, sha384, sha512 |
| MonthsValid | Int | No | 自己署名証明書の有効期間（月数）（デフォルト: 12） | なし |
| EnableException | Switch | No | 例外処理の有効化フラグ | なし |

### 入力データソース

- Active Directory PKIインフラストラクチャ（CA署名の場合）
- 環境変数（$env:USERDNSDOMAIN）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| FriendlyName | String | 証明書に割り当てられたフレンドリ名 |
| DnsNameList | String[] | 証明書のSANに含まれるDNS名のコレクション |
| Thumbprint | String | 証明書のSHA-1ハッシュフィンガープリント |
| NotBefore | DateTime | 証明書が有効になる日時 |
| NotAfter | DateTime | 証明書の有効期限 |
| Subject | String | 証明書のサブジェクト識別名（DN） |
| Issuer | String | 証明書の発行者識別名（DN） |

### 出力先

- PowerShellパイプライン（X509Certificate2オブジェクト）
- ローカル証明書ストア（Cert:\LocalMachine\My）
- リモートマシンの証明書ストア（リモートターゲットの場合）

## 処理フロー

### 処理シーケンス

```
1. 前処理（beginブロック）
   ├─ NonExportableフラグの処理
   ├─ OS言語チェック（英語のみサポート）
   ├─ 管理者権限チェック
   └─ CAサーバー/CA名の自動検出（CA署名の場合）
2. 各ComputerNameに対して処理（processブロック）
   ├─ FQDN解決（Resolve-DbaNetworkName）
   ├─ 一時ディレクトリ作成
   ├─ SAN拡張の生成（Get-SanExt関数）
   ├─ 証明書要求構成ファイル（.inf）の作成
   ├─ certreq -new で証明書要求/自己署名証明書を生成
   ├─ certreq -submit でCA に送信（CA署名の場合）
   ├─ certreq -accept で証明書をインポート
   ├─ リモートマシンへの証明書エクスポート/インポート（必要な場合）
   └─ 一時ファイルのクリーンアップ
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{英語OSロケール?}
    B -->|No| C[エラー終了]
    B -->|Yes| D{管理者権限?}
    D -->|No| E[エラー終了]
    D -->|Yes| F{SelfSigned?}
    F -->|No| G[CA情報を自動検出]
    F -->|Yes| H[CA検出スキップ]
    G --> I[ComputerNameループ開始]
    H --> I
    I --> J[FQDN解決]
    J --> K[一時ディレクトリ作成]
    K --> L[SAN拡張生成]
    L --> M[証明書要求構成ファイル作成]
    M --> N[certreq -new 実行]
    N --> O{SelfSigned?}
    O -->|Yes| P[自己署名証明書生成完了]
    O -->|No| Q[certreq -submit でCAに送信]
    Q --> R{発行成功?}
    R -->|No| S[エラー出力]
    R -->|Yes| T[certreq -accept でインポート]
    P --> U{ローカルホスト?}
    T --> U
    U -->|Yes| V[結果出力]
    U -->|No| W[PFXエクスポート]
    W --> X[WinRMでリモートインポート]
    X --> Y[Get-DbaComputerCertificateで結果取得]
    V --> Z[一時ファイル削除]
    Y --> Z
    S --> Z
    Z --> AA{次のコンピュータ?}
    AA -->|Yes| I
    AA -->|No| AB[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-603-01 | 英語OSロケール | 英語版OSでのみサポート（OSLanguageコード: 9, 1033, 2057等） | 常時 |
| BR-603-02 | 管理者権限要件 | ローカルマシンでの実行には管理者権限が必要 | 常時 |
| BR-603-03 | デフォルトキー長 | 特に指定がなければ2048ビットのRSAキーを生成 | KeyLength未指定時 |
| BR-603-04 | デフォルトフレンドリ名 | 特に指定がなければ「SQL Server」を使用 | FriendlyName未指定時 |
| BR-603-05 | デフォルトDNS | 特に指定がなければショート名とFQDNの両方をSANに含める | Dns未指定時 |
| BR-603-06 | クラスタ証明書 | ClusterInstanceName指定時は各ノードに同一証明書をインストール | クラスタ構成時 |
| BR-603-07 | UserProtected制限 | UserProtectedフラグはローカルホストでのみ有効 | リモートマシンでは無効 |

### 計算ロジック

**SAN拡張（GetHexLength関数とGet-SanExt関数）**：
- DNS名をASN.1 DER形式に変換
- 各文字を16進数に変換し、適切なタグ（0x82）とレングスバイトを付与
- Base64エンコードして証明書要求に組み込み

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | SQLデータベースへのアクセスなし |

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

本機能はSQLデータベースにアクセスせず、Windows証明書ストアとActive Directory PKIのみを操作する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 言語エラー | 英語以外のOSロケール | 英語版OSで実行 |
| - | 権限エラー | 管理者権限なし | 管理者として実行 |
| - | AD接続エラー | Active Directoryにアクセスできない | AD接続を確認、SelfSignedオプション使用 |
| - | 名前解決失敗 | コンピュータ名を解決できない | ネットワーク構成を確認 |
| - | CA送信失敗 | 証明書要求がCAで拒否された | CA権限を確認 |
| - | リモートインポート失敗 | WinRM接続またはインポートが失敗 | WinRM構成と権限を確認 |

### リトライ仕様

特になし

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

証明書作成処理は複数ステップで構成されるが、トランザクション制御はない。失敗時の部分的な状態（証明書要求が作成されたがインポートされていない等）が残る可能性がある。

## パフォーマンス要件

特に規定なし（CA署名の場合、CA応答時間に依存）

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

- 管理者権限（RunAs Admin）が必要
- 秘密鍵は暗号化されてリモートマシンに転送される
- SecurePasswordが指定された場合、PFXエクスポート時に使用される
- NonExportableフラグにより秘密鍵のエクスポートを防止可能
- 自己署名証明書はクライアント信頼ストアへの手動追加が必要

## 備考

- 本機能は英語版OSロケールでのみサポートされている
- Active Directoryの自動登録が有効なアカウントでの実行が推奨される
- certreqコマンドを内部で使用している

---

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

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

### 推奨読解順序

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

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

**読解のコツ**: 本機能は複雑だが、主に3つのフェーズ（構成ファイル生成、証明書作成、リモート配布）で構成されていることを理解するとよい。

#### Step 2: エントリーポイントとbeginブロックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | New-DbaComputerCertificate.ps1 | `public/New-DbaComputerCertificate.ps1` | 209-321行目のbeginブロックで初期化処理を確認 |

**主要処理フロー**:
1. **210-223行目**: NonExportableフラグの処理とデフォルトフラグ設定
2. **225-229行目**: 英語OSロケールチェック（言語コード検証）
3. **231-233行目**: 管理者権限チェック
4. **235-246行目**: GetHexLength関数の定義（SAN拡張用ヘルパー）
5. **248-285行目**: Get-SanExt関数の定義（DNS名をASN.1形式に変換）
6. **287-317行目**: CA自動検出（Active Directory LDAP経由）

#### Step 3: processブロックの証明書生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaComputerCertificate.ps1 | `public/New-DbaComputerCertificate.ps1` | 323-443行目で証明書要求と生成処理を確認 |

**主要処理フロー**:
- **329-349行目**: FQDN解決とクラスタ名処理
- **351-364行目**: 一時ディレクトリ管理
- **366-371行目**: DNS名リストの構築
- **373-408行目**: 証明書要求構成ファイル（.inf）の生成
- **410-413行目**: certreq -new の実行
- **415-443行目**: 自己署名の場合はシリアル番号から証明書取得、CA署名の場合はcertreq -submit/-accept

#### Step 4: リモート配布処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | New-DbaComputerCertificate.ps1 | `public/New-DbaComputerCertificate.ps1` | 446-490行目でリモートマシンへの証明書配布を確認 |

**主要処理フロー**:
- **448-459行目**: PFXエクスポートとローカル証明書削除、クラスタ用フラグ設定
- **461-477行目**: リモート実行スクリプトブロック（証明書インポート処理）
- **479-489行目**: Invoke-Command2でリモート実行、Get-DbaComputerCertificateで結果取得

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

```
New-DbaComputerCertificate
    │
    ├─ [begin]
    │   ├─ Get-DbaCmObject (OSLanguageチェック)
    │   ├─ Test-ElevationRequirement
    │   └─ [ADSI] LDAP接続 (CA自動検出)
    │
    └─ [process]
        │
        ├─ Resolve-DbaNetworkName
        │      └─ FQDN解決
        │
        ├─ GetHexLength (内部関数)
        │      └─ 16進数長計算
        │
        ├─ Get-SanExt (内部関数)
        │      └─ SAN拡張のASN.1 DER生成
        │
        ├─ Set-Content / Add-Content
        │      └─ 証明書要求構成ファイル作成
        │
        ├─ certreq -new
        │      └─ CSR/自己署名証明書生成
        │
        ├─ certreq -submit (CA署名の場合)
        │      └─ CAへの証明書要求送信
        │
        ├─ certreq -accept (CA署名の場合)
        │      └─ 発行された証明書のインポート
        │
        ├─ X509Certificate2.Export (リモートの場合)
        │      └─ PFX形式でエクスポート
        │
        ├─ Invoke-Command2 (リモートの場合)
        │      └─ リモートマシンで証明書インポート
        │
        └─ Get-DbaComputerCertificate (リモートの場合)
               └─ インポート結果の確認
```

### データフロー図

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

ComputerName ───────▶ FQDN解決 ───────────────────▶ 解決済みホスト名
      │                  │
      │                  ▼
      │          証明書要求構成ファイル生成
      │                  │
      │                  ▼
      │          certreq -new
      │                  │
      │      ┌──────────┴──────────┐
      │      ▼                     ▼
      │  自己署名                CA署名
      │      │                     │
      │      ▼                     ▼
      │  シリアル番号で       certreq -submit
      │  証明書取得                │
      │      │                     ▼
      │      │              certreq -accept
      │      │                     │
      │      └──────────┬──────────┘
      │                 ▼
      │          ローカル証明書ストア
      │                 │
      │     ┌───────────┴───────────┐
      │     ▼                       ▼
      │  ローカルホスト          リモートホスト
      │     │                       │
      │     │                       ▼
      │     │              PFXエクスポート
      │     │                       │
      │     │                       ▼
      │     │              WinRMでリモートインポート
      │     │                       │
      │     └───────────┬───────────┘
      │                 ▼
      └─────────▶ X509Certificate2オブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| New-DbaComputerCertificate.ps1 | `public/New-DbaComputerCertificate.ps1` | ソース | メイン機能実装 |
| Resolve-DbaNetworkName.ps1 | `public/Resolve-DbaNetworkName.ps1` | ソース | ホスト名からFQDNへの解決 |
| Test-ElevationRequirement.ps1 | `private/functions/Test-ElevationRequirement.ps1` | ソース | 管理者権限確認 |
| Get-DbaCmObject.ps1 | `private/functions/Get-DbaCmObject.ps1` | ソース | WMIオブジェクト取得 |
| Invoke-Command2.ps1 | `private/functions/Invoke-Command2.ps1` | ソース | PowerShellリモーティングラッパー |
| Get-DbaComputerCertificate.ps1 | `public/Get-DbaComputerCertificate.ps1` | ソース | 証明書取得（結果確認用） |
