# 通知設計書 9-CSRF保護警告（CSRFAdministrativeMonitor）

## 概要

本ドキュメントは、CSRF保護が適切に設定されていない場合に管理者へ警告を表示するCSRFAdministrativeMonitor（CSRF保護警告）の通知設計について記述する。

### 本通知の処理概要

CSRFAdministrativeMonitorは、JenkinsのCSRF（Cross-Site Request Forgery）保護機能が無効になっている状態を検出し、管理者に対して警告メッセージを表示する通知機能である。

**業務上の目的・背景**：CSRF攻撃は、悪意のあるWebサイトがユーザーのブラウザを通じてJenkinsに不正なリクエストを送信させる攻撃手法である。CSRF保護（CrumbIssuer）が無効な場合、ユーザーがログイン状態でJenkinsを使用中に悪意のあるサイトを訪問すると、意図しないビルドの実行、設定の変更、その他の操作が実行される可能性がある。本通知は、この危険な状態を管理者に警告し、CSRF保護の有効化を促すことを目的とする。

**通知の送信タイミング**：Jenkins管理画面（/manage）にアクセスした際に、`isActivated()`メソッドが呼び出され、`Jenkins.get().getCrumbIssuer()`がnullを返す場合に通知が有効化される。

**通知の受信者**：Jenkins管理画面にアクセスできる管理者が対象となる。セキュリティ関連通知として分類される。

**通知内容の概要**：CSRF保護が無効になっている旨のメッセージが表示される。Jenkins公式ドキュメントへの参照リンクと、セキュリティ設定画面へのリンクが提供される。「Dismiss」ボタンで警告の非表示化が可能。

**期待されるアクション**：管理者は「Configure Security」リンクをクリックしてセキュリティ設定画面（/configureSecurity）に遷移し、CSRF保護（Crumb Issuer）を有効化することが期待される。

## 通知種別

アプリ内通知（管理画面バナー表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（画面レンダリング時） |
| 優先度 | 高（セキュリティ関連） |
| リトライ | 無（画面表示のため不要） |

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

Jenkins管理画面（/manage）にアクセスした管理者に対して表示される。CrumbIssuerがnullの場合に有効化。

## 通知テンプレート

### アプリ内通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | 管理画面上部 |
| アラートタイプ | jenkins-alert-warning（警告） |
| 形式 | HTML |

### 本文テンプレート

```html
<div class="jenkins-alert jenkins-alert-warning">
  <form method="post" action="${rootURL}/${it.url}/disable">
    <f:submit value="Dismiss"/>
  </form>
  <j:set var="referenceAnchor">
    <a href="https://www.jenkins.io/redirect/csrf-protection"
       rel="noopener noreferrer" target="_blank">${%referenceUrlContent}</a>
  </j:set>
  <j:set var="actionAnchor">
    <a href="${rootURL}/configureSecurity">${%actionUrlContent}</a>
  </j:set>
  <j:out value="${%warningMessage(referenceAnchor)}"/>
  <p />
  <j:out value="${%actionMessage(actionAnchor)}"/>
</div>
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| rootURL | JenkinsのルートURL | Jenkins.get().getRootUrl() | Yes |
| it.url | モニターのURL | AdministrativeMonitor.getUrl() | Yes |
| referenceAnchor | CSRF保護ドキュメントへのリンク | 固定URL | Yes |
| actionAnchor | セキュリティ設定画面へのリンク | /configureSecurity | Yes |
| warningMessage | 警告メッセージ | Messages.properties | Yes |
| actionMessage | アクション案内メッセージ | Messages.properties | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 管理画面（/manage）へのアクセス | Jenkins.getCrumbIssuer() == null | CSRF保護が無効な場合に表示 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| disable(true)が呼び出された場合 | 管理者が「Dismiss」をクリックした場合 |
| isEnabled() == false | Jenkins設定でこのモニターが無効化されている場合 |
| CrumbIssuerが設定されている場合 | CSRF保護が有効な場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[管理画面へアクセス] --> B{isEnabled?}
    B -->|No| C[表示しない]
    B -->|Yes| D{isActivated?}
    D -->|No| C
    D -->|Yes| E[警告バナー表示]
    E --> F{ユーザーアクション}
    F -->|Configure Security| G[/configureSecurity へ遷移]
    F -->|Learn more| H[Jenkins公式ドキュメントへ]
    F -->|Dismiss| I[disable true で無効化]
    G --> J[CrumbIssuer設定]
    J --> K[終了]
    H --> K
    I --> K
    C --> K
```

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

### 参照テーブル一覧

該当なし（ファイルベースの設定を参照）

### 参照ファイル

