Feature 39: 監査ログシステム
Copyright: 2026 Moonlight Technologies Inc.
Author: Masahiro Aoki
実装日: 2026年2月20日
バージョン: 1.0.0
ステータス: ✅ 実装済み
概要
EvoSpikeNet の監査ログシステム(Feature 39)は、SHA-256 ハッシュチェーンを利用した改ざん検知機能付きの監査ログを提供します。コンプライアンス要件(SOC 2・ISO 27001 等)への対応と、セキュリティインシデントの事後調査を支援します。
全 HTTP リクエストは Starlette ミドルウェアによって自動的に記録されます。
ハッシュチェーンの仕組み
各 AuditEntry は以下の情報を含み、前エントリのハッシュを参照することで改ざんを検知できます。
Entry N-1: hash = SHA256(id + timestamp + action + ... + prev_hash)
│
▼ prev_hash
Entry N: hash = SHA256(id + timestamp + action + ... + prev_hash_N)
│
▼ prev_hash
Entry N+1: hash = SHA256(id + timestamp + action + ... + prev_hash_N+1)
一つのエントリが改ざんされると、それ以降の全エントリのハッシュが不整合となり、verify_chain() で検出されます。
コアコンポーネント
AuditEntry
一件の監査ログレコードです。SHA-256 ハッシュで整合性を保証します。
<!-- from evospikenet.audit_log import AuditEntry, AuditAction, AuditResult -->
from datetime import datetime, timezone
entry = AuditEntry(
action=AuditAction.MODEL_LOAD,
actor="admin_user",
resource="/api/models/load",
result=AuditResult.SUCCESS,
detail={"model": "genome_v3"},
prev_hash="d9e8f7a6...",
)
print(entry.entry_hash) # SHA256 ハッシュ
フィールド:
| フィールド | 型 | 説明 |
|---|---|---|
id |
str | UUID v4 自動生成 |
timestamp |
str | UTC ISO-8601 タイムスタンプ |
action |
str (AuditAction) | 実行アクション |
actor |
str | 操作者 (username, system, etc.) |
resource |
str | 対象リソース (パス等) |
result |
str (AuditResult) | success / failure / partial |
detail |
dict | 追加情報(任意) |
ip_address |
str | クライアント IP(任意) |
prev_hash |
str | 前エントリのハッシュ(チェーン) |
entry_hash |
str | このエントリの SHA-256 ハッシュ |
AuditLogManager
監査ログの管理クラスです。NDJSON 形式でファイルに永続化します。
<!-- TODO: update or remove - import failuditLogManager, AuditAction -->
# インスタンス生成(通常はシングルトンを使用)
log = AuditLogManager(
log_dir="data/audit_logs", # ログディレクトリ
max_memory=10000, # インメモリ保持件数
)
# エントリ書き込み
entry = log.log(
action=AuditAction.MODEL_TRAIN,
actor="admin_user",
resource="/api/models/genome_v3",
result="success",
detail={"version": "3.2.1"},
)
# 検索
entries = log.query(
actor="admin_user",
action_prefix="model.",
result="success",
since=datetime(2026, 2, 1, tzinfo=timezone.utc),
limit=100,
)
# ハッシュチェーン検証
valid, checked, error = log.verify_chain()
# エクスポート
json_data = log.export_json() # list of dicts
csv_data = log.export_csv() # CSV 文字列
AuditAction 一覧
class AuditAction(str, Enum):
# Auth
AUTH_LOGIN = "auth.login"
AUTH_LOGOUT = "auth.logout"
AUTH_FAILED = "auth.failed"
API_KEY_CREATE = "auth.api_key.create"
API_KEY_REVOKE = "auth.api_key.revoke"
# Model / inference
MODEL_LOAD = "model.load"
MODEL_INFERENCE = "model.inference"
CHECKPOINT_SAVE = "checkpoint.save"
CHECKPOINT_RESTORE = "checkpoint.restore"
# Evolution / genome
EVOLUTION_START = "evolution.start"
EVOLUTION_STOP = "evolution.stop"
GENOME_SAVE = "genome.save"
GENOME_APPLY = "genome.apply"
FITNESS_OVERRIDE = "evolution.fitness_override"
# Data
DATA_READ = "data.read"
DATA_WRITE = "data.write"
DATA_DELETE = "data.delete"
DATA_EXPORT = "data.export"
# Configuration
CONFIG_CHANGE = "config.change"
SECURITY_CHANGE = "security.change"
# Infrastructure
NODE_REGISTER = "node.register"
NODE_DEREGISTER = "node.deregister"
FAILOVER = "infra.failover"
SNAPSHOT_CREATE = "snapshot.create"
SNAPSHOT_RESTORE = "snapshot.restore"
SNAPSHOT_DELETE = "snapshot.delete"
# Recovery
RECOVERY_INCIDENT = "recovery.incident"
RECOVERY_ACTION = "recovery.action"
# Generic
HTTP_REQUEST = "http.request"
SYSTEM_EVENT = "system.event"
HTTP 自動ログ(ミドルウェア)
make_audit_middleware() によって (Starlette/FastAPI) 全 HTTP リクエストが
自動的に記録されます。
# api.py での設定(起動時に実行)
<!-- モジュール 'evospikenet' が見つかりません。パッケージ内の移動/名前変更を確認してください -->
<!-middleware("http")(make_audit_middleware(audit_log))
自動ログのフォーマット:
- actor: X-API-Key ヘッダーから取得、存在しない場合は "anonymous"。
返される値は先頭12文字を取り "..." を付加(例 abcd1234efgh...)。
- action: AuditAction.HTTP_REQUEST
- resource: リクエストパス (request.url.path)
- detail: 辞書。現在の実装では以下のキーを含む。
{
"method": "POST",
"path": "/api/models/train",
"status_code": 200,
"query": "foo=bar" // 空の場合は空文字列
}
success、それ以外 → failure
- ip_address: クライアント IP (request.client.host があれば)
REST API
GET /api/audit/logs
クエリパラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
actor |
str | 指定文字列を含む操作者でフィルタ |
action |
str | 完全一致または前方一致 (例 model.、auth.login) |
resource |
str | リソースパスの部分一致 |
result |
str | success / failure / partial |
since |
str | ISO-8601 形式開始時刻 |
until |
str | ISO-8601 形式終了時刻 |
limit |
int | 最大件数 (デフォルト100, 最大1000) |
offset |
int | ページオフセット |
レスポンス例:
{
"total": 1,
"offset": 0,
"limit": 100,
"entries": [
{
"id": "550e8400-...",
"timestamp": "2026-02-20T10:00:00.000Z",
"action": "model.load",
"actor": "admin_user",
"resource": "/api/models/load",
"result": "success",
"detail": { "model": "genome_v3" },
"ip_address": "203.0.113.5",
"prev_hash": "d9e8f7a6...",
"entry_hash": "a3f1b2c4..."
}
]
}
GET /api/audit/stats
監査ログ統計を返します。
レスポンス例:
{
"total_entries_in_memory": 1500,
"log_files": 5,
"current_log_file": "data/audit_logs/audit_20260220T123456Z.ndjson",
"entries_in_current_file": 1234,
"by_action": {
"http.request": 800,
"model.load": 300,
"auth.login": 50
},
"by_result": {
"success": 1400,
"failure": 80,
"partial": 20
}
}
GET /api/audit/verify
ハッシュチェーン整合性を検証します。max_entries クエリパラメータ
(省略時1000)で検査件数を指定できます。
レスポンス例 (整合):
{ "valid": true, "checked": 1500, "broken_at": null, "message": "Chain intact" }
レスポンス例 (破損検知):
{
"valid": false,
"checked": 750,
"broken_at": 750,
"message": "Chain broken at position 750"
}
GET /api/audit/export
ログを json または csv 形式でエクスポートします。
- format:
json(既定)またはcsv - since, until: ISO-8601
返却は Content-Disposition ヘッダ付きのプレーンテキスト応答。
POST /api/audit/log
手動でエントリを書き込みます。外部サービスや SDK から利用。
リクエストボディ例:
{
"action": "model.inference",
"actor": "service-account",
"resource": "/api/generate",
"result": "success",
"detail": { "latency_ms": 120 }
}
レスポンス例:
{
"status": "logged",
"entry_id": "550e8400-e29b-41d4-a716-446655440001",
"entry_hash": "a3f1b2c4..."
}
ハッシュチェーンの整合性を検証します。
レスポンス (正常):
{ "valid": true, "checked": 1500, "error": null }
レスポンス (改ざん検出):
{
"valid": false,
"checked": 750,
"error": "Hash mismatch at entry 750: expected abc..., got xyz..."
}
GET /api/audit/export
クエリパラメータ: format = json または csv
ファイル構造
data/
audit_logs/
audit_2026-02-20.ndjson ← 日次ローテーション
audit_2026-02-19.ndjson
...
NDJSON 形式(1行1エントリ のJSON)で永続化されます。
性能指標
| メトリクス | 目標値 | テスト参照 |
|---|---|---|
| 書き込みスループット | ≥ 1,000 エントリ/秒 | test_write_throughput_1000_entries |
| 並行書き込み (8スレッド) | ≥ 500 エントリ/秒/スレッド | test_concurrent_writes_throughput |
| ハッシュチェーン検証 (1,000件) | < 5,000 ms | test_hash_chain_verify_1000_entries |
| クエリレイテンシ (500件ヒット) | < 200 ms | test_query_latency_1000_entries |
テスト
# ユニットテスト
pytest tests/unit/test_audit_log.py -v
# 結合テスト
pytest tests/integration/test_features_36_39_40_integration.py::TestAuditLogEndpoints -v
# システムテスト(並行書き込み)
pytest tests/system/test_features_36_39_40_system.py::TestConcurrentAuditLog -v
# 性能テスト
pytest tests/performance/test_features_36_39_40_performance.py::TestAuditLogPerformance -v
関連ドキュメント
- SDK API Reference - Feature 39
audit_log_sdk.py- 自動リカバリー
- 地理的分散ノード管理