# 機能設計書 342-Set-DbaSpn

## 概要

本ドキュメントは、dbatools PowerShellモジュールのSet-DbaSpn関数の機能設計書である。この関数はActive DirectoryにService Principal Name (SPN) を登録し、デフォルトでKerberos制約付き委任も設定する。

### 本機能の処理概要

Set-DbaSpn関数は、SQL ServerサービスアカウントにSPNを追加し、オプションでKerberos制約付き委任を構成する機能を提供する。

**業務上の目的・背景**：Kerberos認証を有効にするためには、SQL ServerサービスアカウントにSPNが正しく登録されている必要がある。SPNが未登録または不正に登録されている場合、Kerberos認証が失敗し、NTLM認証へのフォールバックや「ダブルホップ」問題が発生する。この関数は、SPNの登録と委任設定を自動化することで、Kerberos認証環境の構築を支援する。

**機能の利用シーン**：新しいSQL Serverインスタンスをセットアップする場合、サービスアカウントを変更した後にSPNを再登録する場合、Test-DbaSpnで検出された不足SPNを一括登録する場合に使用される。

**主要な処理内容**：
1. 指定されたサービスアカウントをActive Directoryで検索する
2. servicePrincipalNameプロパティにSPNを追加する
3. -NoDelegationが指定されていない場合、msDS-AllowedToDelegateTo属性に委任エントリを追加する
4. 各操作の結果を構造化されたオブジェクトとして出力する

**関連システム・外部連携**：Active Directory (System.DirectoryServices.AccountManagement を使用)、Get-DbaADObject内部関数によるADオブジェクト検索。

**権限による制御**：Active Directoryへの書き込みアクセス権が必要。指定されたCredentialパラメータを使用して認証を行う。

## 関連画面

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

## 機能種別

データ操作（Active Directoryオブジェクトの更新）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SPN | string | Yes | 登録するService Principal Name | MSSQLSvc/servername:port形式 |
| ServiceAccount | string | Yes | SPNを所有するActive Directoryアカウント | domain\username形式またはCOMPUTERNAME$形式 |
| Credential | PSCredential | No | Active Directory接続用の資格情報 | 有効なPSCredentialオブジェクト |
| NoDelegation | switch | No | 委任設定をスキップ | true/false |
| EnableException | switch | No | 例外処理の動作を制御 | true/false |
| Confirm | switch | No | 変更前の確認 | true/false |
| WhatIf | switch | No | 実行されることをシミュレート | true/false |

### 入力データソース

- パイプライン入力: Test-DbaSpnの出力を直接パイプライン経由で受け取り可能
- ValueFromPipelineByPropertyName: SPN, ServiceAccount, Credentialパラメータは名前付きプロパティから自動的にバインドされる

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Name | string | 追加されたService Principal Name |
| ServiceAccount | string | SPNを追加したActive Directoryアカウント |
| Property | string | 変更されたAD属性 (servicePrincipalName または msDS-AllowedToDelegateTo) |
| IsSet | boolean | SPNまたは委任が正常に設定されたかどうか |
| Notes | string | 操作のステータスメッセージ |

### 出力先

PowerShellパイプライン（PSCustomObject）

## 処理フロー

### 処理シーケンス

