# 機能設計書 569-New-DbaLinkedServerLogin

## 概要

本ドキュメントは、dbatools PowerShellモジュールにおけるNew-DbaLinkedServerLoginコマンドレットの機能設計を定義する。本機能は、リンクサーバーへの認証マッピングを作成し、ローカルログインとリモートサーバー認証間の関連付けを構成する。

### 本機能の処理概要

**業務上の目的・背景**：リンクサーバーは、分散クエリやデータ連携において重要な役割を果たす。ローカルのSQL Serverログインがリモートサーバーにアクセスする際の認証方法を定義するリンクサーバーログインは、セキュリティと運用の両面で重要である。本機能は、特定のローカルログインをリモート資格情報にマッピングするか、パススルー認証（Impersonate）を設定するかを選択して構成を自動化する。

**機能の利用シーン**：
- リンクサーバー設定時の認証マッピング構成
- 複数リンクサーバーへの一括ログインマッピング設定
- 分散クエリのための認証設定自動化
- データウェアハウスETL処理用の接続構成
- クロスサーバークエリのための資格情報設定

**主要な処理内容**：
1. SqlInstance指定時はGet-DbaLinkedServer経由でLinkedServerオブジェクト取得
2. パイプライン入力のLinkedServerオブジェクトも処理可能
3. SMO LinkedServerLoginオブジェクトを作成
4. LocalLogin、RemoteUser、Impersonate設定
5. RemoteUserPassword設定（指定時）
6. Create()メソッドでログインマッピング作成

**関連システム・外部連携**：
- SQL Server Management Objects (SMO)のLinkedServerLoginクラス
- Get-DbaLinkedServer経由でのリンクサーバー取得
- Get-DbaLinkedServerLogin経由での作成結果取得

**権限による制御**：
- ALTER ANY LINKED SERVER権限が必要
- sysadminまたはsetupadminロールのメンバーは暗黙的に権限あり

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 76 | リンクサーバーログイン | 主機能 | リンクサーバーログインの作成 |

## 機能種別

データ作成（INSERT）/ セキュリティ管理 / CRUD操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No | 対象SQL Serverインスタンス | LinkedServer必須と連動 |
| SqlCredential | PSCredential | No | 接続用認証情報 | Windows/SQL認証対応 |
| LinkedServer | string[] | No | リンクサーバー名 | SqlInstance指定時は必須 |
| LocalLogin | string | 条件付き必須 | ローカルログイン名 | 全シナリオで必須 |
| RemoteUser | string | No | リモートユーザー名 | 明示的資格情報マッピング用 |
| RemoteUserPassword | SecureString | No | リモートユーザーパスワード | 平文送信注意 |
| Impersonate | switch | No | パススルー認証 | ローカル資格情報をそのまま使用 |
| InputObject | LinkedServer[] | No | パイプラインからのLinkedServerオブジェクト | ValueFromPipeline |
| WhatIf | switch | No | 実行シミュレーション | 変更なし |
| Confirm | switch | No | 確認プロンプト | ConfirmImpact="Low" |
| EnableException | switch | No | 例外を直接スローする | デフォルトは警告メッセージ |

### 入力データソース

- パイプライン入力：InputObjectパラメータがLinkedServerオブジェクトを受け付ける
- SqlInstance指定：Get-DbaLinkedServer経由でLinkedServerオブジェクト取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Name | string | ローカルログイン名 |
| RemoteUser | string | リモートユーザー名 |
| Impersonate | bool | パススルー認証フラグ |
| Parent | LinkedServer | 親LinkedServerオブジェクト |
| DateLastModified | DateTime | 最終更新日時 |
| State | string | SMOオブジェクト状態 |

### 出力先

- PowerShellパイプライン：Get-DbaLinkedServerLogin経由でLinkedServerLoginオブジェクト
- 作成完了後に該当ログインマッピングを再取得して出力

## 処理フロー

### 処理シーケンス

