# 機能設計書 330-Enable-DbaHideInstance

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおける `Enable-DbaHideInstance` 機能の設計書である。SQL ServerインスタンスのHide Instance設定を有効化し、SQL Server Browserサービスからインスタンスを隠蔽する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：セキュリティ強化の観点から、SQL ServerインスタンスをSQL Server Browserサービスの列挙リクエストに応答させないようにすることは重要である。Hide Instance設定を有効化すると、ネットワークスキャンツールや攻撃者によるインスタンス発見を困難にし、攻撃対象を減らすことができる。本機能は、レジストリのHideInstance値を変更してこの設定を有効化する。

**機能の利用シーン**：本番環境のセキュリティ強化、コンプライアンス要件への対応、インターネット公開環境での防御強化、セキュリティ監査対応などで利用される。

**主要な処理内容**：
1. ターゲットコンピュータのネットワーク名解決
2. WMI経由でSQL Serverサービス情報取得
3. レジストリパスの特定
4. レジストリのHideInstance値をtrueに設定
5. 設定変更結果の返却

**関連システム・外部連携**：
- Windowsレジストリ（HKEY_LOCAL_MACHINE）
- SQL Server WMI Provider
- PowerShellリモーティング

**権限による制御**：ターゲットマシンへのWindows管理者権限が必要。SQL Serverログイン権限ではなく、Windowsレジストリへのアクセス権が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIコマンド | 主機能 | PowerShellコマンドラインからの実行 |

## 機能種別

レジストリ設定変更 / インスタンス設定 / セキュリティ強化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No | ターゲットSQL Serverインスタンス | デフォルト: $env:COMPUTERNAME |
| Credential | PSCredential | No | リモートレジストリアクセス用資格情報 | - |
| EnableException | switch | No | 例外を有効化 | - |
| Confirm | switch | No | 確認プロンプト表示 | SupportsShouldProcess |
| WhatIf | switch | No | 実行内容の表示のみ | SupportsShouldProcess |

### 入力データソース

- SQL Server WMI Provider: サービス情報とレジストリパスの取得
- Windowsレジストリ: HideInstance設定値の読み書き

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | レジストリ変更を行ったコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス識別子 |
| HideInstance | bool | 設定後のHideInstance値（true） |

### 出力先

PowerShellパイプライン（PSCustomObject）

## 処理フロー

### 処理シーケンス

