# 機能設計書 516-Set-DbaAgentJobOwner

## 概要

本ドキュメントは、SQL Server Agentジョブの所有者を変更するdbatools関数「Set-DbaAgentJobOwner」の機能設計書である。

### 本機能の処理概要

Set-DbaAgentJobOwnerは、SQL Server Agentジョブの所有者を指定されたログインに統一する機能を提供する。

**業務上の目的・背景**：SQL Server Agentジョブの所有者は、ジョブ実行時のセキュリティコンテキストに影響を与える。組織のセキュリティポリシーとして、ジョブを特定のアカウント（一般的には'sa'または専用のサービスアカウント）が所有することが推奨される。移行後のクリーンアップ、ユーザーアカウント削除前の所有権移譲、環境間の設定標準化などのシナリオで、本機能を使用してジョブ所有者を一括変更できる。

**機能の利用シーン**：
- セキュリティコンプライアンス監査への対応
- 移行後のジョブ所有者の整理
- 退職者アカウントからの所有権移譲
- 環境間でのジョブ所有者の標準化
- ベストプラクティスに基づくsysadminアカウントへの所有権統一

**主要な処理内容**：
1. 対象SQL Serverインスタンスへの接続
2. 対象ジョブの収集（ローカルジョブのみ）
3. ターゲットログインの検証
4. 所有者の変更（OwnerLoginNameプロパティ更新）
5. SMO Alter()メソッドによる変更のコミット
6. 処理結果のステータス出力

**関連システム・外部連携**：SQL Server JobServer.Jobs、Logins

**権限による制御**：ジョブ所有者の変更には適切な権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | SQL Server Management Studio - Job Properties | 参照画面 | ジョブ所有者の確認・変更 |
| - | PowerShell Console | 主画面 | コマンド実行インターフェース |

## 機能種別

データ更新操作 (UPDATE)

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No | 対象SQL Serverインスタンス | パイプライン入力可 |
| SqlCredential | PSCredential | No | 代替認証資格情報 | - |
| Job | object[] | No | 対象ジョブ名 | エイリアス: Jobs |
| ExcludeJob | object[] | No | 除外するジョブ名 | - |
| InputObject | Job[] | No | パイプラインからのジョブオブジェクト | - |
| Login | string | No | ターゲット所有者ログイン | 有効なログイン名、Windowsグループ不可。エイリアス: TargetLogin。デフォルト: 'sa' |
| EnableException | switch | No | 例外処理を有効化 | - |

### 入力データソース

- Get-DbaAgentJobコマンドからのパイプライン入力
- SQL Server JobServer.Jobsコレクション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverのコンピュータ名 |
| InstanceName | string | インスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス名 |
| Name | string | ジョブ名 |
| Category | string | ジョブカテゴリ |
| OwnerLoginName | string | 更新後の所有者ログイン名 |
| Status | string | 処理結果（Skipped/Failed/Successful） |
| Notes | string | 追加情報（スキップ/失敗理由） |

### 出力先

PowerShellパイプライン（Microsoft.SqlServer.Management.Smo.Agent.Job + NoteProperty）

## 処理フロー

### 処理シーケンス

