# 機能設計書 479-Copy-DbaAgentProxy

## 概要

本ドキュメントは、SQL Server Agentのプロキシアカウントをソースインスタンスから宛先インスタンスにコピーするPowerShellコマンド「Copy-DbaAgentProxy」の機能設計書である。

### 本機能の処理概要

Copy-DbaAgentProxyは、SQL Server Agentのプロキシアカウント設定をソースインスタンスから1つ以上の宛先インスタンスにコピーする機能である。プロキシアカウントは、ジョブステップがSQL Agentサービスアカウント以外のセキュリティコンテキストで実行できるようにする。

**業務上の目的・背景**：ジョブステップがOSコマンド、PowerShellスクリプト、SSIS パッケージなどを実行する場合、適切な権限を持つプロキシアカウントが必要である。サーバー移行時にこれらのプロキシアカウントを正確に再作成することは、ジョブの正常動作に不可欠である。本機能を使用することで、プロキシアカウントの設定を効率的に移行でき、関連する資格情報の依存関係も自動的にチェックされる。

**機能の利用シーン**：
- 本番サーバーから災害復旧サーバーへのプロキシアカウント構成の複製
- 新規サーバー構築時のプロキシアカウント設定の展開
- サーバー統合・移行プロジェクトでのプロキシアカウント移行
- 複数環境間でのプロキシアカウント設定の標準化

**主要な処理内容**：
1. ソースサーバーへの接続とプロキシアカウント一覧の取得
2. フィルタリング（ProxyAccount/ExcludeProxyAccount）
3. 宛先サーバーへの接続
4. 各プロキシアカウントの関連資格情報の存在確認
5. 既存プロキシアカウントとの重複チェック
6. SMOスクリプトによるプロキシアカウントの作成
7. 処理結果の出力

**関連システム・外部連携**：SQL Server Agentサービス、msdbデータベース、資格情報（Credentials）。

**権限による制御**：ソースおよび宛先の両方でsysadmin固定サーバーロールのメンバーシップが必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | SQL Server Management Studio - SQL Server Agent - Proxies | 参照画面 | プロキシアカウント設定の確認 |

## 機能種別

データ移行処理 / SMOスクリプティング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Source | DbaInstanceParameter | Yes | コピー元SQL Serverインスタンス | SQL Server 2005以上（MinimumVersion 9） |
| SourceSqlCredential | PSCredential | No | ソース接続用の資格情報 | - |
| Destination | DbaInstanceParameter[] | Yes | コピー先SQL Serverインスタンス（複数可） | SQL Server 2005以上（MinimumVersion 9） |
| DestinationSqlCredential | PSCredential | No | 宛先接続用の資格情報 | - |
| ProxyAccount | string[] | No | コピーするプロキシアカウント名 | - |
| ExcludeProxyAccount | string[] | No | 除外するプロキシアカウント名 | - |
| Force | switch | No | 既存プロキシアカウントを削除して再作成 | - |
| WhatIf | switch | No | 実行内容のプレビュー | - |
| Confirm | switch | No | 実行前の確認プロンプト | - |
| EnableException | switch | No | 例外をスローするかどうか | - |

### 入力データソース

- ソースSQL ServerのJobServer.ProxyAccountsコレクション

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DateTime | DbaDateTime | 処理実行日時 |
| SourceServer | string | ソースSQL Serverインスタンス名 |
| DestinationServer | string | 宛先SQL Serverインスタンス名 |
| Name | string | プロキシアカウント名または資格情報名 |
| Type | string | オブジェクトタイプ（Agent Proxy, Credential, ProxyAccount） |
| Status | string | 処理結果（Successful, Failed, Skipped, Skipping） |
| Notes | string | 追加情報（スキップ理由など） |

### 出力先

パイプライン出力（PSCustomObject - MigrationObject）

## 処理フロー

### 処理シーケンス

