# 帳票設計書 74-監査ログ（JSON形式）

## 概要

本ドキュメントは、Kubernetes APIサーバの監査イベントを構造化JSON形式でログファイルに出力する帳票の設計書である。audit logバックエンドの `FormatJson` モードとして提供される。

### 本帳票の処理概要

本帳票は、Kubernetes APIサーバに対するすべてのAPIリクエストの監査イベントを、構造化されたJSON形式でログファイルに記録する機能を提供する。Legacy形式（No.73）と同じbackend構造体を共有するが、出力形式がJSONである点が異なる。

**業務上の目的・背景**：Legacy形式の1行テキストは人間が読みやすい一方、機械的な解析やログ集約システム（Elasticsearch, Splunk, Fluentd等）との統合には構造化データが適している。JSON形式は、監査イベントの全フィールドを構造化された形式で出力することで、ログ分析基盤との連携やプログラマティックな処理を容易にすることを目的としている。

**帳票の利用シーン**：ログ集約・分析基盤と連携した監査ログ管理に利用される。例えば、Elasticsearchへの投入によるインデックス化・検索、SIEMツールでのリアルタイム監視・アラート、Fluentdによるログ転送・変換、コンプライアンス要件に基づく長期保存・分析などに使用される。

**主要な出力内容**：
1. audit.Event構造体の全フィールドをJSON形式で出力
2. 監査レベルに応じてRequestObject/ResponseObjectも含まれる
3. APIバージョン情報（apiVersion, kind）が含まれる
4. Annotations（監査注釈）も含まれる

**帳票の出力タイミング**：APIサーバがリクエストを処理する各ステージで、監査ポリシーに基づいてイベントが生成される都度出力される。

**帳票の利用者**：セキュリティ管理者、SREチーム、ログ分析基盤管理者

## 帳票種別

監査ログ（JSON形式）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | APIサーバ設定 | kube-apiserver --audit-log-path --audit-log-format=json | APIサーバ起動時設定 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON（1イベント1行のJSON Lines形式） |
| 用紙サイズ | N/A（ログファイル） |
| 向き | N/A |
| ファイル名 | --audit-log-pathで指定されたファイルパス |
| 出力方法 | io.Writerへのストリーム書き込み |
| 文字コード | UTF-8 |

### JSON出力仕様

| 項目 | 内容 |
|-----|------|
| シリアライゼーション | runtime.Encode（audit.Codecs.LegacyCodec使用） |
| GroupVersion | NewBackend呼び出し時に指定されたGroupVersion |
| 1行の形式 | JSON文字列（改行なし、runtime.Encodeの出力そのまま） |

## 帳票レイアウト

### レイアウト概要

1イベント1行のJSON Lines形式で出力する。各行は完全なJSONオブジェクトである。

```json
{"kind":"Event","apiVersion":"audit.k8s.io/v1","level":"Metadata","auditID":"abc-123","stage":"ResponseComplete","requestURI":"/api/v1/namespaces/default/pods","verb":"get","user":{"username":"admin","groups":["system:masters"]},"sourceIPs":["192.168.1.1"],"userAgent":"kubectl/v1.29.0","objectRef":{"resource":"pods","namespace":"default","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":200},"requestReceivedTimestamp":"2024-01-15T10:30:00.000000Z","stageTimestamp":"2024-01-15T10:30:00.001000Z"}
```

### ヘッダー部

ヘッダー部は存在しない。

### 明細部

各JSON行は以下のフィールドを含む（監査レベルに応じて出力されるフィールドが異なる）。

| No | 項目名 | JSONキー | 説明 | データ取得元 | 出力条件 |
|----|-------|---------|------|-------------|---------|
| 1 | Kind | kind | 固定値"Event" | TypeMeta.Kind | 常時 |
| 2 | APIVersion | apiVersion | APIバージョン | TypeMeta.APIVersion | 常時 |
| 3 | 監査レベル | level | None/Metadata/Request/RequestResponse | Event.Level | 常時 |
| 4 | 監査ID | auditID | リクエスト一意ID | Event.AuditID | 常時 |
| 5 | ステージ | stage | リクエスト処理ステージ | Event.Stage | 常時 |
| 6 | リクエストURI | requestURI | リクエストパス | Event.RequestURI | 常時 |
| 7 | Verb | verb | 操作種別 | Event.Verb | 常時 |
| 8 | ユーザ情報 | user | ユーザ名・グループ等 | Event.User | 常時 |
| 9 | 偽装ユーザ | impersonatedUser | 偽装ユーザ情報 | Event.ImpersonatedUser | 設定時のみ |
| 10 | ソースIP | sourceIPs | クライアントIP | Event.SourceIPs | 設定時のみ |
| 11 | User-Agent | userAgent | クライアント識別子 | Event.UserAgent | 設定時のみ |
| 12 | オブジェクト参照 | objectRef | 対象リソース情報 | Event.ObjectRef | 設定時のみ |
| 13 | レスポンスステータス | responseStatus | HTTPステータス | Event.ResponseStatus | 設定時のみ |
| 14 | リクエストボディ | requestObject | リクエスト内容 | Event.RequestObject | Request以上 |
| 15 | レスポンスボディ | responseObject | レスポンス内容 | Event.ResponseObject | RequestResponse |
| 16 | リクエスト受信時刻 | requestReceivedTimestamp | リクエスト受信時刻 | Event.RequestReceivedTimestamp | 常時 |
| 17 | ステージ時刻 | stageTimestamp | ステージ到達時刻 | Event.StageTimestamp | 常時 |
| 18 | 注釈 | annotations | 監査注釈 | Event.Annotations | 設定時のみ |

