# 機能設計書 502-New-DbaAgentProxy

## 概要

本ドキュメントは、SQL Server Agent プロキシアカウントを新規作成する `New-DbaAgentProxy` コマンドの機能設計書である。

### 本機能の処理概要

**業務上の目的・背景**：SQL Server Agent のジョブステップは通常、SQL Agent サービスアカウントのコンテキストで実行される。しかし、セキュリティ上の理由から、特定のジョブステップを異なるセキュリティコンテキストで実行する必要がある場合がある。プロキシアカウントは、既存の SQL Server 資格情報（Credential）を使用して、ジョブステップが別の Windows アカウントの権限で実行できるようにする。本コマンドは、プロキシアカウントの作成を自動化し、サブシステムの割り当てやプリンシパルへのアクセス権付与を一括で行う。

**機能の利用シーン**：CmdExec や PowerShell ジョブステップで特定のネットワークリソースにアクセスする必要がある場合、SSIS パッケージをサービスアカウント以外の資格情報で実行する場合、Analysis Services コマンドを専用アカウントで実行する場合などに利用される。また、非 sysadmin ユーザーがプロキシを使用するジョブステップを作成できるようにするための権限付与にも使用される。

**主要な処理内容**：
1. 対象インスタンスへの接続確立（Connect-DbaInstance 使用、最小バージョン SQL Server 2005）
2. ActiveScripting サブシステムの SQL Server 2016 以降での非サポートチェック
3. 既存プロキシアカウントの確認と Force パラメータによる再作成処理
4. 指定された資格情報（ProxyCredential）の存在確認
5. SMO（ProxyAccount クラス）を使用したプロキシアカウントの作成
6. ログイン、サーバーロール、msdb ロールへのプロキシ使用権限付与
7. サブシステム（CmdExec、PowerShell、SSIS 等）への割り当て
8. 作成されたプロキシアカウントの出力

**関連システム・外部連携**：SQL Server Agent サービス、SQL Server 資格情報（Credential）、Windows セキュリティプリンシパル、各種サブシステム（CmdExec、PowerShell、SSIS、Analysis Services 等）

**権限による制御**：対象インスタンスで sysadmin 権限が必要。プロキシに関連付ける資格情報は事前に作成されている必要がある。プロキシ使用権限は、指定されたログイン、サーバーロール、msdb ロールのメンバーに付与される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 15 | Agentプロキシ管理 | 主画面 | SQLエージェントプロキシの新規作成 |

## 機能種別

CRUD操作（Create）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | Yes | 対象SQL Serverインスタンス | 接続可能なインスタンス名 |
| SqlCredential | PSCredential | No | 代替認証情報 | - |
| Name | string[] | Yes | 作成するプロキシアカウント名 | 必須、インスタンス内で一意 |
| ProxyCredential | string[] | Yes | 使用する資格情報名 | 必須、存在する資格情報名 |
| SubSystem | string[] | No | 割り当てるサブシステム | ActiveScripting/AnalysisCommand/AnalysisQuery/CmdExec/Distribution/LogReader/Merge/PowerShell/QueueReader/Snapshot/Ssis、既定値はCmdExec |
| Description | string | No | プロキシの説明 | - |
| Login | string[] | No | プロキシ使用権限を付与するログイン | 存在するログイン名 |
| ServerRole | string[] | No | プロキシ使用権限を付与するサーバーロール | 存在するサーバーロール名 |
| MsdbRole | string[] | No | プロキシ使用権限を付与するmsdbロール | 存在するmsdbロール名 |
| Disabled | switch | No | 無効状態で作成 | - |
| Force | switch | No | 既存プロキシの再作成 | - |
| EnableException | switch | No | 例外を有効化 | - |

### 入力データソース

PowerShell コマンドラインからのパラメータ入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverインスタンスのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス名 |
| ID | int | プロキシアカウントID |
| Name | string | プロキシアカウント名 |
| CredentialName | string | 関連付けられた資格情報名 |
| CredentialIdentity | string | 資格情報のWindows ID |
| Description | string | プロキシの説明 |
| Logins | string[] | プロキシ使用権限を持つログイン |
| ServerRoles | string[] | プロキシ使用権限を持つサーバーロール |
| MsdbRoles | string[] | プロキシ使用権限を持つmsdbロール |
| SubSystems | string[] | 割り当てられたサブシステム |
| IsEnabled | bool | プロキシの有効状態 |

### 出力先

PowerShell パイプライン（Microsoft.SqlServer.Management.Smo.Agent.ProxyAccount オブジェクト）

## 処理フロー

### 処理シーケンス

