# 帳票設計書 75-監査ログ（Webhook送信）

## 概要

本ドキュメントは、Kubernetes APIサーバの監査イベントをHTTP Webhook経由で外部サービスに送信する帳票の設計書である。audit webhookバックエンドとして提供される。

### 本帳票の処理概要

本帳票は、Kubernetes APIサーバの監査イベントをEventListとしてバッチ化し、HTTP POSTリクエストで外部のWebhookエンドポイントに送信する機能を提供する。

**業務上の目的・背景**：ローカルファイルへの監査ログ出力（No.73/74）では、ログの集約・分析にファイル転送が必要となる。Webhook送信は、監査イベントをリアルタイムに外部サービス（SIEM、ログ集約基盤、カスタム監査サービス等）へ直接送信することで、ログ転送の遅延を最小化し、リアルタイム監視やアラートを実現することを目的としている。

**帳票の利用シーン**：外部監査サービスとのリアルタイム連携に利用される。例えば、SIEMツール（Splunk, QRadar等）へのリアルタイム監査データ送信、カスタム監査Webhookサービスによる特定イベントの検知・通知、マルチクラスタ環境での監査ログの中央集約などに使用される。

**主要な出力内容**：
1. EventList形式（複数の監査イベントをバッチ化）
2. 各EventはJSON形式でシリアライズ
3. HTTP POSTリクエストのBody部として送信

**帳票の出力タイミング**：APIサーバが監査イベントを生成した際に、ProcessEventsが呼び出されるたびに外部Webhookへ送信される。

**帳票の利用者**：セキュリティ管理者、SIEM管理者、クラスタ管理者

## 帳票種別

監査ログ（Webhook送信）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | APIサーバ設定 | kube-apiserver --audit-webhook-config-file | APIサーバ起動時設定 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | HTTP POST リクエストBody（JSON） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A（HTTP通信） |
| 出力方法 | HTTP POST リクエストによるWebhook送信 |
| 文字コード | UTF-8 |

### Webhook送信仕様

| 項目 | 内容 |
|-----|------|
| HTTPメソッド | POST |
| リクエストBody | auditinternal.EventList（JSONシリアライズ） |
| リトライ | 指数バックオフ付きリトライ（DefaultInitialBackoffDelay = 10秒） |
| リトライ判定 | すべてのエラーでリトライ（retryOnError関数） |
| 設定ファイル | kubeconfig形式のWebhook設定ファイル |

## 帳票レイアウト

### レイアウト概要

EventList構造体としてバッチ化された監査イベントがHTTP POSTのBody部としてJSON形式で送信される。

```json
{
  "kind": "EventList",
  "apiVersion": "audit.k8s.io/v1",
  "items": [
    {
      "level": "Metadata",
      "auditID": "abc-123",
      "stage": "ResponseComplete",
      "requestURI": "/api/v1/namespaces/default/pods",
      "verb": "get",
      "user": {"username": "admin"},
      ...
    }
  ]
}
```

### ヘッダー部

ヘッダー部は存在しない（HTTPリクエストBody部のJSON構造はEventListのスキーマに従う）。

### 明細部

EventListのitemsフィールドに含まれる各Eventは、No.74（JSON形式）と同一のフィールド構造を持つ。

| No | 項目名 | JSONキー | 説明 | データ取得元 |
|----|-------|---------|------|-------------|
| 1 | Kind | kind | 固定値"EventList" | EventList.TypeMeta.Kind |
| 2 | APIVersion | apiVersion | APIバージョン | EventList.TypeMeta.APIVersion |
| 3 | Items | items | 監査イベント配列 | EventList.Items |

各Item内のフィールドはNo.74（JSON形式）の明細部と同一。

### フッター部

フッター部は存在しない。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 監査ポリシー | audit.k8s.io/v1 Policy で定義されたルール | Yes |
| Webhook設定 | kubeconfig形式の設定ファイル | Yes |

### ソート順

イベントはProcessEventsに渡された順序で送信される。

### 改ページ条件

該当なし。

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照しない。

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| auditinternal.Event | 監査イベント本体 | apiserver/pkg/apis/audit/types.go で定義 |
| auditinternal.EventList | イベントバッチ | items []Event |

### テーブル別参照項目詳細

#### auditinternal.EventList

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| Items | Webhook Body | ProcessEventsの引数から構築 | 可変長配列 |

## 計算仕様

### 計算項目一覧

