# 技術アーキテクチャ

<figure><img src="/files/IOeEIX5dCxuL05jq1kN6" alt=""><figcaption></figcaption></figure>

**対象:** IT管理者および技術担当者向け。本ページでは**Keeper特権マネージャー**の**技術アーキテクチャ**として、**イベント駆動**の考え方、**MQTT**と**HTTPS**の役割、**プラグイン**の読み込みと監視、**ジョブ**の起動と実行の流れを説明します。

***

### 概要

Keeper特権マネージャーは、各エンドポイントで動く**中央オーケストレーションサービス**です。単体ではポリシー評価やログ記録は行わず、次の役割を担います。

* **MQTTブローカー**と**HTTP/HTTPS API**を内蔵し、プラグインとジョブが通信できるようにします
* **プラグイン**を読み込んで監視します (KeeperPolicy、KeeperAPI、KeeperLoggerなど別プロセス)。失敗時は再起動できます
* **ジョブサービス**を動かし、**イベント**が発動したとき (MQTT経由)、**スケジュール**に一致したとき、またはAPI経由の**手動**トリガー時にジョブを実行します

システムは**イベント駆動**です。多くのワークフローは、何かがMQTTブローカーにメッセージを**パブリッシュ**したときに始まります (例: 「ポリシー評価が必要」「昇格の起動」)。サブスクライバー (プラグインまたはジョブサービス) がそれらのメッセージに反応し、リクエストを処理するか、一連のタスクを順に実行するジョブを起動します。

***

### アーキテクチャの全体像

```
┌─────────────────────────────────────────────────────────────────────────┐
│                    KeeperPrivilegeManager (main service)                  │
├─────────────────────────────────────────────────────────────────────────┤
│  HTTP/HTTPS API (ports 6888 / 6889)  │  MQTT Broker (port 8675)         │
│  - Health, status, plugins, jobs     │  - Event routing                 │
│  - Settings, registration            │  - Plugin ↔ service messaging   │
│  - Plugin start/stop/restart         │  - Job triggers                 │
├─────────────────────────────────────────────────────────────────────────┤
│  Plugin orchestration        │  Job service                             │
│  - Load plugin JSON          │  - Event triggers (MQTT)                 │
│  - Launch plugin processes   │  - Schedule triggers (timer)            │
│  - Health checks             │  - Manual triggers (API)                │
│  - Auto-restart on failure   │  - Run tasks (executable, HTTP, etc.)   │
└─────────────────────────────────────────────────────────────────────────┘
         │                                          │
         │ launch & monitor                          │ execute
         ▼                                          ▼
┌──────────────────┐  ◄──── MQTT ────►  ┌──────────────────────────────────┐
│  Plugins         │                    │  Job executables / tasks          │
│  KeeperPolicy    │                    │  - Policy controls (MFA, etc.)    │
│  KeeperAPI      │                    │  - LaunchPrivilegeElevation        │
│  KeeperLogger   │                    │  - Inventory, risk, config         │
│  KeeperClient   │                    │  - Run as Service / User / HTTP    │
│  keeperAgent    │                    └──────────────────────────────────┘
│  ...            │
└──────────────────┘
```

* **プラグイン**はMQTTブローカーに接続し、メッセージの送受信を行います。HTTP APIを呼び出す場合もあります (設定取得、ジョブ起動、プロセス起動など)。
* **ジョブ**はイベント (MQTT)、スケジュール、またはAPIでトリガーされます。実行時には**タスク**の一覧が順に処理されます (実行ファイルの起動、HTTP呼び出しなど)。タスクの出力はコンテキストにマージされ、後続のタスクやルーティング判断に使われます。

***

### イベント駆動モデル

システムは**イベント駆動**です。処理は単一の逐次プログラムではなく、**イベント**によって起動されます。

#### イベントの流れ

