# 機能設計書 587-Test-DbaWindowsLogin

## 概要

本ドキュメントは、dbatools PowerShellモジュールの`Test-DbaWindowsLogin`コマンドレットに関する機能設計書です。本機能はSQL Server内のWindowsログインおよびグループをActive Directoryに対して検証し、孤立、無効化、または問題のあるアカウントを特定します。

### 本機能の処理概要

`Test-DbaWindowsLogin`は、SQL Serverの全てのWindowsベースのログインおよびグループを照会し、Active Directoryに対して各アカウントを検証してセキュリティ問題とクリーンアップの機会を特定します。ADアカウントがまだ存在するか、有効になっているか、SQL Server SIDと一致するかをチェックし、ドメインマイグレーションやアカウント削除による孤立ログインを検出します。

**業務上の目的・背景**：SQL ServerにはWindowsログインやグループが登録されますが、Active Directory側でアカウントが削除、無効化、または移行された場合、SQL Server側には古いエントリが残ります。このような孤立ログインはセキュリティリスクとなり、また不要なオブジェクトとしてシステムを複雑にします。本機能はこれらの問題を検出してDBAwがログインセキュリティを維持できるようにします。

**機能の利用シーン**：
- 定期的なセキュリティ監査でのWindowsログイン検証
- ADドメインマイグレーション後の孤立ログイン検出
- 退職者やアカウント変更後のクリーンアップ対象特定
- コンプライアンス要件に基づくログイン整合性検証
- 特権アカウントの重点的なセキュリティ監査

**主要な処理内容**：
1. SQL Serverインスタンスへの接続
2. WindowsUserおよびWindowsGroupタイプのログイン取得
3. 各ログインのSIDをActive Directoryで照合
4. UserAccountControl属性の解析（有効/無効、ロックアウト、パスワード期限等）
5. SID不一致やSamAccountName不一致の検出
6. 検証結果の出力

**関連システム・外部連携**：Get-DbaADObject内部関数を使用してActive Directoryへの照会を実行します。

**権限による制御**：SQL Server上でのログイン読み取り権限およびActive Directoryへの照会権限が必要です。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 69 | Windowsログインテスト | 主機能 | Windowsログインの検証 |

## 機能種別

セキュリティ監査 / バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No* | 対象となるSQL Serverインスタンス | パイプライン入力対応 |
| SqlCredential | PSCredential | No | SQL Server接続用の代替資格情報 | - |
| Login | string[] | No | 検証対象の特定ログイン名 | ワイルドカード対応 |
| ExcludeLogin | string[] | No | 検証から除外するログイン名 | ワイルドカード対応 |
| FilterBy | string | No | LoginsOnly/GroupsOnly/None | ValidateSet制約 |
| IgnoreDomains | string[] | No | 検証から除外するドメイン | - |
| InputObject | Login[] | No | パイプラインからのログインオブジェクト | - |
| EnableException | switch | No | 例外をスローするモード | - |

### 入力データソース

- SQL Serverのsys.server_principals（LoginType = WindowsUser, WindowsGroup）
- Active Directory（Get-DbaADObject経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Server | string | SQL Serverインスタンス名 |
| Domain | string | Active Directoryドメイン名 |
| Login | string | Windowsログインのユーザー名部分 |
| Type | string | アカウントタイプ（User, Computer, Group） |
| Found | boolean | ADにアカウントが存在するか |
| SamAccountNameMismatch | boolean | SamAccountNameがSQL Serverと異なるか |
| DisabledInSQLServer | boolean | SQL Serverでログインが無効化されているか |
| Enabled | boolean | ADでアカウントが有効か（グループはnull） |
| AccountNotDelegated | boolean | 委任が許可されていないか |
| LockedOut | boolean | アカウントがロックアウトされているか |
| PasswordExpired | boolean | パスワードが期限切れか |
| PasswordNeverExpires | boolean | パスワードが無期限設定か |
| PasswordNotRequired | boolean | パスワード不要設定か |
| CannotChangePassword | boolean | パスワード変更不可設定か |
| AllowReversiblePasswordEncryption | boolean | 可逆暗号化が有効か |
| SmartcardLogonRequired | boolean | スマートカードログイン必須か |
| TrustedForDelegation | boolean | 委任の信頼が有効か |
| UserAccountControl | int | 生のUserAccountControl値 |

