# 機能設計書 340-Get-DbaSpn

## 概要

本ドキュメントは、SQL ServerサービスのためにActive Directoryに登録されている既存のService Principal Names (SPN)を取得する機能「Get-DbaSpn」の設計仕様を記載する。

### 本機能の処理概要

Get-DbaSpnは、指定されたコンピュータまたはサービスアカウントに対して現在登録されているSQL Server用のSPNをActive Directoryから取得する機能である。Kerberos認証の問題をトラブルシューティングする際に不可欠な情報を提供する。

**業務上の目的・背景**：Service Principal Names (SPN)は、Kerberos認証がSQL Serverに対して正しく機能するために必要である。SPNが欠落または重複している場合、クライアントは統合セキュリティを使用してSQL Serverに認証できなくなる。本機能は、Set-DbaSpnで変更を加える前、または認証失敗を調査する際に、現在のSPN構成を監査するために使用される。

**機能の利用シーン**：
- Kerberos認証の問題をトラブルシューティングする際
- Set-DbaSpn で変更を加える前に現在のSPN構成を確認する際
- SQL Server環境のSPN構成を監査する際
- 特定のサービスアカウントに登録されているSPNを確認する際

**主要な処理内容**：
1. ComputerNameまたはAccountNameに基づいて検索対象を決定
2. ComputerName指定時: Test-DbaSpn を使用してSPN情報を取得
3. AccountName指定時: Get-DbaADObject を使用してADからSPN情報を取得
4. 取得したSPN情報をカスタムオブジェクトとして出力

**関連システム・外部連携**：
- Active Directory (System.DirectoryServices.DirectorySearcher)
- SQL Server サービス情報

**権限による制御**：
- Active Directoryへの読み取りアクセス権限が必要
- サービスアカウントのSPN属性を読み取る権限が必要

## 関連画面

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

## 機能種別

情報取得 / SPN管理 / Kerberos認証

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ComputerName | string[] | No | SPN取得対象のコンピュータ名 | パイプライン入力可能 |
| AccountName | string[] | No | SPN取得対象のサービスアカウント名 | - |
| Credential | PSCredential | No | Active Directory接続用の資格情報 | - |
| EnableException | switch | No | 例外を直接スローする | - |

### 入力データソース

- Active Directory（servicePrincipalName属性）
- SQL Server サービス情報（Test-DbaSpn経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Input | string | 検索に使用した入力値（コンピュータ名またはアカウント名） |
| AccountName | string | SPNが登録されているサービスアカウント名 |
| ServiceClass | string | サービスクラス（常に "MSSQLSvc"） |
| Port | int | ポート番号（SPNに含まれている場合） |
| SPN | string | 完全なService Principal Name |

### 出力先

パイプライン出力（PSCustomObject）

## 処理フロー

### 処理シーケンス

