# 機能設計書 538-Add-DbaServerRoleMember

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおけるAdd-DbaServerRoleMember機能の設計仕様を定義するものである。この機能はログインまたはサーバーロールをサーバーレベルロールに追加し、SQL Serverセキュリティ管理を行う。

### 本機能の処理概要

**業務上の目的・背景**：サーバーレベルのセキュリティ権限管理において、ログインやロールを固定サーバーロール（sysadmin、dbcreator等）やカスタムサーバーロールに追加する作業は頻繁に発生する。本機能は、SSMSやT-SQLスクリプトを使わずにPowerShellから一括でサーバーロールメンバーシップを管理できるようにする。ロールベースアクセス制御（RBAC）の実装を支援する。

**機能の利用シーン**：
- サーバー管理者権限の付与
- サービスアカウントへの権限設定
- カスタムサーバーロールへのログイン追加
- ロール階層の構築（ロールのネスト）
- 大規模環境での一括サーバー権限管理

**主要な処理内容**：
1. 入力タイプの判定（DbaInstanceParameter、Server、ServerRole）
2. Get-DbaServerRole経由でのサーバーロールオブジェクト取得
3. 既存メンバーシップ確認
4. AddMember()メソッドによるログイン追加
5. AddMembershipToRole()メソッドによるロール追加

**関連システム・外部連携**：
- SQL Server Management Objects (SMO) - ServerRole.AddMember(), ServerRole.AddMembershipToRole()
- Get-DbaServerRole - サーバーロールオブジェクト取得

**権限による制御**：
- 対象ロールに対するALTER権限
- securityadminまたはsysadmin固定サーバーロールのメンバーシップ

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 73 | サーバーロールメンバー | 主機能 | サーバーロールメンバーの追加 |

## 機能種別

データ作成処理（INSERT / ADD）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstance[] | No | 対象SQL Serverインスタンス。パイプライン入力可能 | 有効なSQL Server接続文字列 |
| SqlCredential | PSCredential | No | SQL Server接続用の代替認証情報 | 有効なPSCredentialオブジェクト |
| ServerRole | string[] | No | 対象サーバーロール名。パイプライン入力可能 | - |
| Login | string[] | No | 追加するログイン名 | - |
| Role | string[] | No | 追加するサーバーロール名（ロールのネスト用） | - |
| InputObject | object[] | No | パイプライン入力（ServerRole） | - |
| EnableException | switch | No | 例外を呼び出し元にスローする | - |

### 入力データソース

- パラメータ入力（コマンドライン引数）
- パイプライン入力（DbaInstance、ServerRole）

## 出力仕様

### 出力データ

なし（メンバー追加操作のため出力オブジェクトなし）

### 出力先

なし

## 処理フロー

### 処理シーケンス