### 出力先

PowerShellパイプラインへのPSCustomObjectの出力

## 処理フロー

### 処理シーケンス

```
1. IgnoreDomainsの正規化（beginブロック）
   └─ 大文字に変換

2. UserAccountControlマッピングの定義
   └─ 各UACフラグと値のマッピング

3. SQL Serverインスタンスへの接続
   └─ Connect-DbaInstance

4. Windowsログイン/グループの取得
   └─ LoginType in ('WindowsUser', 'WindowsGroup')

5. ローカルアカウントの除外
   └─ "NT "、コンピュータ名、"BUILTIN"で始まるものを除外

6. FilterByによるフィルタリング
   └─ LoginsOnly: WindowsUserのみ
   └─ GroupsOnly: WindowsGroupのみ
   └─ None: 両方

7. 各Windowsログインの検証
   └─ SIDをADで検索（Get-DbaADObject）
   └─ SID一致確認
   └─ SamAccountName一致確認
   └─ UserAccountControl属性の解析

8. 各Windowsグループの検証
   └─ SIDをADで検索（Get-DbaADObject -Type Group）
   └─ SID一致確認
   └─ SamAccountName一致確認

9. 結果出力
   └─ Select-DefaultViewで主要プロパティを表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[IgnoreDomainsの正規化]
    B --> C[UACマッピング定義]
    C --> D[各SqlInstanceループ]
    D --> E[Connect-DbaInstance]
    E --> F{接続成功?}
    F -->|No| G[エラー、次のインスタンスへ]
    F -->|Yes| H[Windowsログイン取得]
    H --> I[ローカルアカウント除外]
    I --> J[Login/ExcludeLoginフィルタ]
    J --> K[FilterByフィルタ]
    K --> L[各Windowsログインループ]
    L --> M{IgnoreDomains?}
    M -->|Yes| N[スキップ]
    M -->|No| O[Get-DbaADObject SID検索]
    O --> P{AD存在確認}
    P --> Q[SID一致確認]
    Q --> R[SamAccountName確認]
    R --> S[UAC属性解析]
    S --> T[結果出力]
    T --> U{次のログイン?}
    N --> U
    U -->|Yes| L
    U -->|No| V[各Windowsグループループ]
    V --> W[同様の処理]
    W --> X{次のグループ?}
    X -->|Yes| V
    X -->|No| Y{次のインスタンス?}
    Y -->|Yes| D
    Y -->|No| Z[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-587-01 | ローカルアカウント除外 | "NT "、コンピュータ名、"BUILTIN"で始まるログインは検証対象外 | 常時 |
| BR-587-02 | SID一致検証 | SQL ServerのSIDとADのSIDが一致するか確認 | 常時 |
| BR-587-03 | SamAccountName検証 | SQL Serverのログイン名とADのSamAccountNameが一致するか確認 | 常時 |
| BR-587-04 | コンピュータアカウント判定 | ログイン名が$で終わる場合はコンピュータアカウントとして検索 | ユーザー検索失敗時 |

### 計算ロジック

UserAccountControl属性のビット演算:
```powershell
# 例：アカウント無効化チェック
$disabled = [bool]($uac.Value -band $mappingRaw['ACCOUNTDISABLE'])
# Enabledはその逆
$enabled = !($uac.Value -band $mappingRaw['ACCOUNTDISABLE'])
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ログイン取得 | sys.server_principals | SELECT | Windowsログイン/グループの取得 |

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

