# 通知設計書 42-コントローラーエグゼキュータ警告（ControllerExecutorsAgents）

## 概要

本ドキュメントは、JenkinsのControllerExecutorsAgents（コントローラーエグゼキュータ警告：エージェント存在時）に関する通知設計書である。エージェントまたはクラウドが設定されているにもかかわらず、ビルトインノード（コントローラー）にエグゼキュータが設定されている場合にセキュリティ警告を表示するAdministrativeMonitor機能について記述する。

### 本通知の処理概要

ControllerExecutorsAgentsは、Jenkinsコントローラー上でビルドを実行することのセキュリティリスクを管理者に警告するAdministrativeMonitorである。

**業務上の目的・背景**：Jenkinsコントローラー（ビルトインノード）上でビルドを実行することは、セキュリティ上の重大なリスクを伴う。ビルドスクリプトは任意のコードを実行できるため、悪意のあるビルドがコントローラーのファイルシステムやJenkinsの内部状態にアクセスする可能性がある。エージェントが存在する環境では、ビルドはエージェント上で実行されるべきであり、コントローラーのエグゼキュータ数は0に設定すべきである。

**通知の送信タイミング**：Jenkinsの管理画面（/manage）にアクセスした際に、isActivated()メソッドで条件がチェックされ、条件を満たす場合に警告が表示される。具体的には、(1) 開発モードでない、(2) コントローラーのエグゼキュータ数が1以上、(3) クラウドまたは静的エージェントが1つ以上存在する、という3条件すべてを満たす場合に警告が有効化される。

**通知の受信者**：Jenkins管理者権限（Jenkins.ADMINISTER）を持つユーザーが対象。管理画面でセキュリティ関連の警告として表示される。

**通知内容の概要**：「ビルトインノードでのビルド実行はセキュリティ上の問題となる可能性がある。ビルトインノードのエグゼキュータ数を0に設定すべき」という警告メッセージと、Jenkins公式ドキュメントへのリンクが表示される。

**期待されるアクション**：管理者は警告を確認し、「Manage」ボタンをクリックしてビルトインノードの設定画面に遷移し、エグゼキュータ数を0に変更する。または、「Dismiss」ボタンで警告を無視する（非推奨）。

## 通知種別

管理者向けAdministrativeMonitor（Webダッシュボード警告表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | オンデマンド（管理画面アクセス時） |
| 優先度 | 高（セキュリティ関連警告） |
| リトライ | N/A（画面表示のため） |

### 送信先決定ロジック

Jenkins管理画面（/manage）にアクセスしたJenkins.ADMINISTER権限を持つユーザーに対して、isActivated()がtrueを返す場合に警告が表示される。

## 通知テンプレート

### 管理画面警告の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | Jenkins管理画面上部 |
| スタイル | jenkins-alert jenkins-alert-warning |
| カテゴリ | セキュリティ関連（isSecurity()=true） |

### 本文テンプレート