```
1. 各SqlInstanceに対してループ処理開始
2. ローカルホストの場合は管理者権限チェック
   └─ Test-ElevationRequirementで確認
3. コンピュータ名の解決
   └─ Resolve-DbaNetworkNameで名前解決
4. SQL Serverサービス情報取得
   └─ Invoke-ManagedComputerCommandでWMI経由取得
5. レジストリパス特定
   └─ AdvancedProperties.REGROOTから取得
6. インスタンス名とサービスアカウント情報取得
7. レジストリ変更実行
   └─ Invoke-Command2でSet-ItemProperty実行
8. 変更後の値を取得して結果オブジェクト作成
9. 成功メッセージ出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[各SqlInstanceをループ]
    B --> C{ローカルホスト?}
    C -->|Yes| D[管理者権限チェック]
    C -->|No| E[続行]
    D --> E
    E --> F[Resolve-DbaNetworkName<br>名前解決]
    F --> G{解決成功?}
    G -->|No| H[Turboモードで再試行]
    G -->|Yes| I[WMI経由でサービス情報取得]
    H --> J{再試行成功?}
    J -->|No| K[エラー出力して次へ]
    J -->|Yes| I
    I --> L{取得成功?}
    L -->|No| K
    L -->|Yes| M[REGROOTからレジストリパス取得]
    M --> N{パス取得成功?}
    N -->|No| O[文字列パースで再試行]
    N -->|Yes| P[インスタンス名・サービスアカウント取得]
    O --> Q{パース成功?}
    Q -->|No| K
    Q -->|Yes| P
    P --> R[Invoke-Command2で<br>Set-ItemProperty実行]
    R --> S{実行成功?}
    S -->|No| T[エラー出力]
    S -->|Yes| U[結果オブジェクト出力]
    U --> V[成功メッセージ出力]
    K --> W{次のインスタンス?}
    T --> W
    V --> W
    W -->|Yes| B
    W -->|No| X[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-330-01 | ローカル管理者権限 | ローカルホストの場合は管理者権限必須 | IsLocalHost=true時 |
| BR-330-02 | レジストリ変更即時反映 | 変更は新規接続から即時有効 | 常時 |
| BR-330-03 | Windows資格情報 | SQL Server資格情報ではなくWindows資格情報が必要 | リモートアクセス時 |
| BR-330-04 | サービス再起動不要 | 設定変更後のサービス再起動は不要 | 常時 |
| BR-330-05 | ポート指定必須 | 設定後はクライアントが正確なポートを指定する必要あり | 接続時 |

### 計算ロジック

レジストリパス構築：
- `Registry::HKEY_LOCAL_MACHINE\{REGROOT}\MSSQLServer\SuperSocketNetLib`
- REGROOTはWMI AdvancedPropertiesから取得

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

本機能はデータベース操作を行わない。Windowsレジストリ操作のみ。

### レジストリ操作詳細

| 操作 | パス | キー | 値 |
|-----|------|------|-----|
| SET | HKLM\{REGROOT}\MSSQLServer\SuperSocketNetLib | HideInstance | 1 (true) |
| GET | 同上 | HideInstance | 変更後の値を取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ElevationError | ローカルで管理者権限不足 | Stop-Functionで処理継続 |
| - | ResolutionError | コンピュータ名解決失敗 | Turboモードでリトライ、失敗時Stop-Function |
| - | WMIError | WMI情報取得失敗 | Stop-Functionで処理継続 |
| - | ObjectNotFound | インスタンスが見つからない | Stop-Functionで処理継続 |
| - | RemotingError | リモート接続失敗 | Stop-Functionで処理継続 |

### リトライ仕様

名前解決時にResolve-DbaNetworkNameが失敗した場合、-Turboオプションで再試行。

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

レジストリ操作のため、トランザクション制御なし。

## パフォーマンス要件

特に定義されていない。即座に完了する軽量な操作。

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

- Windows管理者権限が必要
- PowerShellリモーティングを使用
- SQL Serverログイン権限は不要
- 資格情報はPSCredentialオブジェクトとして安全に管理
- 設定変更の影響: インスタンスがネットワーク検出から隠蔽される（セキュリティ向上）

## 備考

- 対となる機能: Disable-DbaHideInstance
- 作者: Gareth Newman (@gazeranco)
- SQL Server Configuration Managerの「プロトコル」プロパティに相当
- 設定後、クライアントは正確なポート番号またはSQL Serverエイリアスを使用して接続する必要がある

---

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

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

### 推奨読解順序

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

出力オブジェクトの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | 136-141行目のPSCustomObject定義（スクリプトブロック内） |

**読解のコツ**: Disable-DbaHideInstanceと同じ構造だが、HideInstance値がtrueになる点が異なる。

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

パラメータ定義と初期処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | 72-78行目のparam定義 |
| 2-2 | Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | 79-85行目のプロセスブロック開始 |

**主要処理フロー**:
- **72-78行目**: パラメータ定義（SqlInstanceデフォルトは$env:COMPUTERNAME）
- **83-85行目**: ローカルホストの管理者権限チェック

#### Step 3: 名前解決とWMI情報取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | 87-95行目の名前解決処理 |
| 3-2 | Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | 97-101行目のWMI情報取得 |

**主要処理フロー**:
- **87-95行目**: Resolve-DbaNetworkName（失敗時Turboモードでリトライ）
- **97-101行目**: Invoke-ManagedComputerCommandでWMIサービス情報取得
- **98行目**: SQL Serverサービスをフィルタ（DisplayName一致）

#### Step 4: レジストリ変更処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | 103-122行目のレジストリパス取得 |
| 4-2 | Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | 131-151行目のレジストリ変更 |

**主要処理フロー**:
- **103-104行目**: AdvancedPropertiesからREGROOT、VSNAME取得
- **112-122行目**: REGROOT取得失敗時の文字列パース
- **132-141行目**: スクリプトブロックでSet-ItemProperty実行
- **133行目**: HideInstanceを$trueに設定

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

```
Enable-DbaHideInstance
    │
    ├─ Test-ElevationRequirement
    │      └─ 管理者権限チェック
    │
    ├─ Resolve-DbaNetworkName
    │      └─ コンピュータ名解決
    │
    ├─ Invoke-ManagedComputerCommand
    │      └─ WMI経由でサービス情報取得
    │
    └─ Invoke-Command2
           └─ リモートでレジストリ変更
                  ├─ Set-ItemProperty（HideInstance=true）
                  └─ Get-ItemProperty（変更確認）
```

### データフロー図

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

SqlInstance ───────▶ Resolve-DbaNetworkName
                              │
                              ▼
                    Invoke-ManagedComputerCommand
                       （WMI情報取得）
                              │
                              ▼
                    REGROOTパス抽出
                              │
                              ▼
                    Invoke-Command2
                       （レジストリ変更）
                              │
                              ▼
                        PSCustomObject
                   （ComputerName, InstanceName,
                    SqlInstance, HideInstance=true）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Enable-DbaHideInstance.ps1 | `public/Enable-DbaHideInstance.ps1` | ソース | メイン関数の実装 |
| Disable-DbaHideInstance.ps1 | `public/Disable-DbaHideInstance.ps1` | ソース | 対となる無効化関数 |
| Resolve-DbaNetworkName.ps1 | `public/Resolve-DbaNetworkName.ps1` | ソース | ネットワーク名解決 |
| Invoke-ManagedComputerCommand.ps1 | `private/functions/Invoke-ManagedComputerCommand.ps1` | ソース | WMIコマンド実行 |
| Invoke-Command2.ps1 | `private/functions/Invoke-Command2.ps1` | ソース | リモートコマンド実行 |