```
1. processブロックで入力検証
   └─ SqlInstance指定時はLinkedServer必須チェック
   └─ LocalLoginパラメータ必須チェック

2. SqlInstance指定時
   └─ Get-DbaLinkedServer経由でLinkedServerオブジェクト取得
   └─ $InputObjectに追加

3. 各LinkedServerに対してループ
   └─ ShouldProcess確認
   └─ New-Object LinkedServerLoginで作成
   └─ Parent、Name、RemoteUser、Impersonate設定
   └─ RemoteUserPassword設定（指定時、ConvertFrom-SecurePass使用）
   └─ Create()実行
   └─ Get-DbaLinkedServerLogin経由で結果出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SqlInstance指定?}
    B -->|Yes| C{LinkedServer指定?}
    C -->|No| D[エラー終了]
    C -->|Yes| E{LocalLogin指定?}
    B -->|No| E
    E -->|No| F[エラー終了]
    E -->|Yes| G{SqlInstance指定?}
    G -->|Yes| H[Get-DbaLinkedServer]
    G -->|No| I[InputObject使用]
    H --> J[InputObjectに追加]
    I --> J
    J --> K[LinkedServerループ開始]
    K --> L[ShouldProcess確認]
    L --> M{ShouldProcess=Yes?}
    M -->|No| N{次のLinkedServerあり?}
    M -->|Yes| O[New-Object LinkedServerLogin]
    O --> P[Parent設定]
    P --> Q{LocalLogin指定?}
    Q -->|Yes| R[Name設定]
    Q -->|No| S[Name未設定]
    R --> T{RemoteUser指定?}
    S --> T
    T -->|Yes| U[RemoteUser設定]
    T -->|No| V{RemoteUserPassword指定?}
    U --> V
    V -->|Yes| W[SetRemotePassword実行]
    V -->|No| X[Impersonate設定]
    W --> X
    X --> Y[$newLinkedServerLogin.Create]
    Y --> Z[Get-DbaLinkedServerLogin出力]
    Z --> N
    N -->|Yes| K
    N -->|No| AA[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | LinkedServer必須 | SqlInstance指定時はLinkedServerも必須 | SqlInstance指定時 |
| BR-002 | LocalLogin必須 | 全シナリオでLocalLoginは必須 | 常時 |
| BR-003 | パスワード平文送信 | RemoteUserPasswordはSQL Serverに平文送信される | RemoteUserPassword指定時 |
| BR-004 | Impersonate排他 | ImpersonateとRemoteUser/RemoteUserPasswordは論理的に排他 | 認証方式選択時 |

### 計算ロジック

特段の計算ロジックなし。SMOオブジェクトを使用した標準的なログインマッピング作成。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| LinkedServer取得 | sys.servers | SELECT | リンクサーバー情報取得 |
| ログインマッピング作成 | sys.linked_logins | INSERT | 新規ログインマッピング作成 |

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

#### sys.linked_logins（SMO経由）
| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | server_id, local_principal_id, uses_self_credential, remote_name | パラメータ値 | Create()で実行 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InputError | 入力エラー | SqlInstance指定時LinkedServer未指定 | エラーメッセージ表示後終了 |
| InputError | 入力エラー | LocalLogin未指定 | エラーメッセージ表示後終了 |
| CreateError | 作成エラー | Create()失敗 | エラー出力後、次のLinkedServerへ継続 |

### リトライ仕様

リトライ機能は実装されていない。エラー発生時は次のLinkedServerへ処理を継続する。

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

- 各ログインマッピング作成は個別のDDL操作として実行
- 複数LinkedServer処理時、一部失敗しても他は継続

## パフォーマンス要件

- SMOを使用した軽量な操作
- Get-DbaLinkedServer呼び出しによる若干のオーバーヘッド
- 複数LinkedServer指定時は順次処理

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

- **重要**: RemoteUserPasswordはSQL Serverに平文で送信される
- セキュリティ管理者への確認を推奨
- sp_addlinkedsrvloginのドキュメント参照を推奨
- 認証情報はPSCredentialオブジェクトを使用
- ALTER ANY LINKED SERVER権限が必要

## 備考

- パスワードの平文送信についてはセキュリティ上の注意が必要
- Impersonateを使用する場合は、同一ドメイン内でローカルログインがリモートサーバーでも有効である必要あり
- 作成後はGet-DbaLinkedServerLogin経由で結果を取得して出力

---

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

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

### 推奨読解順序

#### Step 1: パラメータ定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | New-DbaLinkedServerLogin.ps1 | `public/New-DbaLinkedServerLogin.ps1` | パラメータ定義（100-111行目） |

**読解のコツ**: SqlInstanceとLinkedServerの関係、LocalLoginの必須性を理解する。

**主要処理フロー**:
- **101-102行目**: SqlInstance/SqlCredential
- **103行目**: LinkedServer
- **104行目**: LocalLogin
- **105-106行目**: RemoteUser/RemoteUserPassword
- **107行目**: Impersonate

#### Step 2: 入力検証を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | New-DbaLinkedServerLogin.ps1 | `public/New-DbaLinkedServerLogin.ps1` | processブロック冒頭の検証（112-121行目） |

**主要処理フロー**:
- **113-116行目**: SqlInstance指定時LinkedServer必須チェック
- **118-121行目**: LocalLogin必須チェック

#### Step 3: メイン処理フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | New-DbaLinkedServerLogin.ps1 | `public/New-DbaLinkedServerLogin.ps1` | ログインマッピング作成（123-157行目） |

**主要処理フロー**:
- **123-125行目**: Get-DbaLinkedServer呼び出し
- **129行目**: ShouldProcess確認
- **131行目**: New-Object LinkedServerLogin
- **132行目**: Parent設定
- **134-136行目**: LocalLogin指定時Name設定
- **138-140行目**: RemoteUser設定
- **142-144行目**: SetRemotePassword実行
- **146行目**: Impersonate設定
- **148行目**: Create実行
- **150行目**: Get-DbaLinkedServerLogin出力

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

```
New-DbaLinkedServerLogin
    │
    ├─ 入力検証
    │      ├─ SqlInstance指定時LinkedServer必須チェック
    │      └─ LocalLogin必須チェック
    │
    ├─ Get-DbaLinkedServer（SqlInstance指定時）
    │
    └─ foreach $lnkSrv
           ├─ ShouldProcess確認
           │
           ├─ New-Object LinkedServerLogin
           │      ├─ Parent = $lnkSrv
           │      ├─ Name = $LocalLogin
           │      ├─ RemoteUser = $RemoteUser
           │      ├─ SetRemotePassword()（RemoteUserPassword指定時）
           │      └─ Impersonate = [boolean]$Impersonate
           │
           ├─ $newLinkedServerLogin.Create()
           │
           └─ Get-DbaLinkedServerLogin -LocalLogin $LocalLogin
```

### データフロー図

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

SqlInstance ─────────────▶ Get-DbaLinkedServer ────────────▶ $InputObject
LinkedServer                      │
                                  │
LocalLogin ──────────────▶ New-Object LinkedServerLogin ───▶ $newLinkedServerLogin
                                  │
RemoteUser ──────────────▶ RemoteUser設定 ─────────────────▶ 資格情報マッピング
                                  │
RemoteUserPassword ──────▶ SetRemotePassword ──────────────▶ パスワード設定
                                  │
Impersonate ─────────────▶ Impersonate設定 ────────────────▶ パススルー設定
                                  │
                           $newLinkedServerLogin.Create() ──▶ 作成完了
                                  │
                           Get-DbaLinkedServerLogin ───────▶ LinkedServerLogin出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| New-DbaLinkedServerLogin.ps1 | `public/New-DbaLinkedServerLogin.ps1` | ソース | メイン機能実装 |
| Get-DbaLinkedServer.ps1 | `public/Get-DbaLinkedServer.ps1` | ソース | リンクサーバー取得 |
| Get-DbaLinkedServerLogin.ps1 | `public/Get-DbaLinkedServerLogin.ps1` | ソース | 作成結果取得 |