1. エンドポイント上で**何かが起きます** (例: ユーザーが昇格を要求する、フックやエージェントが検知する、またはサービスが起動する)。
2. 特定の**トピック**へMQTTブローカー経由で**メッセージがパブリッシュ**されます (例: KeeperPolicyが購読するトピックへのポリシー評価リクエスト、またはジョブサービスが待ち受けるトピックへの `PolicyEvaluationPending` や `LaunchPrivilegeElevation` などのカスタムイベント)。
3. **サブスクライバー**がメッセージを受け取ります。

* **プラグイン** (例: KeeperPolicy) はトピックを購読し、リクエストを処理します (例: ポリシー評価、ALLOW/DENY/PENDINGの返却)。
* **ジョブサービス**は、**カスタムイベント**がパブリッシュされると (購読または通知で) それを受け取り、そのイベント名を `events` に持つジョブをすべて見つけ、イベントのコンテキスト付きで**一致するジョブをそれぞれ起動**します。

4. **ジョブ**は**タスク**を順に実行します。タスクはさらにMQTTへパブリッシュ (例: 応答トピックへ返す)、HTTP APIを呼び出す (例: 昇格起動、設定取得)、実行ファイルを起動する (例: KeeperMFA、KeeperApproval) などが可能です。これにより**後続のイベント**が発動する場合があります (例: コントロール完了後に `LaunchPrivilegeElevation` がパブリッシュされ、起動ジョブが動きます)。

このため、1つのイベントがジョブ実行につながり、そのジョブが別イベントをパブリッシュし、さらに別のジョブへと続くことがあります。ポリシー評価、コントロール (MFA、承認、正当化)、起動の一連の処理は、このイベント連鎖でつながっています。

#### 代表的なイベント名 (カスタムイベント)

* **PolicyEvaluationPending** — ポリシー評価がPENDING (コントロール必須) になったとき。privilege-elevation-policy-controls、file-access-policy-controls、default-policy-controls などのポリシーコントロール用ジョブがこれを購読し、MFA/正当化/承認のワークフローを実行します。
* **LaunchPrivilegeElevation** — ユーザーへの昇格が許可されたとき。実際にプロセスを起動するジョブ (LaunchPrivilegeElevation) が、コンテキスト (ファイルパス、コマンドライン、ユーザーなど) 付きでトリガーされます。
* **Startup** — サービス起動時に発動します。登録やクリーンアップなどのジョブが購読します。
* **LaunchApprovedRequest**、**ShowAgent**など — UIやワークフローから特定のジョブを起動するときに使われます。

イベントには**コンテキスト** (パラメータ) を付与でき、ジョブの初期コンテキストとして引き渡され、タスクから参照できます (例: `{RequestId}`、`{FilePath}`、`{UserName}`)。

***

### MQTTの役割

#### MQTTブローカーの役割

メインサービスは**組み込みMQTTブローカー** (既定ポート**8675**、`localhost` のみ) を動かしています。製品の**メッセージバス**です。

* **プラグイン**はMQTTクライアントとしてブローカーに接続します。各プラグインには**購読**構成 (購読するトピック) と**パブリッシュ**許可 (パブリッシュできるトピック) があります。
* **プロセスベースのセキュリティ:** **KeeperPrivilegeManagerによって起動された**プロセス (かつ有効な証明書を提示できるもの) だけが接続を許可されます。任意のアプリケーションがパブリッシュや購読を行えないようにします。
* **トピックベースのルーティング:** メッセージは、そのトピックを購読しているすべてのクライアントに届きます。**EventMessages** (またはカスタムイベント用の同等トピック) へパブリッシュすると、ジョブサービスが受け取ってジョブを起動できます。**KeeperPolicy** へパブリッシュすると、KeeperPolicyプラグインが受け取ってポリシーを評価します。

#### 代表的なトピック (概念)