| ファイル | 用途 | 備考 |
|---------|------|------|
| $JENKINS_HOME/config.xml | CrumbIssuer設定の参照 | crumbIssuer要素の存在確認 |

### 更新ファイル

| ファイル | 操作 | 概要 |
|---------|------|------|
| $JENKINS_HOME/config.xml | UPDATE | disable()呼び出し時にdisabledAdministrativeMonitorsを更新 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 設定保存失敗 | disable()時のIOException | ログ出力、ユーザーに再試行を促す |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

該当なし（画面表示のため）

### 配信時間帯

制限なし（常時有効）

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

- 本通知はセキュリティ関連（`isSecurity()` = true）としてマークされている
- doDisable()は`@RequirePOST`で保護されている（基底クラス）
- CSRF保護の重要性を説明し、有効化を強く推奨

## 備考

- Symbol: `csrf`
- パッケージ: jenkins.security.csrf
- 導入バージョン: Jenkins 2.85以降（@since 2.85）
- @Restricted(NoExternalUse.class)で外部使用制限
- 外部リンク: https://www.jenkins.io/redirect/csrf-protection
- メッセージリソース: jenkins/security/csrf/Messages.properties

---

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

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

### 推奨読解順序

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

CrumbIssuerインターフェースとその実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CrumbIssuer.java | `core/src/main/java/hudson/security/csrf/CrumbIssuer.java` | CSRF保護の基本インターフェース |
| 1-2 | DefaultCrumbIssuer.java | `core/src/main/java/hudson/security/csrf/DefaultCrumbIssuer.java` | デフォルト実装 |

**読解のコツ**: CrumbIssuerはCSRFトークン（Crumb）を発行・検証する役割を持つ点に注目。

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

CSRFAdministrativeMonitorクラスがエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CSRFAdministrativeMonitor.java | `core/src/main/java/jenkins/security/csrf/CSRFAdministrativeMonitor.java` | isActivated()でCrumbIssuer存在チェック |

**主要処理フロー**:
1. **43-46行目**: `getDisplayName()` - 表示名取得
2. **48-51行目**: `isActivated()` - `Jenkins.get().getCrumbIssuer() == null`でCSRF保護無効を検出
3. **53-56行目**: `isSecurity()` - trueを返しセキュリティ関連通知としてマーク

#### Step 3: ビューテンプレートを理解する

Jellyテンプレートで警告UIを構成。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | message.jelly | `core/src/main/resources/jenkins/security/csrf/CSRFAdministrativeMonitor/message.jelly` | 警告メッセージとリンク構成 |

**主要処理フロー**:
- **26行目**: jenkins-alert-warningクラスで警告スタイル適用
- **27-29行目**: Dismissフォーム
- **30-35行目**: 外部ドキュメントリンクとアクションリンクの設定
- **36-38行目**: メッセージ表示

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

```
Jenkins.getAdministrativeMonitors()
    │
    ├─ CSRFAdministrativeMonitor.isEnabled()
    │      └─ Jenkins.getDisabledAdministrativeMonitors().contains(id)
    │
    ├─ CSRFAdministrativeMonitor.isActivated()
    │      └─ Jenkins.getCrumbIssuer() == null
    │
    └─ CSRFAdministrativeMonitor.isSecurity()
           └─ return true
```

### データフロー図

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

管理画面アクセス ───▶ isActivated()チェック ───▶ 警告バナー表示
                         │
                         └─ Jenkins.getCrumbIssuer()
                                    │
                                    ▼
                            config.xml参照
                            (crumbIssuer要素)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CSRFAdministrativeMonitor.java | `core/src/main/java/jenkins/security/csrf/CSRFAdministrativeMonitor.java` | ソース | メインクラス |
| AdministrativeMonitor.java | `core/src/main/java/hudson/model/AdministrativeMonitor.java` | ソース | 基底クラス |
| CrumbIssuer.java | `core/src/main/java/hudson/security/csrf/CrumbIssuer.java` | ソース | CSRF保護インターフェース |
| DefaultCrumbIssuer.java | `core/src/main/java/hudson/security/csrf/DefaultCrumbIssuer.java` | ソース | デフォルト実装 |
| message.jelly | `core/src/main/resources/jenkins/security/csrf/CSRFAdministrativeMonitor/message.jelly` | テンプレート | 警告バナーUI |
| description.jelly | `core/src/main/resources/jenkins/security/csrf/CSRFAdministrativeMonitor/description.jelly` | テンプレート | 説明文 |
| Messages.properties | `core/src/main/resources/jenkins/security/csrf/Messages.properties` | リソース | メッセージ定義 |
| CSRFAdministrativeMonitorTest.java | `test/src/test/java/jenkins/security/csrf/CSRFAdministrativeMonitorTest.java` | テスト | 単体テスト |