#### sys.server_principals

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | name, sid, is_disabled, type | type in ('U', 'G') | 読み取りのみ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ConnectionError | SQL Server接続失敗 | Stop-Function、次のインスタンスへ |
| - | ADSearchError | AD検索失敗 | Warning出力、処理継続 |
| - | InputError | SqlInstanceとInputObjectの両方指定 | Stop-Function |

### リトライ仕様

リトライ処理なし。ADエラーは警告として処理を継続します。

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

読み取り専用操作のためトランザクション管理は不要です。

## パフォーマンス要件

特に規定なし。大量のWindowsログインがある場合はAD照会に時間がかかる可能性があります。

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

- SQL Serverへのログイン読み取り権限が必要
- Active Directoryへの照会権限が必要
- UserAccountControl情報が出力に含まれる（セキュリティ監査目的）

## 備考

- Get-DbaADObject内部関数を使用してAD照会を実行
- ローカルアカウント（NT SERVICE等）は検証対象外
- グループアカウントにはUAC関連プロパティはnull

---

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

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

### 推奨読解順序

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

出力されるデータ構造とUserAccountControlマッピングを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 131-155行目: UACマッピング定義 |
| 1-2 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 274-295行目: ユーザー出力構造 |
| 1-3 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 333-352行目: グループ出力構造 |

**読解のコツ**: $mappingRawはUserAccountControl属性のビットフラグと値のマッピングです。各フラグをビット演算で解析します。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 110-123行目: パラメータ定義 |

**主要処理フロー**:
1. **112-114行目**: SqlInstance、SqlCredential
2. **115-118行目**: Login、ExcludeLogin、FilterBy
3. **119-122行目**: IgnoreDomains、InputObject

#### Step 3: ログインの取得とフィルタリング

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 171行目: Windowsログインフィルタ |
| 3-2 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 180行目: ローカルアカウント除外 |
| 3-3 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 187-201行目: FilterByによる振り分け |

**主要処理フロー**:
- **171行目**: LoginType in ('WindowsUser', 'WindowsGroup')でフィルタ
- **180行目**: "NT ", コンピュータ名, "BUILTIN"で始まるものを除外
- **187-201行目**: LoginsOnly/GroupsOnly/Noneで振り分け

#### Step 4: ADでの検証処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 213-244行目: ユーザー検証処理 |
| 4-2 | Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | 246-273行目: UAC属性解析 |

**主要処理フロー**:
- **214-215行目**: SIDのバイナリ変換
- **218行目**: Get-DbaADObjectでSID検索
- **219-225行目**: ユーザー/コンピュータ判定
- **231-239行目**: SID一致、SamAccountName一致確認
- **260-272行目**: UACビット演算で各属性取得

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

```
Test-DbaWindowsLogin
    │
    ├─ Connect-DbaInstance
    │      └─ SQL Server接続
    │
    ├─ $server.Logins (フィルタリング)
    │      └─ WindowsUser/WindowsGroup取得
    │
    ├─ Get-DbaADObject (User)
    │      └─ ADでユーザー/コンピュータ検索
    │
    ├─ Get-DbaADObject (Group)
    │      └─ ADでグループ検索
    │
    └─ Select-DefaultView
           └─ 主要プロパティの出力
```

### データフロー図

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

SqlInstance ───────────▶ Connect-DbaInstance ──────────▶ $server
                              │
                         Windowsログイン取得 ──────────▶ $allWindowsLoginsGroups
                              │
FilterBy ──────────────▶ フィルタリング ───────────────▶ $windowsLogins/$windowsGroups
                              │
IgnoreDomains ─────────▶ ドメイン除外 ─────────────────▶ 検証対象ログイン
                              │
                         Get-DbaADObject ──────────────▶ AD情報
                              │
                         SID/SamAccountName照合 ───────▶ 検証結果
                              │
                         UAC属性解析 ──────────────────▶ PSCustomObject
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Test-DbaWindowsLogin.ps1 | `public/Test-DbaWindowsLogin.ps1` | ソース | メイン処理 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