* **KeeperPolicy** — ポリシー評価リクエスト (受信)、ポリシー応答 (送信)。
* **KeeperLogger** — ログメッセージ (プラグインとジョブがここへパブリッシュしログを集約)。
* **KeeperApi** — バックエンド同期、登録、監査 (KeeperAPIプラグイン)。
* **EventMessages** (または同等) — ジョブを起動するカスタムイベント (例: PolicyEvaluationPending、LaunchPrivilegeElevation)。ジョブサービスが購読し、イベント名とジョブ定義を照合します。
* **JobService** — ジョブ関連メッセージ (完了、トリガーなど)。
* **keeperAgent**、**KeeperClient**、**RequestApproval**など — UIや承認ワークフローで使用。

正確なトピック名やどのプラグインが何をパブリッシュ/購読するかは、各プラグインのJSON (`Subscription`、`metadata.mqttTopics`) で定義されます。アーキテクチャ上重要なのは、**イベントおよびポリシー処理に関するコンポーネント間通信はすべてlocalhost上のMQTT**経由であり、プロセスとトピックの検証が行われることです。

#### MQTTとイベント駆動ジョブ

**カスタムイベント**でジョブを起動する場合:

1. 何らかのコンポーネント (例: KeeperPolicyまたは別ジョブ) がイベント用トピックへ**イベント名**と**ペイロード** (コンテキスト) を載せたメッセージを**パブリッシュ**します。
2. **ジョブサービス**がメッセージを受け取り、**TriggerJobByEvent(eventName, context)** (または同等) を呼び出します。
3. `**events` 配列にそのイベント名を含む**ジョブ** (例: `customEvent: "LaunchPrivilegeElevation"`) がすべて**照合**され、そのコンテキストで**起動**されます。
4. それぞれのジョブが**タスクリスト**を実行します。タスクはさらにMQTTへパブリッシュしたりHTTP APIを呼んだりし、追加のイベントや副作用を生みます。

MQTTは**リクエスト/レスポンス** (例: ポリシーリクエスト → KeeperPolicy → 応答) と、ジョブサービスへ**ファイア・アンド・フォーゲット型のイベント**を届けて**ジョブを起動**する用途の両方に使われます。

***

### HTTPS (およびHTTP) の使われ方

#### HTTP/HTTPS APIサーバー

メインサービスは**HTTP/HTTPS API** (Kestrel) を**localhost のみ** (127.0.0.1) にバインドして公開します。

* **HTTP**既定ポート**6888**
* **HTTPS**既定ポート**6889** (推奨。`localhost` 向け自己署名証明書を使用)

APIの用途:

* **ヘルスと状態** — `GET /health`、`GET /`、`GET /api/system/status` (認証なし。監視やスクリプト用)
* **プラグイン管理** — プラグインの開始/停止/再起動、一覧 (エンドポイントに応じてAdminまたはPlugin認可)
* **ジョブ管理** — ジョブ一覧、ジョブ実行、コンテキスト付きトリガー、ジョブJSONの検証 (PluginまたはAdmin)
* **設定** — アプリおよびプラグイン設定の読み書き。プラグイン設定のJSONからの復元 (書き込みはAdmin)
* **登録** — エージェントのKeeperバックエンドへの登録/登録解除 (Adminまたは構成どおり)
* **その他** — ファイルアクセス、ユーザーセッション起動、一時アカウント、監査など。詳細については、[ローカルエンドポイント](/keeperpam/jp/endpoint-privilege-manager/reference/local-endpoints.md)のページをご参照ください。

#### APIの呼び出し元

* **プラグイン** — 設定読み込み (`GET /api/PluginSettings/{pluginName}`)、ジョブトリガー (`POST /api/Jobs/{id}/trigger`)、起動/一時アカウント系エンドポイントなど。HTTPSベースURL (構成やパラメータ由来) を使います。
* **ジョブのタスク** — ジョブ内の**HTTPタスク**が任意のURL (多くはローカルAPI) を呼び、ジョブ起動、プロセス起動、実行許可の作成、設定の復元などを行います。**Service**タスクで実行ファイル (KeeperMFA、RedirectEvaluatorなど) を動かす場合、実行ファイルがコールバックできるようAPIベースURLが引数で渡されることがあります。
* **管理者/スクリプト** — 管理スクリプトや運用者がAPIを呼び出し (必要に応じてAdmin権限またはクライアント証明書)、ヘルス確認、プラグイン再起動、ジョブ実行、設定変更を行います。