### フッター部

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

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 監査ポリシー | audit.k8s.io/v1 Policy で定義されたルール | Yes |
| 監査レベル | None/Metadata/Request/RequestResponse | Yes |
| OmitStages | 除外するステージ | No |
| OmitManagedFields | ManagedFieldsの除外 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | イベント発生順（時系列） | 昇順 |

### 改ページ条件

改ページは発生しない（1行1イベントのストリーム出力）。

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

### 参照テーブル一覧

本帳票はデータベースを参照せず、APIサーバ内部の監査イベントオブジェクトを直接処理する。

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

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

#### auditinternal.Event

No.73（Legacy形式）と同一のEvent構造体を使用する。JSON形式ではEvent構造体の全フィールドがruntime.Encodeによりシリアライズされる。

## 計算仕様

### 計算項目一覧

本帳票には計算項目は存在しない。Event構造体がruntime.Encodeにより直接JSONにシリアライズされる。

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[APIリクエスト受信] --> B[監査ポリシー評価]
    B --> C{監査レベル判定}
    C -->|None| D[出力なし]
    C -->|Metadata以上| E[Eventオブジェクト生成]
    E --> F[ProcessEvents呼び出し]
    F --> G[logEvent: フォーマット判定]
    G --> H[runtime.Encode でJSON文字列生成]
    H --> I[io.Writerへ書き込み]
    I --> J[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| エンコードエラー | runtime.EncodeがEvent構造体のシリアライズに失敗 | HandlePluginError経由で記録 | Event構造体の整合性確認 |
| 書き込みエラー | io.Writerへの書き込み失敗 | HandlePluginError経由で記録 | ログファイルのディスク容量・権限確認 |
| 不明フォーマット | format値がlegacy/json以外 | "log format %q is not in list of known formats" | APIサーバ設定確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | APIリクエスト数に比例（毎秒数十〜数千イベント） |
| 目標出力時間 | 同期書き込み（APIリクエスト処理に同期） |
| 同時出力数上限 | APIサーバの並行リクエスト数に依存 |

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

- JSON形式はLegacy形式よりも多くの情報を含む（RequestObject/ResponseObject等）
- 監査レベルがRequest/RequestResponseの場合、リクエスト/レスポンスボディが含まれるため、Secretやトークン等の機密情報がログに記録される可能性がある
- OmitManagedFieldsオプションでManagedFieldsを除外し、ログサイズを削減可能
- ログファイルへのアクセス制御と暗号化を推奨

## 備考

- JSON形式はruntime.Encodeを使用してEvent構造体をシリアライズするため、Event構造体の全フィールドが出力される
- Legacy形式（No.73）との違いは出力フォーマットのみで、トリガーやデータソースは同一
- エンコーダはaudit.Codecs.LegacyCodec(groupVersion)で初期化される
- JSON出力にはruntime.Encodeの結果がそのまま使用され、追加の改行は付加されない（Legacy形式では"\n"が付加される）

---

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

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

### 推奨読解順序

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

No.73（Legacy形式）と同一のEvent構造体を使用する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `staging/src/k8s.io/apiserver/pkg/apis/audit/types.go` | Event構造体（行79-152）の全フィールド。JSON形式ではRequestObject/ResponseObject（行128-137）も出力対象となる点に注目 |

**読解のコツ**: Legacy形式ではEventStringで一部フィールドのみ出力するが、JSON形式ではruntime.EncodeによりEvent構造体全体がシリアライズされる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | backend.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend.go` | logEvent関数（行70-92）のFormatJsonケース（行75-81）を理解。runtime.Encodeによるシリアライズと、エラー時のHandlePluginError呼び出しに注目 |

**主要処理フロー**:
1. **行75**: `case FormatJson:` でJSON形式処理に分岐
2. **行76**: `runtime.Encode(b.encoder, ev)` でEvent構造体をJSON文字列にエンコード
3. **行77-79**: エンコードエラー時はHandlePluginErrorでエラーを記録しfalseを返す
4. **行81**: `line = string(bs[:])` でバイト列を文字列に変換
5. **行87**: `fmt.Fprint(b.out, line)` でio.Writerに書き込み

#### Step 3: エンコーダの初期化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | backend.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend.go` | NewBackend関数（行54-60）のencoder初期化（行58: audit.Codecs.LegacyCodec(groupVersion)）を確認 |

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

```
kube-apiserver (監査ハンドラ)
    |
    +-- audit.Backend.ProcessEvents (backend.go:62)
            |
            +-- logEvent (backend.go:70)
                    |
                    +-- [FormatJson] runtime.Encode(b.encoder, ev) (backend.go:76)
                    |       +-- audit.Codecs.LegacyCodec(groupVersion)
                    |
                    +-- fmt.Fprint(b.out, line) (backend.go:87)
```

### データフロー図

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

APIリクエスト              監査ポリシー評価
(audit.Event) ---------> ProcessEvents() ----+
                                              |
                          logEvent()           |
                          format="json"        +--> runtime.Encode() --> io.Writer
                                                    (JSON文字列)         (ログファイル)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| backend.go | `staging/src/k8s.io/apiserver/plugin/pkg/audit/log/backend.go` | ソース | 監査ログバックエンド本体（Legacy/JSON共通） |
| types.go | `staging/src/k8s.io/apiserver/pkg/apis/audit/types.go` | ソース | 監査イベント型定義 |
| scheme.go | `staging/src/k8s.io/apiserver/pkg/audit/scheme.go` | ソース | Codecs定義（JSON/protobufエンコーダ） |
| format.go | `staging/src/k8s.io/apiserver/pkg/audit/format.go` | ソース | Legacy形式文字列生成（JSON形式では不使用） |