```
Building on the built-in node can be a security issue.
You should set the number of executors on the built-in node to 0.
See the documentation.

[Manage] [Dismiss]
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | - | - | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| it.url | モニターのURL | AdministrativeMonitor.getUrl() | Yes |
| it.id | モニターのID | AdministrativeMonitor.id | Yes |
| rootURL | JenkinsルートURL | Staplerコンテキスト | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 管理画面（/manage）アクセス | isActivated()=true | 条件を満たす場合に警告表示 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 開発モード | Main.isDevelopmentModeがtrueの場合は表示されない |
| エグゼキュータ0 | Jenkins.get().getNumExecutors()が0の場合は表示されない |
| エージェント・クラウドなし | cloudsとnodesの両方が空の場合は表示されない |
| 無効化済み | disable(true)で無効化された場合は表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[管理画面アクセス] --> B{権限チェック}
    B -->|ADMINISTER権限あり| C{isEnabled?}
    B -->|権限なし| Z[警告非表示]
    C -->|有効| D{isActivated?}
    C -->|無効化済み| Z
    D -->|有効化| E[message.jelly表示]
    D -->|非有効化| Z
    E --> F{ユーザーアクション}
    F -->|Manage| G[ビルトインノード設定画面へ遷移]
    F -->|Dismiss| H[disable実行・管理画面へリダイレクト]
    G --> I[エグゼキュータ数変更]
    I --> J[警告解消]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | データベースは使用しない | Jenkinsオブジェクトモデルを参照 |

### Jenkins設定参照

| 参照項目 | 用途 | 取得条件 |
|---------|------|---------|
| Jenkins.get().getNumExecutors() | コントローラーのエグゼキュータ数 | isActivated()判定で使用 |
| Jenkins.get().clouds | クラウド設定リスト | isActivated()判定で使用 |
| Jenkins.get().getNodes() | 静的エージェントリスト | isActivated()判定で使用 |
| Main.isDevelopmentMode | 開発モードフラグ | isActivated()判定で使用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Jenkins設定ファイル | UPDATE | disable()時にdisabledAdministrativeMonitorsに追加 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| IOエラー | disable()やJenkins.save()失敗時 | IOException伝播 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | N/A |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 表示頻度 | 管理画面アクセス毎 |
| 重複表示 | なし（1つの警告のみ） |

### 配信時間帯

常時（管理画面アクセス時に条件判定）

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

- isSecurity()がtrueを返すため、セキュリティ関連警告としてカウントされる（50-52行目）
- doAct()メソッドは@RequirePOSTアノテーションによりPOSTリクエストのみ許可（60行目）
- AdministrativeMonitorの基底クラスでJenkins.ADMINISTER権限が必要（AdministrativeMonitor.java 209行目）
- NoExternalUse制限により内部利用専用

## 備考

- Symbol名は`executorsOnBuiltInNodeWithAgents`および`controllerExecutorsWithAgents`（40行目）
- 警告メッセージ内のドキュメントリンク: https://www.jenkins.io/redirect/building-on-controller/
- 2021年にCloudBees社により追加された機能
- No.43のControllerExecutorsNoAgentsとは排他的な関係（エージェント有無で切り替わる）

---

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

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

### 推奨読解順序

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

AdministrativeMonitorの基本構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AdministrativeMonitor.java | `core/src/main/java/hudson/model/AdministrativeMonitor.java` | 基底クラスの構造、id、isEnabled()、isActivated()、disable()の仕組み |

**読解のコツ**: AdministrativeMonitorは抽象クラスで、isActivated()が抽象メソッド。各実装クラスで条件を定義する。

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

ControllerExecutorsAgentsクラスの全体構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ControllerExecutorsAgents.java | `core/src/main/java/jenkins/diagnostics/ControllerExecutorsAgents.java` | クラス定義、@Extension/@Symbolアノテーション（39-41行目） |

**主要処理フロー**:
1. **39-41行目**: @Extension, @Symbol, @Restricted定義
2. **44-47行目**: getDisplayName()でメッセージリソースから表示名取得
3. **49-52行目**: isSecurity()でセキュリティ警告フラグ設定

#### Step 3: 有効化条件を理解する

isActivated()メソッドの条件ロジックを追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ControllerExecutorsAgents.java | `core/src/main/java/jenkins/diagnostics/ControllerExecutorsAgents.java` | isActivated()メソッド（54-58行目） |

**主要処理フロー**:
- **55-57行目**: 3つの条件をANDで評価
  - `!Main.isDevelopmentMode`: 開発モードでない
  - `Jenkins.get().getNumExecutors() > 0`: エグゼキュータが1以上
  - `!Jenkins.get().clouds.isEmpty() || !Jenkins.get().getNodes().isEmpty()`: クラウドまたはエージェントが存在

#### Step 4: アクション処理を理解する

ユーザーのボタンクリック時の処理フローを追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ControllerExecutorsAgents.java | `core/src/main/java/jenkins/diagnostics/ControllerExecutorsAgents.java` | doAct()メソッド（60-68行目） |

**主要処理フロー**:
- **60行目**: @RequirePOSTでPOSTリクエスト必須
- **62-64行目**: "no"パラメータ（Dismiss）の場合、disable(true)して/manageへリダイレクト
- **65-67行目**: "yes"パラメータ（Manage）の場合、ビルトインノード設定画面へリダイレクト

#### Step 5: 表示テンプレートを理解する

警告メッセージの表示方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | message.jelly | `core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/message.jelly` | 警告UIの構造、フォームのアクション定義 |
| 5-2 | message.properties | `core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/message.properties` | 警告メッセージテキスト |
| 5-3 | description.jelly | `core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/description.jelly` | モニターの説明文表示 |

**主要処理フロー**:
- **message.jelly 27-31行目**: jenkins-alert-warningスタイルのdiv、ManageとDismissボタン
- **message.properties 23-25行目**: ExecutorsWarningメッセージ定義

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

```
管理画面アクセス（/manage）
    │
    ├─ AdministrativeMonitor.all()
    │      └─ ExtensionList.lookup(AdministrativeMonitor.class)
    │
    └─ 各モニターに対して
           ├─ isEnabled()
           │      └─ disabledAdministrativeMonitors.contains(id)チェック
           │
           └─ isActivated()
                  └─ ControllerExecutorsAgents.isActivated()
                         ├─ Main.isDevelopmentMode チェック
                         ├─ Jenkins.get().getNumExecutors() チェック
                         └─ clouds/nodes 存在チェック

ユーザーアクション
    │
    └─ doAct() [POST]
           ├─ "no" → disable(true) → /manage リダイレクト
           └─ "yes" → /computer/(built-in)/configure リダイレクト
```

### データフロー図

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

Jenkins設定状態 ───▶ isActivated()条件判定 ───▶ 警告表示可否
- numExecutors              │
- clouds                    │
- nodes                     │
- developmentMode           │
                           ▼
                    message.jelly
                           │
                           ▼
               [警告メッセージ表示]


ボタンクリック ───▶ doAct() ───▶ リダイレクト
- yes: Manage              │        - /computer/(built-in)/configure
- no: Dismiss              │        - /manage + disable()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ControllerExecutorsAgents.java | `core/src/main/java/jenkins/diagnostics/ControllerExecutorsAgents.java` | ソース | メインクラス、条件判定とアクション処理 |
| AdministrativeMonitor.java | `core/src/main/java/hudson/model/AdministrativeMonitor.java` | ソース | 基底クラス、共通機能 |
| message.jelly | `core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/message.jelly` | テンプレート | 警告UI表示 |
| message.properties | `core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/message.properties` | 設定 | 警告メッセージテキスト |
| description.jelly | `core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/description.jelly` | テンプレート | モニター説明表示 |
| description.properties | `core/src/main/resources/jenkins/diagnostics/ControllerExecutorsAgents/description.properties` | 設定 | 説明テキスト |
| Messages.properties | `core/src/main/resources/jenkins/diagnostics/Messages.properties` | 設定 | DisplayName定義 |
| ControllerExecutorsAgentsTest.java | `test/src/test/java/jenkins/diagnostics/ControllerExecutorsAgentsTest.java` | テスト | ユニットテスト |