```
1. パラメータチェック
   └─ ComputerName、AccountName両方未指定の場合はlocalhost（$env:COMPUTERNAME）を使用

2. ComputerName処理
   └─ 各コンピュータに対してTest-DbaSpn を呼び出し
   └─ IsSet = true のSPNを出力

3. AccountName処理
   └─ 各アカウントに対してProcess-Account内部関数を呼び出し
   └─ Get-DbaADObject でADオブジェクトを取得
   └─ servicePrincipalName属性を解析して出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{ComputerName指定?}
    B -->|Yes| C[各コンピュータをループ]
    B -->|No| D{AccountName指定?}

    C --> E{$で終わる?}
    E -->|Yes| F[アカウントとして処理]
    E -->|No| G[Test-DbaSpn実行]
    G --> H{IsSet = true?}
    H -->|Yes| I[PSCustomObject出力]
    H -->|No| J[次のコンピュータ]
    I --> J
    J --> K{次のコンピュータ?}
    K -->|Yes| C
    K -->|No| L{AccountName指定?}

    D -->|Yes| M[Process-Account]
    D -->|No| N[localhost使用]
    N --> C

    F --> M
    L -->|Yes| M
    L -->|No| O[終了]

    M --> P[Get-DbaADObject]
    P --> Q{結果あり?}
    Q -->|Yes| R[servicePrincipalName取得]
    Q -->|No| S[警告出力]
    R --> T[各SPNをループ]
    T --> U[ポート番号解析]
    U --> V[PSCustomObject出力]
    V --> W{次のSPN?}
    W -->|Yes| T
    W -->|No| X{次のアカウント?}
    S --> X
    X -->|Yes| M
    X -->|No| O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルトコンピュータ | ComputerName、AccountName両方未指定時はlocalhostを使用 | 両方未指定時 |
| BR-002 | アカウント判定 | コンピュータ名が$で終わる場合はアカウントとして処理 | ComputerName処理時 |
| BR-003 | ServiceClass固定 | ServiceClassは常に"MSSQLSvc" | 常に |
| BR-004 | Port解析 | SPNに:が含まれる場合、後半部分をポート番号として解析 | SPN解析時 |

### 計算ロジック

- ポート番号: SPN.Split(":")[1] を整数に変換
- ServiceClass: MSSQLSvcで固定（コメントアウトされたコードでは動的取得の痕跡あり）

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

本機能はSQL Serverへのデータベースアクセスを行わない。Active Directoryへの問い合わせのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ADLookupFailure | AD検索エラー | ドメインが解決できない場合 | 警告ログを出力して処理継続 |
| AccountNotFound | アカウント未検出 | サービスアカウントがADに存在しない場合 | 警告ログを出力して処理継続 |
| PermissionError | 権限エラー | SPN属性を読み取る権限がない場合 | 警告ログを出力して処理継続 |

### リトライ仕様

リトライは行わない。

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

本機能はデータ変更を行わないため、トランザクション管理は不要。

## パフォーマンス要件

- Active Directoryへの問い合わせ時間に依存
- 複数のコンピュータやアカウントを処理する場合は処理時間が増加

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

- Active Directoryへの読み取りアクセス権限が必要
- サービスアカウント情報が表示されるため、機密情報として扱う
- Credential パラメータで別の資格情報を指定可能

## 備考

- Set-DbaSpn と連携して使用
- Test-DbaSpn で期待されるSPNと実際のSPNを比較可能
- Remove-DbaSpn でSPNを削除可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Get-DbaSpn.ps1 | `public/Get-DbaSpn.ps1` | 出力オブジェクト構造（37-47行目の.OUTPUTS） |

**読解のコツ**: 出力オブジェクトは検索モード（ComputerName/AccountName）によらず同じ構造を持つ。Input、AccountName、ServiceClass、Port、SPNの5プロパティ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Get-DbaSpn.ps1 | `public/Get-DbaSpn.ps1` | パラメータ定義（66-72行目） |

**主要処理フロー**:
1. **73-126行目**: begin - Process-Account内部関数の定義とデフォルト値設定
2. **128-176行目**: process - ComputerNameとAccountNameの処理

#### Step 3: 内部関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Get-DbaSpn.ps1 | `public/Get-DbaSpn.ps1` | Process-Account関数（74-122行目） |

**主要処理フロー**:
- **76-81行目**: アカウントタイプの判定（$ suffix でComputer/User判定）
- **82-87行目**: Get-DbaADObject でADオブジェクト取得
- **88-99行目**: 権限エラーとアカウント未検出のハンドリング
- **101-120行目**: SPNの解析と出力

#### Step 4: ComputerName処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Get-DbaSpn.ps1 | `public/Get-DbaSpn.ps1` | ComputerName処理（130-169行目） |

**主要処理フロー**:
- **131-136行目**: $ suffix チェックでアカウント処理への振り分け
- **140行目**: Test-DbaSpn でSPN情報を取得
- **145-166行目**: IsSet = true のSPNを出力

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

```
Get-DbaSpn
    │
    ├─ Process-Account（内部関数）
    │      │
    │      ├─ Get-DbaADObject
    │      │      └─ Active DirectoryからADオブジェクト取得
    │      │
    │      └─ GetUnderlyingObject()
    │             └─ servicePrincipalName属性取得
    │
    └─ Test-DbaSpn
           └─ コンピュータのSPN構成を取得
```

### データフロー図

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

ComputerName ──▶ Test-DbaSpn
                    │
                    ├─ SQL Serverサービス検出
                    ├─ 期待されるSPN計算
                    ├─ 実際のSPN取得
                    │
                    ▼
              IsSet = true フィルタ
                    │
                    ▼
              PSCustomObject ──▶ パイプライン出力

AccountName ───▶ Process-Account
                    │
                    ├─ Get-DbaADObject
                    │      └─ servicePrincipalName
                    │
                    ▼
              SPN解析（ポート番号抽出）
                    │
                    ▼
              PSCustomObject ──▶ パイプライン出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Get-DbaSpn.ps1 | `public/Get-DbaSpn.ps1` | ソース | メイン関数 |
| Test-DbaSpn.ps1 | `public/Test-DbaSpn.ps1` | ソース | SPN構成の検証 |
| Set-DbaSpn.ps1 | `public/Set-DbaSpn.ps1` | ソース | SPNの設定 |
| Remove-DbaSpn.ps1 | `public/Remove-DbaSpn.ps1` | ソース | SPNの削除 |
| Get-DbaADObject.ps1 | `private/functions/Get-DbaADObject.ps1` | ソース | ADオブジェクト取得 |