```
1. beginブロック
   └─ Forceパラメータ指定時、ConfirmPreferenceを'none'に設定
2. processブロック（各インスタンスに対して）
   ├─ インスタンス接続（最小バージョン SQL Server 2005 / Version 9）
   ├─ ActiveScripting サブシステムの SQL Server 2016+ チェック
   ├─ JobServer オブジェクト取得（Agent サービス確認）
   └─ 各プロキシ名に対する処理ループ
       ├─ 既存プロキシの確認
       │   ├─ 存在し Force あり → 削除後再作成
       │   └─ 存在し Force なし → スキップ（警告出力）
       ├─ 資格情報の存在確認（存在しなければスキップ）
       ├─ 新規 ProxyAccount オブジェクト作成
       │   └─ Disabled スイッチに応じて有効/無効状態設定
       ├─ ProxyAccount.Create() 実行
       ├─ ログインへのプロキシ使用権限付与（AddLogin）
       ├─ サーバーロールへの権限付与（AddServerRole）
       ├─ msdb ロールへの権限付与（AddMsdbRole）
       ├─ サブシステムへの割り当て（AddSubSystem）
       ├─ Alter() と Refresh() で変更確定
       └─ 出力用プロパティ追加と Select-DefaultView で結果出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[インスタンス接続]
    B --> C{ActiveScripting + SQL 2016+?}
    C -->|Yes| D[エラー終了]
    C -->|No| E[JobServer取得]
    E --> F{プロキシ名ループ}
    F --> G{既存プロキシ存在?}
    G -->|Yes| H{Force指定?}
    H -->|No| I[警告出力、次へ]
    H -->|Yes| J[既存プロキシ削除]
    J --> K{資格情報存在?}
    G -->|No| K
    K -->|No| L[警告出力、次へ]
    K -->|Yes| M[ProxyAccount作成]
    M --> N[Create実行]
    N --> O[ログイン権限付与]
    O --> P[サーバーロール権限付与]
    P --> Q[msdbロール権限付与]
    Q --> R[サブシステム割り当て]
    R --> S[Alter/Refresh]
    S --> T[結果出力]
    T --> U{次のプロキシ?}
    U -->|Yes| F
    U -->|No| V{次のインスタンス?}
    I --> U
    L --> U
    V -->|Yes| B
    V -->|No| W[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-502-01 | 資格情報必須 | プロキシは既存の SQL Server 資格情報を参照する必要がある | 常時 |
| BR-502-02 | サブシステム既定値 | サブシステム未指定時は CmdExec が既定で割り当てられる | SubSystem未指定時 |
| BR-502-03 | ActiveScripting非サポート | ActiveScripting（ActiveX スクリプト）は SQL Server 2016 以降で廃止 | SQL Server 2016以降 |
| BR-502-04 | 既存プロキシ保護 | 同名プロキシが存在する場合、Force なしではスキップ | 常時 |
| BR-502-05 | 最小バージョン | SQL Server 2005（バージョン9）以降が必要 | 常時 |
| BR-502-06 | sysadmin権限 | デフォルトでは sysadmin のみがプロキシを使用可能、他のプリンシパルには明示的な付与が必要 | 常時 |

### 計算ロジック

特になし。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロキシ作成 | msdb.dbo.sysproxies | INSERT | SMO経由でプロキシレコード作成 |
| ログイン権限付与 | msdb.dbo.sysproxylogin | INSERT | ログインへのプロキシ使用権限 |
| サブシステム割り当て | msdb.dbo.sysproxysubsystem | INSERT | サブシステムへの割り当て |

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

#### msdb.dbo.sysproxies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | Name パラメータ値 | プロキシ名 |
| INSERT | credential_id | ProxyCredential の ID | 関連資格情報 |
| INSERT | enabled | Disabled スイッチの逆 | 有効/無効状態 |
| INSERT | description | Description パラメータ値 | 説明 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 接続エラー | インスタンスへの接続失敗 | Stop-Function で処理継続 |
| - | バージョンエラー | SQL Server 2005 未満 | Stop-Function で処理継続 |
| - | サブシステムエラー | ActiveScripting + SQL 2016以降 | Stop-Function で処理継続 |
| - | Agent エラー | SQL Agent サービス未起動 | Stop-Function で処理継続 |
| - | 資格情報エラー | 指定資格情報が存在しない | Warning 出力、次へ進む |
| - | ログインエラー | 指定ログインが存在しない | Warning 出力、処理継続 |
| - | ロールエラー | 指定サーバーロールが存在しない | Warning 出力、処理継続 |
| - | msdbロールエラー | 指定msdbロールが存在しない | Warning 出力、処理継続 |
| - | 作成エラー | プロキシ作成失敗 | Stop-Function で処理継続 |
| - | AG関連エラー | AGリスナー経由での作成試行 | 専用エラーメッセージで継続 |

### リトライ仕様

リトライ処理は実装されていない。

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

SMO の ProxyAccount.Create() および Alter() メソッドによる暗黙的トランザクション。

## パフォーマンス要件

特に定義されていない。

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

- 対象インスタンスへの sysadmin 権限が必要
- プロキシに関連付ける資格情報には、必要な Windows 権限を持つアカウントを設定すること
- 非 sysadmin ユーザーにプロキシ使用権限を付与する場合、最小権限の原則に従うこと
- プロキシを通じて実行されるジョブステップは、資格情報のアカウント権限で実行される

## 備考

- SQL Server 2005 以降をサポート（Connect-DbaInstance -MinimumVersion 9）
- ActiveScripting（ActiveX スクリプト）は SQL Server 2016 で廃止された機能
- 可用性グループリスナー経由での作成はサポートされない

---

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

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

### 推奨読解順序

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

SMO の ProxyAccount クラスと SubSystem 列挙型を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | New-DbaAgentProxy.ps1 | `public/New-DbaAgentProxy.ps1` | 143-160行目: パラメータ定義、特に SubSystem の ValidateSet |

**読解のコツ**: SubSystem パラメータの ValidateSet で使用可能なサブシステム一覧を確認できる。

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

接続処理とバージョンチェック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | New-DbaAgentProxy.ps1 | `public/New-DbaAgentProxy.ps1` | 164-180行目: 接続とバージョン/サブシステムチェック |

**主要処理フロー**:
1. **167行目**: Connect-DbaInstance -MinimumVersion 9 でSQL Server 2005以上を強制
2. **172-174行目**: ActiveScripting + SQL 2016 以降の組み合わせをチェック
3. **176-180行目**: JobServer 取得（Agent サービス確認）

#### Step 3: プロキシ作成処理を理解する

メインの作成ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaAgentProxy.ps1 | `public/New-DbaAgentProxy.ps1` | 182-276行目: プロキシ作成のメインループ |

**主要処理フロー**:
- **184-194行目**: 既存プロキシの確認と Force 処理
- **196-199行目**: 資格情報の存在確認
- **201-224行目**: ProxyAccount オブジェクト作成（Disabled考慮、AGリスナーエラー処理）
- **227-255行目**: ログイン/サーバーロール/msdbロールへの権限付与
- **257-261行目**: サブシステムへの割り当て
- **263-274行目**: Alter/Refresh と出力

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

```
New-DbaAgentProxy
    │
    ├─ Connect-DbaInstance -MinimumVersion 9 (167行目)
    │      └─ SQL Server 2005以上への接続確立
    │
    ├─ $jobServer.ProxyAccounts[$proxyName].Drop() (187行目)
    │      └─ 既存プロキシの削除（Force時）
    │
    ├─ New-Object Microsoft.SqlServer.Management.Smo.Agent.ProxyAccount (206,209行目)
    │      └─ SMO ProxyAccount オブジェクト作成
    │
    ├─ $proxy.Create() (221行目)
    │      └─ プロキシの永続化
    │
    ├─ $proxy.AddLogin() (230行目)
    │      └─ ログインへの権限付与
    │
    ├─ $proxy.AddServerRole() (239行目)
    │      └─ サーバーロールへの権限付与
    │
    ├─ $proxy.AddMsdbRole() (249行目)
    │      └─ msdbロールへの権限付与
    │
    ├─ $proxy.AddSubSystem() (259行目)
    │      └─ サブシステムへの割り当て
    │
    └─ $proxy.Alter() / $proxy.Refresh() (264-265行目)
           └─ 変更の確定と最新状態取得
```

### データフロー図

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

SqlInstance     ─────▶ Connect-DbaInstance ─────▶ Server オブジェクト
                              │
Name            ─────────────▶├─▶ プロキシ名検証
ProxyCredential ─────────────▶├─▶ 資格情報存在確認
SubSystem       ─────────────▶├─▶ サブシステム検証
Disabled        ─────────────▶│
                              ▼
                      ProxyAccount オブジェクト作成
                              │
Login           ─────────────▶├─▶ AddLogin()
ServerRole      ─────────────▶├─▶ AddServerRole()
MsdbRole        ─────────────▶├─▶ AddMsdbRole()
                              │
                              ▼
                      Create() / Alter() 実行
                              │
                              ▼
                      Select-DefaultView ─────▶ ProxyAccount オブジェクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| New-DbaAgentProxy.ps1 | `public/New-DbaAgentProxy.ps1` | ソース | メインコマンド実装 |
| Get-DbaAgentProxy.ps1 | `public/Get-DbaAgentProxy.ps1` | ソース | 既存プロキシ取得（Force時の確認用） |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | インスタンス接続 |