**認可レベル** (概念): **Public** (ヘルス、状態)、**Plugin** (Keeper特権マネージャーによって起動されたプロセス + 証明書)、**Admin** (昇格済みユーザーまたは信頼済みプロセス + 証明書)。**同期的な**管理APIと連携にはHTTPS、プラグインとジョブまわりの**非同期**のイベント・メッセージにはMQTTが使われます。

***

### プラグインの読み込みと監視

#### プラグインの読み込み

1. **検出** — 起動時にメインサービスが**Plugins**フォルダを走査し、**プラグインJSON** (例: `KeeperPolicy.json`、`KeeperApi.json`) を探します。各ファイルが1プラグインを表し、id、名前、実行パス、購読トピック、起動優先度、autoStart、その他メタデータを記述します。
2. **検証** — サービスがプラグインを検証します (例: パスの安全性、必要なら証明書)。検証に失敗したプラグインは起動されません。
3. **起動順** — プラグインは**startupPriority**で並べられます (数値が小さいほど先)。**autoStart: true**のものがその順で起動します。**autoStart: false**は読み込まれますが、APIやオンデマンドで要求されるまで起動しません。
4. **起動** — **Executable**プラグインでは、サービスがプラグインプロセスを起動します (**executablePath**)。プロセスはMQTTブローカーに接続し、通常はHTTP APIで設定を読み込みます。その後、構成どおりトピックを購読しメッセージを処理します。

**プラグインはJSONから読み込まれます** — ランタイムにAPIで「登録」するのではなく、起動時の定義の根拠はJSONファイルです。プラグインを追加するにはJSON (とバイナリ) を置き、サービスを再起動します (または autoStart: false ならAPIで開始します)。

#### 監視と再起動

* **ヘルスチェック** — メインサービスが定期的に各プラグインプロセスの生存を確認し、必要なら生存確認 (単純なpingやヘルスコールバックなど) を行います。間隔と挙動は構成可能です (例: appsettingsのPluginMonitoring)。
* **自動再起動** — プラグインに**autoRestart: true**があり、監視で異常終了またはヘルス不良と判定された場合、サービスが**自動再起動**できます。KeeperPolicyやKeeperLoggerなど重要なプラグインの継続稼働に役立ちます。
* **手動制御** — 管理者はHTTP APIでプラグインを**停止**または**再起動**できます (`POST /api/plugins/{name}/stop`、`POST /api/plugins/{name}/restart`)。サービス全体の再起動は不要です。

**まとめ: プラグインは `Plugins/*.json` から読み込まれ、優先度順に起動され、監視されます。失敗時は自動再起動するか、API経由で手動再起動できます。**

***

### ジョブの起動と実行

#### ジョブ定義と登録

* **ジョブ**は**Jobs**フォルダ内の**JSONファイル**で定義されます。各ファイルに**id**、**events** (任意)、**schedule** (任意)、**parameters**、**tasks**、**condition**、任意で**alternateJobId**があります。
* 起動時 (および実装に応じてファイル変更時)、**ジョブサービス**がジョブJSONをすべて読み込み検証し、各ジョブを**登録**します。いずれかの**トリガー**が発動するとジョブが「起動」されます。

#### トリガーの種類

次のいずれかでジョブが**起動**されます。

| トリガー種別       | 発動のしかた                                                                                                                                                   | ジョブが一致する条件                                                                                            |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| **Event**    | イベント用トピックに**イベント名** (例: PolicyEvaluationPending、LaunchPrivilegeElevation) を含むメッセージがパブリッシュされます。ジョブサービスが**TriggerJobByEvent(eventName, context)** を呼び出します。 | ジョブの**events**配列にその名前のイベントがあること (例: `eventType: "Custom"`、`customEvent: "LaunchPrivilegeElevation"`)。 |
| **Schedule** | 内部**タイマー**が動きます (例: 毎分、cron単位)。ジョブサービスが各ジョブの**schedule** (interval、cron、runAt、カレンダー) を評価します。                                                             | 現在時刻がジョブのスケジュールに合致すること。                                                                               |
| **Manual**   | 管理者またはスクリプトが**POST /api/Jobs/{jobId}/run**または**POST /api/Jobs/{jobId}/trigger**を任意のボディ付きで呼び出します。                                                         | リクエストのジョブidがジョブの**id**と一致すること。                                                                        |