```
1. 各インスタンスの処理（processブロック）
   ├─ Connect-DbaInstanceで接続
   └─ ジョブの収集
       ├─ Job指定あり: 名前でフィルタ
       └─ Job指定なし: ローカルジョブのみ
   └─ ExcludeJobの適用

2. 各ジョブの処理
   ├─ ターゲットログインの決定
   │   ├─ Login指定あり: 指定値を使用
   │   └─ Login指定なし: ID=1のログイン（saまたはリネームされたsa）を自動検出
   │
   ├─ 検証チェック
   │   ├─ 所有者が既にターゲットと同じ → Skipped
   │   ├─ ターゲットログインが存在しない → Failed
   │   └─ ターゲットがWindowsグループ → Failed
   │
   └─ 所有者変更処理
       ├─ ShouldProcess確認
       ├─ OwnerLoginName更新
       ├─ Alter()メソッド呼び出し
       └─ Status/Notes設定

3. 結果出力
   └─ Select-DefaultViewで表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[各インスタンスをループ]
    B --> C[Connect-DbaInstance]
    C --> D{Job指定?}
    D -->|Yes| E[名前でフィルタ]
    D -->|No| F[ローカルジョブのみ取得]
    E --> G[ExcludeJob適用]
    F --> G
    G --> H[InputObjectに追加]
    H --> I[各ジョブをループ]
    I --> J{Login指定?}
    J -->|Yes| K[指定値をターゲットに]
    J -->|No| L[ID=1ログインを自動検出]
    K --> M{所有者が既にターゲット?}
    L --> M
    M -->|Yes| N[Status=Skipped, Notes=Owner already set]
    M -->|No| O{ターゲットログイン存在?}
    O -->|No| P[Status=Failed, Notes=Login not valid]
    O -->|Yes| Q{Windowsグループ?}
    Q -->|Yes| R[Status=Failed, Notes=Windows Group]
    Q -->|No| S[ShouldProcess確認]
    S --> T[OwnerLoginName更新]
    T --> U[Alter実行]
    U --> V[Status=Successful]
    N --> W[NoteProperty追加]
    P --> W
    R --> W
    V --> W
    W --> X[Select-DefaultView]
    X --> Y{次のジョブ?}
    Y -->|Yes| I
    Y -->|No| Z{次のインスタンス?}
    Z -->|Yes| B
    Z -->|No| AA[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | デフォルト所有者 | Login未指定時はID=1のログイン（通常sa）を使用 | Login未指定時 |
| BR-002 | 所有者重複スキップ | 所有者が既にターゲットと同じ場合はスキップ | OwnerLoginName = newLogin |
| BR-003 | ログイン存在確認 | ターゲットログインがインスタンスに存在する必要がある | 常時 |
| BR-004 | Windowsグループ除外 | Windowsグループはジョブ所有者として使用不可 | LoginType = WindowsGroup |
| BR-005 | ローカルジョブのみ | Job未指定時はローカルジョブのみ対象（MultiServerジョブは除外） | Job未指定時 |

### 計算ロジック

**saの自動検出**：
```powershell
$newLogin = ($server.logins | Where-Object { $_.id -eq 1 }).Name
```
これにより、'sa'がリネームされている環境でも正しいsysadminアカウントを検出できる。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ジョブ更新 | msdb.dbo.sysjobs | UPDATE | 所有者の更新 |

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

#### msdb.dbo.sysjobs

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | owner_sid | ターゲットログインのSID | OwnerLoginNameプロパティ経由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ConnectionError | インスタンス接続失敗 | 接続情報を確認 |
| - | Skipped | 所有者が既にターゲットと同じ | 対応不要 |
| - | Failed | ターゲットログインが存在しない | 有効なログイン名を指定 |
| - | Failed | ターゲットがWindowsグループ | 個別ユーザーまたはSQLログインを指定 |
| - | Stop-Function | 所有者変更失敗 | エラーメッセージを確認 |

### リトライ仕様

リトライ機能なし。

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

SMOのAlter()メソッドによる暗黙的トランザクション。各ジョブの更新は個別のトランザクション。

## パフォーマンス要件

特に定義なし。

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

- ジョブ所有者の変更は監査対象となりうる重要な操作
- ジョブの実行セキュリティコンテキストに影響を与える
- ベストプラクティス: https://www.itprotoday.com/sql-server-tip-assign-ownership-jobs-sysadmin-account
- WhatIf/Confirmパラメータによる事前確認が可能

## 備考

- SQL Server 2000以上に対応
- パイプライン処理でGet-DbaAgentJobからの入力に対応
- 複数サーバー・複数ジョブの一括処理に対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Microsoft.SqlServer.Management.Smo.Agent.Job | SMO | ジョブオブジェクトのプロパティ（OwnerLoginName, JobType） |
| 1-2 | Microsoft.SqlServer.Management.Smo.Login | SMO | ログインオブジェクトのプロパティ（ID, LoginType） |

**読解のコツ**: JobTypeがLocalのジョブのみ対象。ログインIDが1のものがsa（またはリネームされたsa）である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Set-DbaAgentJobOwner.ps1 | `public/Set-DbaAgentJobOwner.ps1` | 関数定義、パラメータ、processブロック構造 |

**主要処理フロー**:
1. **108-121行目**: CmdletBinding属性とパラメータ定義
2. **122-194行目**: processブロック - メイン処理

#### Step 3: ジョブ収集ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Set-DbaAgentJobOwner.ps1 | `public/Set-DbaAgentJobOwner.ps1` | ジョブフィルタリングロジック |

**主要処理フロー**:
- **134-138行目**: Job指定/未指定でのフィルタリング
- **140-142行目**: ExcludeJobの適用

#### Step 4: 所有者変更処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Set-DbaAgentJobOwner.ps1 | `public/Set-DbaAgentJobOwner.ps1` | 所有者変更ロジック |

**主要処理フロー**:
- **152-157行目**: ターゲットログインの決定
- **159-186行目**: 検証と所有者変更
- **187-192行目**: NotePropertyの追加と出力

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

```
Set-DbaAgentJobOwner
    │
    ├─ Connect-DbaInstance
    │
    ├─ JobServer.Jobs (ジョブコレクション)
    │      ├─ Where-Object Name -contains Job (フィルタ)
    │      └─ Where-Object JobType -eq Local (ローカルのみ)
    │
    ├─ Logins (ログイン検証)
    │      └─ Where-Object { $_.id -eq 1 } (saの検出)
    │
    ├─ Job.OwnerLoginName = $newLogin (更新)
    │
    ├─ Job.Alter() (コミット)
    │
    ├─ Add-Member NoteProperty (Status, Notes追加)
    │
    └─ Select-DefaultView (出力)
```

### データフロー図

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

SqlInstance ─────────▶ Connect-DbaInstance
      │                        │
Job名（任意）─────────▶ ジョブフィルタリング
      │                ├─ 名前フィルタ
      │                └─ ローカルジョブのみ
      │                        │
ExcludeJob ──────────▶ 除外フィルタ
      │                        │
Login（任意）─────────▶ ターゲット決定
      │                ├─ 指定値
      │                └─ ID=1ログイン
      │                        │
InputObject ─────────▶ 各ジョブを処理
                              │
                              ▼
                       検証チェック
                       ├─ 所有者重複
                       ├─ ログイン存在
                       └─ Windowsグループ
                              │
                              ▼
                       OwnerLoginName更新
                              │
                              ▼
                         Alter()
                              │
                              ▼
                    Add-Member NoteProperty
                              │
                              ▼
                   Select-DefaultView ───▶ [Jobオブジェクト出力]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Set-DbaAgentJobOwner.ps1 | `public/Set-DbaAgentJobOwner.ps1` | ソース | メイン関数 |
| Get-DbaAgentJob.ps1 | `public/Get-DbaAgentJob.ps1` | ソース | ジョブ取得（パイプライン入力元） |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続 |