```
1. 入力検証（beginブロック）
   └─ SqlInstance、ServerRole、Login すべて未指定時はエラー

2. 入力タイプ別処理（processブロック）
   ├─ DbaInstanceParameter → Get-DbaServerRole呼び出し
   ├─ Server → Get-DbaServerRole呼び出し
   └─ ServerRole → 直接使用

3. ServerRole必須検証
   └─ ServerRole以外の入力時はServerRoleパラメータ必須

4. ロールループ処理
   ├─ Login処理
   │   ├─ 既存メンバーシップ確認
   │   └─ AddMember()メソッド実行
   └─ Role処理
       ├─ 対象ロール存在確認
       └─ AddMembershipToRole()メソッド実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstance/ServerRole/Login 指定?}
    B -->|すべて未指定| C[エラー: 入力必須]
    B -->|あり| D{入力タイプ判定}
    D -->|DbaInstanceParameter| E[Get-DbaServerRole]
    D -->|Server| F[Get-DbaServerRole]
    D -->|ServerRole| G[直接使用]
    E --> H[serverRoles取得]
    F --> H
    G --> H
    H --> I{ServerRole指定必須?}
    I -->|Yes/未指定| J[エラー: ServerRole必須]
    I -->|OK| K[foreach sr in serverRoles]
    K --> L[foreach login in Login]
    L --> M{既にメンバー?}
    M -->|Yes| N[警告: 既存]
    M -->|No| O[AddMember実行]
    O --> P{次のLogin?}
    N --> P
    P -->|Yes| L
    P -->|No| Q[foreach role in Role]
    Q --> R{ロール存在?}
    R -->|No| S[警告: 不存在]
    R -->|Yes| T[AddMembershipToRole実行]
    T --> U{次のRole?}
    S --> U
    U -->|Yes| Q
    U -->|No| V{次のServerRole?}
    V -->|Yes| K
    V -->|No| W[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 入力必須 | SqlInstance/ServerRole/Loginのいずれかが必須 | 常時 |
| BR-002 | ServerRole必須条件 | ServerRole以外の入力時はServerRoleパラメータ必須 | ServerRole以外の入力時 |
| BR-003 | 重複チェック | 既にメンバーの場合は警告出力 | Login追加時 |
| BR-004 | ロール存在確認 | ネスト対象ロールが存在すること | Role追加時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ログイン追加 | sys.server_role_members | INSERT | ロールメンバーシップ追加 |
| ロール追加 | sys.server_role_members | INSERT | ロールネスト追加 |

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

#### sys.server_role_members

SMO ServerRole.AddMember()メソッド経由で以下相当のDDLが実行される：
```sql
ALTER SERVER ROLE [ロール名] ADD MEMBER [ログイン名]
```

SMO ServerRole.AddMembershipToRole()メソッド経由で以下相当のDDLが実行される：
```sql
ALTER SERVER ROLE [親ロール名] ADD MEMBER [子ロール名]
```

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 入力不足 | SqlInstance/ServerRole/Login全て未指定 | パイプまたはパラメータで入力 |
| - | ServerRole未指定 | ServerRole以外でServerRole未指定 | ServerRoleパラメータを指定 |
| - | ロール不存在 | ネスト対象ロールが存在しない | 有効なロールを指定 |
| - | 権限不足 | ALTER権限なし | 必要な権限を付与 |

### リトライ仕様

Stop-Functionにより、エラー発生時は処理を停止。ただしRole不存在時は警告のみで継続。

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

SMO ServerRole.AddMember()およびAddMembershipToRole()メソッドが内部的にトランザクションを管理する。

## パフォーマンス要件

- メンバー追加は通常即座に完了
- 多数のログイン/ロールを一括追加する場合は順次処理

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

- ALTER ANY SERVER ROLE権限またはsysadmin固定サーバーロールのメンバーシップが必要
- ConfirmImpact=Highにより、デフォルトで確認プロンプトが表示される
- サーバーロールへのメンバー追加はサーバーレベル権限に直接影響

## 備考

- sysadmin等の固定サーバーロールにも対応
- カスタムサーバーロール（SQL Server 2012以降）にも対応
- ロールのネスト（ロール内にロールを追加）も可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Add-DbaServerRoleMember.ps1 | `public/Add-DbaServerRoleMember.ps1` | 出力なし（追加操作）- .OUTPUTSセクション確認 |

**読解のコツ**: 追加操作のため出力オブジェクトはない。処理結果はVerboseメッセージまたは警告で示される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Add-DbaServerRoleMember.ps1 | `public/Add-DbaServerRoleMember.ps1` | param()ブロック（101-113行目）でパラメータ定義確認 |

**主要処理フロー**:
1. **115-124行目**: beginブロックでの入力検証
2. **125行目**: processブロック開始
3. **128-165行目**: 入力タイプ別のswitch処理
4. **131-134行目**: ServerRoleパラメータ必須チェック
5. **167-205行目**: ロール/Login/Roleループと追加処理

#### Step 3: メンバー追加ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Add-DbaServerRoleMember.ps1 | `public/Add-DbaServerRoleMember.ps1` | 167-205行目のメンバー追加処理 |

**主要処理フロー**:
- **169-183行目**: Login追加処理
  - **170行目**: EnumMemberNames()で既存メンバー確認
  - **177行目**: AddMember()実行
- **184-203行目**: Role追加処理
  - **186行目**: Get-DbaServerRoleでロール存在確認
  - **198行目**: AddMembershipToRole()実行

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

```
Add-DbaServerRoleMember
    │
    ├─ begin: 入力パラメータ検証
    │      └─ SqlInstance/ServerRole/Login チェック
    │
    ├─ 入力タイプ判定（GetType().FullName）
    │      ├─ DbaInstanceParameter
    │      ├─ Server
    │      └─ ServerRole
    │
    ├─ Get-DbaServerRole（ロールオブジェクト取得）
    │      └─ ServerRole フィルタ
    │
    └─ foreach sr in serverRoles
           ├─ foreach login
           │      ├─ EnumMemberNames()（既存メンバー確認）
           │      ├─ ShouldProcess確認
           │      └─ AddMember()（ログイン追加）
           │
           └─ foreach role
                  ├─ Get-DbaServerRole（ロール存在確認）
                  ├─ ShouldProcess確認
                  └─ AddMembershipToRole()（ロール追加）
```

### データフロー図

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

SqlInstance ─────────▶ 入力タイプ判定
      or                      │
InputObject ─────────────────┤
(Server/ServerRole)          │
                              ▼
                       Get-DbaServerRole ─────────▶ ServerRole[]
                              │
ServerRole[] ────────────────┤
                              │
Login[] ─────────────────────┤
                              ▼
                       EnumMemberNames()
                              │
                              ▼
                       重複確認 ───────────────────▶ 警告（既存の場合）
                              │
                              ▼
                       AddMember() ───────────────▶ (なし)

Role[] ──────────────────────┤
                              ▼
                       Get-DbaServerRole
                       (存在確認) ────────────────▶ 警告（不存在の場合）
                              │
                              ▼
                       AddMembershipToRole() ─────▶ (なし)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Add-DbaServerRoleMember.ps1 | `public/Add-DbaServerRoleMember.ps1` | ソース | メイン機能実装 |
| Get-DbaServerRole.ps1 | `public/Get-DbaServerRole.ps1` | ソース | サーバーロール取得 |