ジョブは**events**と**schedule**の両方を持てます。**イベントが一致する**か**スケジュールが一致する**かのいずれかで実行されます。

#### ジョブ実行の流れ (概要)

1. **トリガーが発動すると**、ジョブサービスが一致するジョブをすべて探します (イベント名、スケジュール、またはジョブid)。
2. 一致する各ジョブ (多くは1つ) について、サービスが**トリガコンテキスト** (イベントペイロード、パラメータ、既定値) でジョブ実行を**開始**します。
3. **ジョブ単位のcondition** (定義されている場合) を評価します。失敗ならジョブはスキップされます (または**alternateJobId**が実行されます)。成功なら**タスクループ**に入ります。
4. **タスクループ** — 順に各タスクについて:

* **タスクcondition** (定義されている場合) を現在の**コンテキスト** (トリガコンテキスト + パラメータ + 先行タスクの出力) で評価します。偽ならタスクは**スキップ**され、リスト順の次のタスクへ進みます。
* タスクが**プラグイン設定**を参照する場合 (例: 「metadata.redirect.enabled が false のときスキップ」)、それを評価し、スキップならコマンドは実行せず、任意の**ContextWhenSkipped**をコンテキストにマージします。
* タスクを**実行**します:
  * **Service** — サービスセッションで実行ファイルを起動します (RedirectEvaluator、KeeperMFAなど)。出力 (例: stdoutのJSON) を後続タスク用にコンテキストへマージできます。
  * **HTTP** — HTTP/HTTPSリクエストを発行します (例: ローカルAPIでプロセス起動や別ジョブのトリガー)。実行ファイルは使いません。
  * **User / UserDesktop / UserElevated** — ユーザーセッションで実行します (非昇格、デスクトップ、または昇格)。
* **ルーティング** — 成功時、次タスクは**OnSuccess** (明示的なタスクid) またはリストの次です。失敗時は**OnFailure**またはリストの次です。**ContinueOnFailure**がfalseならジョブは停止します。スキップ時は常にリストの**次**です。

5. タスクリストが終わる (またはタスクが「停止」へルート) と、ジョブの実行が**完了**します。再度トリガーされない限り、それ以上タスクは動きません。

**ジョブはイベント (MQTT)、スケジュール (タイマー)、またはAPIで起動されます**。各実行は任意の条件とルーティング付きの**タスク列**であり、タスクは実行ファイル、HTTP、ユーザーコンテキストで動き、MQTTパブリッシュやAPI呼び出しでさらにジョブや操作を引き起こせます。

#### タスク実行タイプ (要約)

| 種別               | 実行場所                     | 代表的な用途                                                                    |
| ---------------- | ------------------------ | ------------------------------------------------------------------------- |
| **Service**      | サービスセッション (ユーザーデスクトップなし) | バックエンド実行ファイル (RedirectEvaluator、リスク評価)、スクリプト、組み込みコマンド (echo、publish-mqtt) |
| **Http**         | HTTPクライアント               | ローカルAPIまたは外部URLの呼び出し (ジョブのトリガー、昇格起動、設定復元)                                 |
| **User**         | ユーザーセッション、非昇格            | ユーザーコンテキストでのプロセス                                                          |
| **UserDesktop**  | ユーザーのデスクトップ、非昇格          | ダイアログ表示が必要なUIアプリ (KeeperMFA、KeeperJustification、KeeperApproval)           |
| **UserElevated** | ユーザーコンテキスト、昇格            | ユーザーセッションで昇格したプロセスを実行                                                     |

