# カスタムプラグイン統合ガイド

## カスタムプラグイン統合ガイド <a href="#custom-plugin-integration-guide" id="custom-plugin-integration-guide"></a>

本ガイドでは、カスタム実行ファイルを管理プラグインとして登録する方法を説明します。管理プラグインとは、エージェントが起動・監視・再起動し、自身のライフサイクルに組み込む常駐コンポーネントです。まだ[統合の概要](https://github.com/Keeper-Security/gitbook-jp-secrets-manager/blob/main/endpoint-privilege-manager/integrations/endpoint-privilege-manager/integrations/overview.md)を読んでいない場合はそちらから始めてください。プラグインパターンの定義、ジョブタスクよりプラグインが適する場合、本ガイドの前提となる概念がまとまっています。

スケジュールで動いて終了するツール (スキャナー、レポート、メンテナンスジョブなど) を作る場合は[カスタムジョブ統合ガイド](/keeperpam/jp/endpoint-privilege-manager/integrations/custom-job-guide.md)をご参照ください。本ガイドは常駐プロセス向けです。

{% stepper %}
{% step %}

### プラグインJSONファイル <a href="#the-plugin-json-file" id="the-plugin-json-file"></a>

#### 場所と命名 <a href="#location-and-naming" id="location-and-naming"></a>

プラグインは次の場所にJSONファイルを置くことで登録されます。

```
{AgentRoot}/Plugins/{PluginId}.json
```

`.json` を除いたファイル名は、ファイル内の `id` フィールドと一致する必要があります。`MyBridge.json` には `"id": "MyBridge"` を含めます。プラグインIDはプラグイン設定呼び出し `GET /api/PluginSettings/MyBridge` のキーにもなるため、安定した一意の識別子を選び、デプロイ後に変更しないでください。

バイナリは通常次の場所に置きます。

```
{AgentRoot}/Plugins/bin/{PluginId}/{PluginId}.exe    (Windows)
{AgentRoot}/Plugins/bin/{PluginId}/{PluginId}        (Linux / macOS)
```

JSONの `executablePath` にはエージェントルートからの相対パス、またはデプロイレイアウト上必要なら絶対パスを指定します。

#### プラグインの構造 (JSON) <a href="#anatomy-of-a-plugin-json" id="anatomy-of-a-plugin-json"></a>

注釈付きの完全な例です。

```json
{
  "id": "MyBridge",
  "name": "My Bridge",
  "description": "Bridges inbound commands to an internal service.",
  "version": "1.0.0",

  "pluginType": "Executable",
  "executablePath": "bin/MyBridge/MyBridge.exe",
  "supportedPlatforms": ["Windows"],

  "Subscription": {
    "Topic": "MyBridge",
    "Qos": 2,
    "CleanSession": true
  },

  "metadata": {
    "mqttRole": ["subscriber", "publisher"],
    "mqttTopics": {
      "publish": ["KeeperLogger", "MyBridge/Responses/+"],
      "subscribe": ["MyBridge/Commands/+"]
    }
  },

  "startupPriority": 60,
  "autoStart": true,
  "executionContext": "Service",
  "requiresMonitoring": true,
  "autoRestart": true
}
```

#### フィールドの説明 <a href="#field-reference" id="field-reference"></a>

<table><thead><tr><th width="258.066650390625">フィールド</th><th width="106.33349609375">必須</th><th>説明</th></tr></thead><tbody><tr><td><code>id</code></td><td>はい</td><td>安定した識別子。ファイル名と一致させる。<code>/api/PluginSettings/{id}</code> のキーとして使われる。</td></tr><tr><td><code>name</code></td><td>いいえ</td><td>ログや管理画面に表示される名前。</td></tr><tr><td><code>description</code></td><td>いいえ</td><td>人が読める説明。</td></tr><tr><td><code>version</code></td><td>いいえ</td><td>セマンティックバージョン文字列。診断と変更追跡に使う。</td></tr><tr><td><code>pluginType</code></td><td>はい</td><td>単体バイナリの場合は <code>Executable</code>。その他の型はエージェントのバージョンによる。管理者に確認する。</td></tr><tr><td><code>executablePath</code></td><td>はい</td><td>バイナリへのパス。エージェントルート相対または絶対。</td></tr><tr><td><code>arguments</code></td><td>いいえ</td><td>起動時にバイナリへ渡すコマンドライン引数。一部の変数置換に対応。利用可能なトークンは管理者に確認する。</td></tr><tr><td><code>supportedPlatforms</code></td><td>はい</td><td><code>"Windows"</code>、<code>"Linux"</code>、<code>"macOS"</code> の配列。</td></tr><tr><td><code>Subscription</code></td><td>はい</td><td>このプラグインの主MQTT購読。<a href="#mqtt-for-plugins">プラグイン向けMQTT</a> をご参照ください。</td></tr><tr><td><code>metadata</code></td><td>はい</td><td><code>mqttTopics</code> とプラグイン固有キーのコンテナ。</td></tr><tr><td><code>metadata.mqttTopics.publish</code></td><td>はい</td><td>パブリッシュしてよいトピック。ブローカーがこのリストを強制する。</td></tr><tr><td><code>metadata.mqttTopics.subscribe</code></td><td>はい</td><td>主たる <code>Subscription</code> トピック以外で購読するトピック。</td></tr><tr><td><code>startupPriority</code></td><td>いいえ</td><td>プラグイン起動順。小さいほど先。デプロイ内の他プラグインの値を見て、依存関係に合う値を選ぶ。</td></tr><tr><td><code>autoStart</code></td><td>いいえ</td><td><code>true</code> でエージェント起動時に自動起動。<code>false</code> はオンデマンドやジョブ起動。省略時は <code>false</code>。</td></tr><tr><td><code>executionContext</code></td><td>いいえ</td><td><code>Service</code> でエージェントのサービスアカウントとして実行。セキュリティ要件に合わせる。</td></tr><tr><td><code>requiresMonitoring</code></td><td>いいえ</td><td><code>true</code> でエージェントがプロセスを監視し、想定外終了を検知する。</td></tr><tr><td><code>autoRestart</code></td><td>いいえ</td><td><code>true</code> で監視が停止を検知したときに再起動。<code>requiresMonitoring</code> も <code>true</code> のときに意味がある。</td></tr><tr><td><code>enabled</code></td><td>いいえ</td><td><code>false</code> にすると登録のみで実行しない。開発時に便利。</td></tr></tbody></table>
{% endstep %}

{% step %}

#### プラグイン向けMQTT <a href="#mqtt-for-plugins" id="mqtt-for-plugins"></a>

プラグインはジョブタスクとは、MQTTブローカーとのやり取りが次の3点で異なります。

1. 主たる `Subscription` がある。
2. ジョブのルートではなく `metadata.mqttTopics` 下でトピックを宣言する。
3. MQTTクライアントIDの形式が異なる。

**主購読**

各プラグインは主MQTT購読を宣言します。

```json
"Subscription": {
  "Topic": "MyBridge",
  "Qos": 2,
  "CleanSession": true
}
```

エージェントがプラグインを名前付きコンポーネントとして識別し通信するために使うトピックです。`metadata.mqttTopics` で宣言する追加トピックとは別です。欠落や重複が許されないコマンドには `Qos: 2` を使います。永続セッションが必要なユースケースでない限り `CleanSession: true` にします。

**パブリッシュ・購読トピックの宣言**

パブリッシュまたは購読するすべてのトピックを `metadata.mqttTopics` に宣言します。ブローカーがリストを強制するため、未宣言トピックへのパブリッシュは接続に成功しても拒否されます。

```json
"metadata": {
  "mqttTopics": {
    "publish": ["KeeperLogger", "MyBridge/Responses/+"],
    "subscribe": ["MyBridge/Commands/+"]
  }
}
```

実際に使うものだけを宣言します。`#` のような広いワイルドカードは本当に必要な場合に限ります。トピックリストを絞ると誤構成の影響範囲を抑えられます。

`KeeperLogger` へログを出す場合は `publish` に含めます。メッセージ形式は[カスタムジョブ統合ガイド](/keeperpam/jp/endpoint-privilege-manager/integrations/custom-job-guide.md)で説明する `RequestMessage` JSON構造と同じです。

**プラグイン向けMQTTクライアントID形式**

プラグインのMQTTクライアントIDはジョブタスクとは形式が異なります。ジョブの3要素 (`{JobId}_{Token}_{Pid}`) をプラグインに使わないでください。ブローカーはクライアントID形式でトピック権限チェックを振り分けるため、誤った形式ではチェックに失敗します。

サービスアカウントで動作するプラグイン (一般的なケース) の例:

```
{PluginName}_{ProcessId}
```

ユーザーセッションで動作するプラグインの例:

```
{PluginName}_{UserName}_{ProcessId}
```

`{PluginName}` は短い固定トークンで、多くの場合プラグインの `id` に揃えます。完全な例:

```python
import os

plugin_name = "MyBridge"
pid = os.getpid()
client_id = f"{plugin_name}_{pid}"
# 例: "MyBridge_51204"
```

**ブローカーへの接続**

ブローカーアドレスは環境変数として注入されません。起動時にジョブタスクと同様、プラグイン設定から取得します。エージェントが提供する `KeeperApiBaseUrl` を使って `GET /api/PluginSettings/KeeperPrivilegeManager` を呼びます。コード例は[概要](https://github.com/Keeper-Security/gitbook-jp-secrets-manager/blob/main/endpoint-privilege-manager/integrations/endpoint-privilege-manager/integrations/overview.md)ページをご参照ください。

ジョブタスクとは異なり、プラグインには `{KeeperApiBaseUrl}` が引数として自動注入されません。プラグインJSONの `arguments` でAPIベースURLを明示して渡すか、ポートが保証されているデフォルト `https://127.0.0.1:6889` にフォールバックする必要があります。

ブローカーはループバック上でTLSを使います。MQTTクライアントをTLS向けに設定して接続し、組織のCAバンドルがあれば利用し、なければセキュリティポリシーに従いループバック限定で証明書検証を無効にします。
{% endstep %}

{% step %}

#### HTTPS経由のプラグイン設定 <a href="#plugin-settings-over-https" id="plugin-settings-over-https"></a>

プラグインは、システム全体の `KeeperPrivilegeManager` 設定とは別に、プラグインIDに紐づくスコープ付き構成を読み取れます。

```
GET https://127.0.0.1:{httpsPort}/api/PluginSettings/MyBridge
```

マージ後の有効な設定が、文字列キーと文字列値のフラットなJSONオブジェクトとして返ります。設定の出所は次のとおりです。

* プラグインJSONファイル (`Plugins/MyBridge.json`)
* 統合ストレージ (ポリシーで適用)
* システムデフォルト

ディスク上のJSONを直接解析するのではなく、常にこのエンドポイントで有効設定を読み取ってください。ディスク上のファイルはポリシー上書きを反映していない場合があります。

実行中のプラグインから単一の設定キーを更新する場合:

```
PUT https://127.0.0.1:{httpsPort}/api/PluginSettings/MyBridge/{settingName}
```

いずれも**プラグイン階層**の認可が必要です。エージェントが起動したプロセスでないと、プロセス認証に合格できません。同じバイナリを手動実行すると `403` になります。プラグイン設定APIの全体は [HTTPリファレンス](/keeperpam/jp/endpoint-privilege-manager/integrations/http-reference-guide.md)をご参照ください。
{% endstep %}

{% step %}

#### 署名とプロセス信頼 <a href="#signing-and-process-trust" id="signing-and-process-trust"></a>

`Plugins/` 配下のパスに置かれたバイナリは、`Jobs/bin/` より厳しい信頼ルールの対象です。プラグインオーケストレータがバイナリを起動するとプロセスが起動済み登録簿に載り、ジョブタスクと同様にMQTTとプラグイン階層HTTPSへのアクセスが付与されます。ただしプラグイン実行ファイルに適用されるパス前提と証明書チェックはより厳しいです。

**本番のプラグインバイナリはすべて署名してください。** Windowsでは標準のプラグイン信頼経路にAuthenticodeが必要です。macOSではApple Developer IDを使います。Linuxではデプロイの署名方針 (該当する場合はGPG署名パッケージやIMA) に合わせます。

デプロイでサムプリントの明示的な信頼登録が必要な場合のみ、コード署名証明書のサムプリントを `appsettings.json` の `Settings:AlternativeSignatures` に追加します。

```json
{
  "Settings": {
    "AlternativeSignatures": [
      "A1B2C3D4E5F6789012345678901234567890ABCD"
    ]
  }
}
```

`appsettings.json` を変更したらエージェントサービスを再起動します。

**本番検証を手動実行に頼らないでください。** エージェント外でプラグインバイナリを手動起動した場合、MQTT接続やプラグイン設定呼び出しには証明書チェックをパスする必要があります。オーケストレータが起動したバイナリは既に登録されているためそのチェックをスキップします。本番の挙動と一致すると決めつける前に、開発環境で手動起動を検証してください。
{% endstep %}

{% step %}

#### デプロイ <a href="#deployment" id="deployment"></a>

本番エージェントへの新規プラグイン追加は、ジョブのデプロイより手順が多くなりがちです。典型的には次が必要です。

1. 組織のリリース手順に従った**パッケージ化と署名**。
2. プラグインJSONの `executablePath` が指す場所へ、対象エンドポイントすべてに**バイナリを配置**。
3. サポートされたデプロイ手段で **`{AgentRoot}/Plugins/{PluginId}.json` にプラグインJSONを配置** (Last Known Good が有効なら手動コピーだけにしない)。
4. **エージェントの再起動**またはプラグインの再読み込みで、オーケストレータに新規登録を認識させる。

新規プラグインを投入してよい経路は環境ごとに異なります。Keeper管理者に確認してください。調整なしの任意ファイル配置は、Last Known Goodの保護やパッケージ前提と衝突することがあります。

デプロイ後の**プラグイン設定の更新**にエージェント再起動は不要です。プラグイン階層で認証されたプロセスから `PUT /api/PluginSettings/{PluginId}/{settingName}` を使うか、コンソール経由で設定ポリシーを更新します。

**設定が反映されない**場合は `POST /api/PluginSettings/{PluginId}/revert` でディスク上のプラグインJSONを統合ストレージへ再インポートし、その後 `GET` で有効値を確認します。
{% endstep %}
{% endstepper %}

## チェックリスト <a href="#checklist" id="checklist"></a>

フリートへ展開する前に全項目を確認してください。

<table><thead><tr><th width="55.06671142578125">#</th><th>確認項目</th></tr></thead><tbody><tr><td>1</td><td>プラグインの <code>id</code> がファイル名と一致する。各対応プラットフォームで <code>executablePath</code> にバイナリがある</td></tr><tr><td>2</td><td><code>Subscription.Topic</code> が設定され、デプロイ内のプラグイン間で一意である</td></tr><tr><td>3</td><td><code>metadata.mqttTopics.publish</code> に、バイナリが実際にパブリッシュするすべてのトピックが含まれる</td></tr><tr><td>4</td><td><code>metadata.mqttTopics.subscribe</code> に、<code>Subscription.Topic</code> 以外で購読するすべてのトピックが含まれる</td></tr><tr><td>5</td><td>MQTTクライアントIDがプラグイン形式 (<code>PluginName_Pid</code>)。ジョブの3要素形式ではない</td></tr><tr><td>6</td><td>バイナリは署名済み。必要ならサムプリントが <code>AlternativeSignatures</code> にある</td></tr><tr><td>7</td><td>実行中プラグイン内から <code>GET /api/PluginSettings/KeeperPrivilegeManager</code> が <code>broker.host</code> と <code>broker.port</code> を返す</td></tr><tr><td>8</td><td><code>GET /api/PluginSettings/{PluginId}</code> が想定どおりのプラグインスコープ設定を返す</td></tr><tr><td>9</td><td>MQTTに接続でき、主購読が有効で、<code>KeeperLogger</code> へのパブリッシュがログに見える</td></tr><tr><td>10</td><td><code>autoStart</code>、<code>requiresMonitoring</code>、<code>autoRestart</code> を運用で検証。CPU負荷、セッション挙動、再起動間隔が許容範囲か確認する</td></tr><tr><td>11</td><td>同一バイナリをジョブと二重に登録していない。役割ごとに実行ファイルを分ける</td></tr></tbody></table>

## トラブルシューティング <a href="#troubleshooting" id="troubleshooting"></a>

<table><thead><tr><th width="322.800048828125">症状</th><th>確認先</th></tr></thead><tbody><tr><td>デプロイ後にプラグインが起動しない</td><td>対象OSで <code>executablePath</code> が解決するか。署名を確認。エージェントログのオーケストレータエラーを確認</td></tr><tr><td>MQTT接続が拒否される</td><td>信頼済みとして登録されていない。手動ではなくオーケストレータが起動したか確認</td></tr><tr><td>MQTTは接続するがパブリッシュが拒否される</td><td><code>metadata.mqttTopics.publish</code> にトピックがない。文字列が完全一致するか確認</td></tr><tr><td><code>GET /api/PluginSettings/MyBridge</code> が <code>403</code></td><td>プラグイン認証されていない。手動ではなくエージェントがバイナリを起動したか確認</td></tr><tr><td>設定変更が反映されない</td><td>統合ストレージがJSONを上書きしている可能性。<code>/revert</code> で再インポート後に再確認</td></tr><tr><td>プラグインがループで予期せず再起動する</td><td><code>autoRestart: true</code> と起動エラーで終了するバイナリの組み合わせ。根本原因を直してから自動再起動を再有効化</td></tr><tr><td>重複プロセスが検出される</td><td>同一バイナリがプラグインとジョブタスクの両方に登録されている。役割ごとに実行ファイルを分ける</td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/jp/endpoint-privilege-manager/integrations/custom-plugin-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