```
1. サービスアカウントの検索
   └─ Get-DbaADObjectを使用してActive Directoryでアカウントを検索
   └─ アカウント名が$で終わる場合はコンピュータアカウントとして検索

2. SPNの追加処理
   └─ ShouldProcessで確認後、servicePrincipalName属性にSPNを追加
   └─ CommitChanges()でADへの変更を確定
   └─ 結果オブジェクトを出力

3. 委任設定の追加処理（-NoDelegation未指定時）
   └─ SPN追加が成功した場合のみ実行
   └─ msDS-AllowedToDelegateTo属性に委任エントリを追加
   └─ CommitChanges()でADへの変更を確定
   └─ 結果オブジェクトを出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Get-DbaADObjectでサービスアカウント検索]
    B --> C{アカウント発見?}
    C -->|No| D[エラー: アカウント未発見]
    C -->|Yes| E{ShouldProcess確認}
    E -->|WhatIf| F[シミュレーション出力]
    E -->|実行| G[servicePrincipalNameにSPN追加]
    G --> H{追加成功?}
    H -->|No| I[失敗結果出力]
    H -->|Yes| J[成功結果出力]
    J --> K{NoDelegation?}
    I --> L[終了]
    K -->|Yes| M[委任スキップログ出力]
    K -->|No| N{ShouldProcess確認}
    N -->|WhatIf| O[シミュレーション出力]
    N -->|実行| P[msDS-AllowedToDelegateTo追加]
    P --> Q[委任結果出力]
    Q --> L
    M --> L
    O --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | SPN形式 | SPNはMSSQLSvc/hostname:port形式で指定する必要がある | 常に適用 |
| BR-002 | サービスアカウント形式 | domain\usernameまたはCOMPUTERNAME$形式で指定 | 常に適用 |
| BR-003 | デフォルト委任有効 | NoDelegation未指定時は自動的に委任を設定 | デフォルト動作 |
| BR-004 | 委任設定条件 | SPN追加成功時のみ委任設定を実行 | SPN追加成功時 |
| BR-005 | コンピュータアカウント識別 | $で終わるアカウント名はコンピュータアカウントとして検索 | アカウント名の末尾が$ |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし（Active Directory操作のみ） |

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

該当なし（Active Directoryの属性操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | AD検索失敗 | ドメイン解決不可またはアクセス権不足 | 資格情報とドメイン接続を確認 |
| - | アカウント未発見 | 指定されたサービスアカウントがADに存在しない | アカウント名を確認 |
| - | プロパティアクセス不可 | サービスアカウントのプロパティ検査権限がない | 適切な権限を持つ資格情報を使用 |
| - | SPN追加失敗 | ADへの書き込み権限がないまたは重複SPN | AD管理者権限を確認、重複SPNを削除 |
| - | 委任追加失敗 | msDS-AllowedToDelegateTo属性への書き込み権限がない | AD管理者権限を持つアカウントで実行 |

### リトライ仕様

明示的なリトライ機能はなし。エラー発生時はWrite-Messageで警告を出力し、EnableExceptionに応じて例外をスローする。

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

Active Directoryの各操作（SPN追加、委任追加）は個別にCommitChanges()でコミットされる。SPN追加が失敗した場合、委任設定は実行されない。

## パフォーマンス要件

AD検索とプロパティ更新は通常数秒以内で完了。大規模なAD環境ではドメインコントローラーへのネットワーク遅延に依存。

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

- Active Directoryへの書き込みアクセス権限が必要
- 資格情報はPSCredentialオブジェクトとして安全に渡される
- WhatIfパラメータで事前に影響範囲を確認可能
- SupportsShouldProcess属性による確認プロンプト対応
- 委任設定によりサービスアカウントが他のサービスに認証を渡せるようになるため、セキュリティ影響を考慮すること

## 備考

- Test-DbaSpnからのパイプライン入力をサポート（IsSet -eq $falseのSPNを自動登録可能）
- 1回の呼び出しで最大2つのオブジェクト（SPN追加結果と委任追加結果）を出力
- -NoDelegation指定時は委任設定をスキップし、SPNのみを登録

---

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

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

### 推奨読解順序

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

出力されるPSCustomObjectの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Set-DbaSpn.ps1 | `public/Set-DbaSpn.ps1` | 156-162行目と182-188行目の出力オブジェクト構造を確認 |

**読解のコツ**: PowerShellのPSCustomObjectはハッシュテーブル構文で定義される。@{key=value}形式で出力プロパティが定義されている。

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

関数の入口と主要パラメータを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Set-DbaSpn.ps1 | `public/Set-DbaSpn.ps1` | 105-117行目のパラメータ定義を確認 |

**主要処理フロー**:
1. **105-117行目**: param()ブロックでパラメータ定義
2. **107-113行目**: ValueFromPipelineByPropertyNameでパイプライン入力をサポート
3. **115行目**: NoDelegationスイッチで委任設定の制御
4. **116行目**: EnableExceptionスイッチで例外処理動作を制御

#### Step 3: 処理ロジックを理解する

processブロック内の主要処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Set-DbaSpn.ps1 | `public/Set-DbaSpn.ps1` | 119-194行目のprocess{}ブロック |

**主要処理フロー**:
- **121-125行目**: アカウントタイプの判定（User/Computer）
- **126-130行目**: Get-DbaADObjectでAD検索
- **131-139行目**: 検索結果のチェックとエラーハンドリング
- **142-163行目**: SPN追加処理
- **166-193行目**: 委任設定追加処理（NoDelegation未指定時）

#### Step 4: 依存関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Get-DbaADObject.ps1 | `private/functions/Get-DbaADObject.ps1` | AD検索のロジックとIdentityType処理 |

**主要処理フロー**:
- **81-114行目**: パラメータ定義とsearchClass決定
- **116-131行目**: 内部関数Get-DbaADObjectInternalでの実際のAD検索

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

```
Set-DbaSpn
    │
    ├─ Get-DbaADObject (private/functions/Get-DbaADObject.ps1)
    │      └─ System.DirectoryServices.AccountManagement.Principal.FindByIdentity
    │
    ├─ $Result.GetUnderlyingObject()
    │      └─ DirectoryEntry オブジェクト取得
    │
    ├─ $adentry.Properties['serviceprincipalname'].Add()
    │      └─ SPN追加
    │
    ├─ $adentry.Properties['msDS-AllowedToDelegateTo'].Add()
    │      └─ 委任追加（NoDelegation未指定時）
    │
    └─ $adentry.CommitChanges()
           └─ ADへの変更確定
```

### データフロー図

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

SPN パラメータ ───┬──▶ Get-DbaADObject() ──▶ ADアカウント検索
                  │         │
ServiceAccount ───┘         ▼
                     GetUnderlyingObject() ──▶ DirectoryEntry取得
                            │
                            ▼
                     servicePrincipalName ──▶ PSCustomObject
                     追加処理                  (SPN追加結果)
                            │
                     ┌──────┴───────┐
                     │              │
               NoDelegation?    委任追加処理
                     │              │
                   [Yes]         [No]
                     │              ▼
                   スキップ    msDS-AllowedToDelegateTo ──▶ PSCustomObject
                                                            (委任追加結果)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Set-DbaSpn.ps1 | `public/Set-DbaSpn.ps1` | ソース | メイン関数 |
| Get-DbaADObject.ps1 | `private/functions/Get-DbaADObject.ps1` | ソース | ADオブジェクト検索の内部関数 |
| Test-DbaSpn.ps1 | `public/Test-DbaSpn.ps1` | ソース | パイプライン入力元として使用可能 |
| Remove-DbaSpn.ps1 | `public/Remove-DbaSpn.ps1` | ソース | 対となるSPN削除関数 |