***

### エンドツーエンド例: 特権昇格

MQTT、HTTPS、プラグイン、ジョブの関係を1例にまとめます。

1. **ユーザー**が昇格を要求します (例: アプリを右クリックして「管理者として実行」)。OSまたはエージェント (KeeperRunAs、フックなど) がこれを検知し、ポリシー判断が必要になります。
2. **KeeperPolicyへのリクエスト** — 判断が必要なコンポーネントが**KeeperPolicy**トピック (または同等) に、コンテキスト (ユーザー、マシン、アプリケーション、コマンドライン、イベント種別) を載せて**メッセージをパブリッシュ**します。
3. **KeeperPolicy** (プラグイン) がメッセージを受け取り、ポリシーを評価し、**ALLOW**、**DENY**、または**PENDING** (コントロール必須) と決めます。**応答をパブリッシュ**します (例: 応答トピックまたはEventMessages)。
4. 結果が**PENDING**なら、ジョブサービス (またはイベントを出したコンポーネント) がコンテキスト (ControlList、SessionId、RespondToTopicなど) 付きで**PolicyEvaluationPending**イベントを**トリガー**します。**privilege-elevation-policy-controls** (または同等) ジョブが**一致**して**実行**されます。
5. そのジョブが**タスク**を実行します: 例 PendingApprovals 確認、続けて **KeeperMfa** / **KeeperJustification** / **KeeperApproval** (UserDesktopタスク)、**publish-mqtt**で監査送信、コントロール成功後に **LaunchPrivilegeElevation** イベントを**パブリッシュ**します (コンテキストに FilePath、CommandLine、UserName など)。
6. **LaunchPrivilegeElevation**ジョブがそのイベントに**一致**して動きます。タスク例: **check-redirect** (RedirectEvaluator設定を読み、リダイレクト有効ならRedirectEvaluator実行)、**launch-substitute** (代替exeを昇格起動するHTTP) または **launch-elevated** (要求されたexeを昇格起動するHTTP)、**publish-mqtt**で最終応答 (DidElevateやDenyなど) を呼び出し元へ送ります。
7. **呼び出し元** (フックやエージェント) が応答を受け取り、ユーザー操作を許可またはブロックします。

この一連の流れでは、**MQTT**がイベントとリクエスト/レスポンスを運び、**HTTPS**がプラグイン設定、ジョブのトリガー、起動APIに使われます。**プラグイン**はJSONから読み込まれ監視され、**ジョブ**はイベント (またはスケジュール/手動) で起動し、実行ファイルやHTTPを経由して処理を進めます。

***

### まとめ

| トピック       | 要約                                                                                                                                                      |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **イベント駆動** | 処理は**イベント** (MQTTメッセージ) で駆動します。ポリシーリクエスト、コントロール、起動の流れはすべてブローカーへのパブリッシュで始まり、サブスクライバー (プラグイン、ジョブサービス) がロジックやジョブを実行します。                                    |
| **MQTT**   | ポート8675の組み込みブローカー (`localhost`)。ポリシーのリクエスト/レスポンス、カスタムイベント (ジョブのトリガー)、ログ、プラグイン間メッセージに使用します。プロセスとトピックの制限があります。                                            |
| **HTTPS**  | ポート6888 (HTTP) と6889 (HTTPS) のKestrel、`localhost` のみ。ヘルス、プラグイン/ジョブ管理、設定、登録、起動、その他API操作に使用します。                                                           |
| **プラグイン**  | 起動時に**Plugins/.json**から読み込まれ、優先度で起動し、**監視**と構成どおり**自動再起動**されます。MQTTに接続し、必要に応じHTTP APIを呼びます。                                                             |
| **ジョブ**    | **Jobs/.json**で定義されます。**イベント** (MQTT)、**スケジュール** (タイマー)、**手動** (API) で起動します。各実行は条件とルーティング付きの**タスクリスト** (Service、HTTP、User、UserDesktop、UserElevated) です。 |


---

# 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/reference/technical-architecture.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.