本帳票には計算項目は存在しない。

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[APIリクエスト受信] --> B[監査ポリシー評価]
    B --> C{監査レベル判定}
    C -->|None| D[出力なし]
    C -->|Metadata以上| E[Eventオブジェクト生成]
    E --> F[ProcessEvents呼び出し]
    F --> G[processEvents: EventListを構築]
    G --> H[WithExponentialBackoff: リトライ付き送信]
    H --> I[RestClient.Post().Body(&list).Do(ctx)]
    I --> J{送信成功?}
    J -->|Yes| K[終了]
    J -->|No| L[retryOnError: リトライ判定]
    L --> H
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 送信エラー | Webhookエンドポイントへの接続失敗 | HandlePluginError経由で記録 | Webhookエンドポイントの可用性確認 |
| Webhook設定エラー | kubeconfig読み込み失敗 | loadWebhook関数のエラー | 設定ファイルのパス・内容確認 |
| リトライ超過 | 指数バックオフの上限到達 | HandlePluginError経由で記録 | Webhookエンドポイントの復旧確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | APIリクエスト数に比例（毎秒数十〜数千イベント） |
| 目標出力時間 | Webhookエンドポイントの応答時間に依存 |
| 同時出力数上限 | APIサーバの並行リクエスト数に依存 |
| トレーシング閾値 | 50ms + 25ms * イベント数 |

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

- Webhook設定ファイル（kubeconfig形式）には認証情報が含まれる可能性があるため、ファイルアクセス制御が必要
- 送信データにはリクエスト/レスポンスボディが含まれる場合があり、機密情報の取り扱いに注意
- TLS通信の使用を推奨
- retryOnError関数はすべてのエラーでリトライするため、リトライ時にも監査データが送信される可能性がある

## 備考

- retryOnError関数はエラーが発生した場合に常にtrueを返し、すべてのエラーでリトライする。これはデフォルト実装の保守的なリトライ判定（限られたHTTPエラーコードのみリトライ）では監査イベントのドロップにつながるためである
- NewDynamicBackend関数は、REST clientを直接渡してバックエンドを構築する（動的設定用）
- NewBackend関数は、kubeconfig設定ファイルからWebhookを構成する（静的設定用）
- OpenTelemetryトレーシングが統合されており、"Call Audit Events webhook"というスパン名で送信をトレースする
- トレーシング閾値は50ms + 25ms * イベント数で、シリアライゼーション時間を考慮した設定

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `staging/src/k8s.io/apiserver/pkg/apis/audit/types.go` | Event構造体（行79-152）とEventList構造体（行162-170）を確認 |
| 1-2 | webhook.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go` | backend構造体（行82-85）でGenericWebhookとname文字列を確認 |

**読解のコツ**: Webhookバックエンドのbackend構造体はログバックエンド（No.73/74）とは異なり、GenericWebhookをラップしている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | webhook.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go` | NewBackend関数（行101-107）でkubeconfigからWebhookを構成する静的初期化を理解 |
| 2-2 | webhook.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go` | NewDynamicBackend関数（行89-98）でRESTClientから直接構成する動的初期化を理解 |
| 2-3 | webhook.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go` | loadWebhook関数（行67-80）でkubeconfig読み込みとGenericWebhook生成を確認 |

**主要処理フロー**:
1. **行101-107**: NewBackendでloadWebhookを呼び出しbackend構造体を生成
2. **行67-80**: loadWebhookでkubeconfig読み込み、GenericWebhook生成、ShouldRetry設定

#### Step 3: イベント送信処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | webhook.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go` | ProcessEvents関数（行117-123）とprocessEvents関数（行125-142）で送信ロジックを理解 |
| 3-2 | webhook.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go` | retryOnError関数（行60-65）でリトライ判定ロジック（常にtrue）を確認 |

**主要処理フロー**:
- **行125-129**: EventListを構築（各EventをItems配列に追加）
- **行130-141**: WithExponentialBackoffで指数バックオフ付きHTTP POST送信
- **行131-133**: OpenTelemetryトレーシングスパンの開始
- **行139**: トレーシング閾値の計算（50ms + 25ms * イベント数）
- **行140**: RestClient.Post().Body(&list).Do(ctx) でHTTP POST送信

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

```
kube-apiserver (監査ハンドラ)
    |
    +-- webhook.Backend.ProcessEvents (webhook.go:117)
            |
            +-- processEvents (webhook.go:125)
                    |
                    +-- EventList構築 (webhook.go:126-129)
                    |
                    +-- WithExponentialBackoff (webhook.go:130)
                            |
                            +-- tracing.Start("Call Audit Events webhook") (webhook.go:131)
                            +-- RestClient.Post().Body(&list).Do(ctx) (webhook.go:140)
                            +-- span.End() (webhook.go:139)
                            |
                            +-- [エラー時] retryOnError (webhook.go:60) -> true -> リトライ
```

### データフロー図

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

APIリクエスト              監査ポリシー評価
(audit.Event[]) -------> ProcessEvents() ----+
                                              |
                          processEvents()      |
                          EventList構築        +--> HTTP POST --> Webhookエンドポイント
                          WithExponentialBackoff     (JSON Body)    (外部サービス)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| webhook.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/webhook/webhook.go` | ソース | Webhook監査バックエンド本体 |
| types.go | `staging/src/k8s.io/apiserver/pkg/apis/audit/types.go` | ソース | 監査イベント型定義 |
| webhook.go (util) | `staging/src/k8s.io/apiserver/pkg/util/webhook/webhook.go` | ソース | GenericWebhookユーティリティ |
| install.go | `staging/src/k8s.io/apiserver/pkg/apis/audit/install/install.go` | ソース | audit Schemeへの型登録 |