```
1. ソースサーバー接続（begin）
   └─ Connect-DbaInstance -MinimumVersion 9でソースに接続
2. プロキシアカウントのフィルタリング
   └─ ProxyAccount/ExcludeProxyAccountでフィルタ
3. 宛先サーバー接続（process）
   └─ Connect-DbaInstance -MinimumVersion 9で宛先に接続
4. 各プロキシアカウントの処理（foreach account）
   ├─ 資格情報名の空チェック
   ├─ 宛先での関連資格情報の存在確認
   ├─ 既存プロキシアカウントの確認
   │   ├─ 既存でForceなし: スキップ
   │   └─ 既存でForceあり: 削除して再作成
   └─ Script()でプロキシアカウント作成
5. 結果出力
   └─ 各操作ごとにMigrationObjectを出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[ソースサーバー接続]
    B --> C{接続成功?}
    C -->|No| D[エラー終了]
    C -->|Yes| E[プロキシアカウント一覧取得]
    E --> F{ProxyAccountフィルタ?}
    F -->|Yes| G[指定プロキシのみ抽出]
    F -->|No| H{ExcludeProxyAccountフィルタ?}
    G --> H
    H -->|Yes| I[除外プロキシを除去]
    H -->|No| J[foreach 宛先インスタンス]
    I --> J
    J --> K[宛先サーバー接続]
    K --> L[foreach プロキシアカウント]
    L --> M{資格情報名が空?}
    M -->|Yes| N[Skipped: 資格情報名が空]
    M -->|No| O{宛先に資格情報存在?}
    O -->|No| P[Skipped: 資格情報なし]
    O -->|Yes| Q{宛先に既存?}
    Q -->|Yes| R{Force指定?}
    R -->|No| S[Skipped: 既に存在]
    R -->|Yes| T[既存プロキシ削除]
    Q -->|No| U[プロキシアカウント作成]
    T --> U
    U --> V{作成成功?}
    V -->|Yes| W[Successful]
    V -->|No| X{サブシステムエラー?}
    X -->|Yes| Y[Skipping: サブシステムなし]
    X -->|No| Z[Failed]
    N --> AA[次のプロキシへ]
    P --> AA
    S --> AA
    W --> AA
    Y --> AA
    Z --> AA
    AA --> L
    L --> J
    J --> AB[終了]
    D --> AB
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 資格情報依存 | プロキシアカウントの関連資格情報が宛先に存在しない場合はスキップ | 常時 |
| BR-002 | 空資格情報名スキップ | 資格情報名が空または未設定のプロキシはスキップ | 常時 |
| BR-003 | Force動作 | Forceが指定された場合、既存プロキシを削除して再作成 | 宛先に同名プロキシが存在する場合 |
| BR-004 | サブシステムエラー処理 | サブシステムが宛先に存在しない場合は警告付きでスキップ | SSIS等の特定サブシステム使用時 |
| BR-005 | 最小バージョン | SQL Server 2005以降が必要 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロキシ削除 | msdb.dbo.sysproxies | DELETE | SMO Drop()により削除 |
| プロキシ作成 | msdb.dbo.sysproxies | INSERT | SMO Script()で生成したT-SQLを実行 |

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

#### msdb.dbo.sysproxies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | proxy_id, name, credential_id, enabled, description | ソースプロキシの設定値 | SMO Script()で生成 |
| DELETE | - | WHERE name = @proxyName | SMO Drop()で削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ConnectionError | 接続エラー | ソースまたは宛先に接続できない | Stop-Functionで処理を中断 |
| CredentialMissing | 資格情報不足 | 関連資格情報が宛先に存在しない | Skippedとして記録し次のプロキシへ |
| EmptyCredential | 資格情報名なし | 資格情報名が空または未設定 | Skippedとして記録し次のプロキシへ |
| SubsystemError | サブシステムエラー | サブシステムが宛先に存在しない | Skippingとして記録し次のプロキシへ |
| DropError | 削除エラー | 既存プロキシの削除に失敗 | Failedとして記録し次のプロキシへ |
| CreateError | 作成エラー | プロキシの作成に失敗 | Failedとして記録し次のプロキシへ |

### リトライ仕様

リトライ処理は実装されていない。エラー発生時は次のプロキシの処理に移行する。

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

個々のプロキシ作成操作は独立したトランザクションとして実行される。一括トランザクションは使用されない。

## パフォーマンス要件

特になし。プロキシ数に比例して処理時間が増加するが、通常は数秒程度。

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

- ソースおよび宛先の両方でsysadmin権限が必要
- SQL認証使用時は資格情報がSecureStringとして管理される
- プロキシアカウントは異なるセキュリティコンテキストでジョブを実行するため、適切な権限管理が重要
- WhatIfパラメータによる事前確認が可能

## 備考

- プロキシアカウントはSQL Server 2005以降でサポート
- 関連する資格情報（Credential）は事前にCopy-DbaCredentialで移行しておく必要がある
- ジョブ移行前にプロキシアカウントを移行する必要がある

---

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

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

### 推奨読解順序

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

SMOのProxyAccountオブジェクトの構造と、資格情報との依存関係を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Copy-DbaAgentProxy.ps1 | `public/Copy-DbaAgentProxy.ps1` | 115行目で$sourceServer.JobServer.ProxyAccountsを取得 |

**読解のコツ**: ProxyAccountオブジェクトは.Name、.CredentialName、.Description等のプロパティを持ち、Script()メソッドでT-SQLを生成できる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Copy-DbaAgentProxy.ps1 | `public/Copy-DbaAgentProxy.ps1` | 95-107行目のパラメータ定義、108-123行目のbeginブロック |

**主要処理フロー**:
1. **108-122行目**: beginブロックでソース接続（MinimumVersion 9）とフィルタリング
2. **135-161行目**: 資格情報名の空チェックと宛先資格情報の存在確認
3. **180-206行目**: 既存確認とForce処理
4. **208-235行目**: Script()でプロキシ作成（サブシステムエラー処理含む）

#### Step 3: 資格情報依存チェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Copy-DbaAgentProxy.ps1 | `public/Copy-DbaAgentProxy.ps1` | 148行目と163-178行目の資格情報チェック |

**主要処理フロー**:
- **148行目**: $account.CredentialNameで資格情報名を取得
- **153-161行目**: 資格情報名が空の場合はスキップ
- **163-178行目**: $destServer.Credentials[$CredentialName]で宛先資格情報の存在確認

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

```
Copy-DbaAgentProxy
    │
    ├─ Connect-DbaInstance -MinimumVersion 9（Source）
    │      └─ ソースサーバー接続
    │
    ├─ $sourceServer.JobServer.ProxyAccounts
    │      └─ プロキシアカウント一覧取得
    │
    ├─ ProxyAccount/ExcludeProxyAccountフィルタ
    │      └─ beginブロックでフィルタリング
    │
    ├─ Connect-DbaInstance -MinimumVersion 9（Destination）
    │      └─ 宛先サーバー接続
    │
    ├─ $destServer.Credentials[$CredentialName]
    │      └─ 資格情報存在確認
    │
    ├─ $destServer.JobServer.ProxyAccounts[$proxyName].Drop()
    │      └─ 既存プロキシの削除（Force時）
    │
    ├─ $account.Script()
    │      └─ プロキシ作成スクリプト生成
    │
    └─ $destServer.Query()
           └─ T-SQL実行（sp_add_proxy）
```

### データフロー図

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

Source           ───▶ Connect-DbaInstance ───▶ $sourceServer
                                │
                                ▼
$sourceServer.JobServer.ProxyAccounts ───▶ フィルタリング
                                │
Destination      ───▶ Connect-DbaInstance ───▶ $destServer
                                │
                                ▼
各プロキシ ───▶ 資格情報依存チェック ───▶ スキップ or 続行
                    │
                    ▼
           既存確認 / Force処理
                    │
                    ▼
           Script()でT-SQL生成 ───▶ Query()で実行
                    │
                    ├─ サブシステムエラー ───▶ Skipping
                    │
                    ▼
                [MigrationObject出力]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Copy-DbaAgentProxy.ps1 | `public/Copy-DbaAgentProxy.ps1` | ソース | メイン処理ロジック |
| Copy-DbaCredential.ps1 | `public/Copy-DbaCredential.ps1` | ソース | 資格情報コピー（プロキシの前提） |
| Copy-DbaAgentJob.ps1 | `public/Copy-DbaAgentJob.ps1` | ソース | ジョブコピー（プロキシが前提） |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続用コマンド |
