概要 — 何をする画面か
セキュリティ ▸ 問題解決 は、セキュリティのインシデントと侵害への対応を、5段階のパイプラインを持つ単一のケースボードとして管理します。
open → investigating → cause_identified → resolved → closed
すべてのケースは 500レポート構造(直接原因/根本原因/解決/再発防止策)と、監査可能なタイムラインを持ちます。この画面は サービス ▸ 問題解決 のコントローラーをミラーリングしたものです。同じ infr_incident テーブルを共有しつつ area='security' で絞り込み、セキュリティのケースをサービスのインシデントから分離しています。
ケースがこのボードに載る経路は2つあります。
- 手動登録 — 運用担当者がケースを作成します。選択できる source は
manual·agency·quarantineです。 - 診断からの昇格 — セキュリティ診断 の
fail + critの検出結果が、自動的にケースへ昇格します(source=detection)。これはシステム専用の source であり、担当者が手で選ぶことはできません。
このコンソールは、リモートの crontab やファイアウォールを直接操作しません。人間による対応プロセスを記録・追跡するためのワークフローツールです。実際のブロックや隔離の操作は ブロックリスト と 自動ブロック にあります。
こんなときに使う
- IDS/AI の検知(脅威、検知 · JA3)から得られた侵害の疑いが確定したものを、調査と解決の履歴が残る正式なケースへ昇格させるとき。
- agency(CERT、法執行機関)との協力要請や侵害報告を追跡するとき。
- quarantine(隔離)状態のホストを、復旧と再投入まで管理するとき。
- セキュリティ診断 が
fail+critと判定したハードニングやルートキットのリスクを、自動作成されたケースとして受け取り、担当を割り当てるとき。 - 事後に MTTR と累計ダウンタイムを算出し、直接原因・根本原因・再発防止策を文書化するとき。
画面構成
KPI ストリップ
| KPI | 定義 |
|---|---|
| total | area='security' のケースの総数 |
| active | open + investigating + cause_identified の合計 |
| resolved | resolved + closed の合計 |
| MTTR | occurred_at と resolved_at の両方を持つケースの平均分数 |
| downtime | 全ケースの downtime_min の合計 |
| uptime target | OpsPolicy::slaDefaults()['uptime_target'] |
ケースボード
ケースは次の順で並びます。
- ステータス順位 —
open→investigating→cause_identified→resolved→closed - 深刻度順位 —
crit→warn→info - 新しい順 —
idの降順
各カードには、タイトル、深刻度、ステータス、source バッジ、紐付いたプロジェクト/サービス、発生時刻、ダウンタイム、イベント件数が表示されます。
詳細モーダル
ケースを開くと、2つのペインに分かれます。
- レポート — サマリー、直接原因、根本原因、解決、再発防止策の各フィールド。
- タイムライン —
infr_incident_eventの履歴(作成、ノート、ステータス変更、…)を時系列で表示します。
上部のステータスパイプラインをクリックすると、ステップ遷移ダイアログが開きます。「このステップで何をするか」のガイドが表示され、その段階のレポートフィールドをその場で更新できます。
使い方
ケースを作成する(手動)
- 上部の [ケースを登録] をクリックします。
- タイトル(必須)、深刻度、source(
manual/agency/quarantine)を入力します。 - 必要に応じて、プロジェクト、サービス、URL、発生時刻、影響範囲、ダウンタイム(分)を設定します。
- [保存] —
status=open、area=security、detected_at=now()で新しいケースが作成され、タイムラインにcreatedイベントが記録されます。
detectionは source の一覧に表示されません。セキュリティ診断が自動生成する、システム専用の source だからです。
ステータス遷移(パイプライン)
詳細モーダルのパイプラインで、遷移先のステータスをクリックします。各段階で推奨される作業は次のとおりです。
| 段階 | この段階ですること |
|---|---|
| open | 受付状態に戻します(分析を始める前) |
| investigating | 症状を確認し、影響範囲を見極め、サマリーを記述します |
| cause_identified | 直接原因と、その背景にある根本原因を特定して記録します |
| resolved | 復旧方法と再発防止策を記録します |
| closed | 対処と防止策が適用されていることを確認し、ケースを終了します |
サーバー側の遷移ルール:
resolvedへ移すと、resolved_atが空だった場合にnow()で埋められます。closedへ移すと、ダイアログで指定された終了日時の値が使われます。指定がない場合は、まだ値がないときに限りnow()が既定値になります。- ステータスが実際に変化した場合、
status_change(from→to)イベントがタイムラインに記録されます。ノートを添えるとnoteイベントも追加されます。
協業ノート
詳細モーダルでノートを追加すると、タイムラインに kind=note のイベントが記録されます。ノート専用のテーブルはありません — ノートは infr_incident_event に統合されています。
削除
ケースを削除すると、その infr_incident_event の行も削除され、監査ログに記録されます。(昇格元となった診断スキャンは独立しており、削除されません。)
昇格したケースの自動解消
セキュリティ診断 がプローブ結果を取り込むと、DiagnosticsService::reconcileCases() がホストごとにケースを突き合わせます。
fail + critの検出結果 →fingerprintをキーとして未解決のケースを upsert します(再発時はoccurrence_countが加算されます)。- 後続のスキャンでその項目が合格した/消えた場合 → 未解決のケースが自動的に解消されます(
status=resolved、resolved_at、resolution=auto-resolved text)。あわせてstatus_changeのタイムラインイベントが記録されます。
自動解消は、診断チェックが再び合格したときにのみ発動します。手動で作成したケース(
manual/agency/quarantine)が自動的に解消されることはありません — 担当者がパイプラインに沿って遷移させる必要があります。
データソース
テーブル
| テーブル | 役割 |
|---|---|
infr_incident |
ケース本体(area='security' で絞り込み)。ステータス、深刻度、source、500レポートの各フィールド、発生/解決/終了の時刻、fingerprint、occurrence_count |
infr_incident_event |
ケースのタイムライン(作成、ノート、ステータス変更、…) |
infr_project |
紐付け用のプロジェクト一覧 |
infr_service |
紐付け用のサービス一覧 |
列挙値
STATUSES = [open, investigating, cause_identified, resolved, closed]
SEVERITIES = [info, warn, crit]
SOURCES = [manual, pulse, alert, agency, quarantine, detection] # すべて
manual-selectable sources = [manual, agency, quarantine]
OPEN_STATUSES (dedup targets) = [open, investigating, cause_identified]
AREAS = [service, security] # 共有テーブルの分割軸
レポートフィールド(500構造)
| フィールド | 意味 |
|---|---|
summary |
症状/影響のサマリー |
direct_cause |
直接的な原因(例: MySQL Too many connections) |
root_cause |
背景/根本原因(例: スクリプトの接続リーク) |
resolution |
インシデント中に実施した復旧措置 |
action_taken |
今後に向けた再発防止策 |
downtime_min |
ダウンタイム(分)— downtime KPI の元データ |
impact |
影響を受けた範囲 |
API エンドポイント
| メソッド · パス | 用途 |
|---|---|
GET /security/resolution |
ボードの初回描画 |
GET /security/resolution/live |
ポーリング更新(ケース、KPI、タイムスタンプ) |
POST /security/resolution/save |
ケースの作成/更新 |
POST /security/resolution/transition |
ステータス遷移(+任意のノート/レポート更新) |
POST /security/resolution/note |
協業ノートの追加 |
POST /security/resolution/delete |
ケースの削除 |
アクセス権限
- 読み取り: セキュリティのグループ全体が
infr.level:2ミドルウェアで保護されています。レベル2以上(staff=5 · admin=10)だけが入れます。デモ(1)はブロックされます。 - 書き込み(保存/遷移/ノート/削除): コントローラーの
canWrite()がセッションのinfr_user_level >= 2を再確認します。満たさない場合は403(resolution.err.forbidden)を返します。 - 監査: すべての書き込みが
infr_audit_logに記録されます —sec.incident_create·sec.incident_update·sec.incident_transition·sec.incident_delete。遷移では meta に{from,to}が、保存では{title,severity}が保存されます。監査ログ を参照してください。
トラブルシューティングとFAQ
Q. サービスのボードで見えているケースが、ここにありません。
どちらのボードも同じ infr_incident テーブルを共有していますが、area で分かれています。この画面が表示するのは area='security' だけです。サービスのインシデントは サービス ▸ 問題解決 で探してください。
Q. detection の source でケースを作成できません。
仕様どおりです。detection は セキュリティ診断 が fail+crit の検出結果から自動作成する、システム専用の source です。手動登録で選べるのは manual、agency、quarantine だけです。
Q. 自動昇格したケースが、ひとりでに解決済みになりました。
後続のスキャンで元の診断チェックが合格すると、reconcileCases() が未解決のケースを自動的に解消します。resolution には自動解消のテキストが入り、ステータス変更のイベントが追加されます。
Q. MTTR が空欄です。
MTTR は、occurred_at と resolved_at の両方を持つケースについてのみ算出されます。発生時刻がないケースや、まだ解決していないケースは除外されます。
Q. 過去の終了日時を設定できますか。
できます。終了ダイアログの終了日時フィールドに値を入力すると(発生時刻と同じインターフェースです)、そのまま保存されます。空のままにした場合、サーバーはまだ値がないときに限り now() を入れます。
Q. ケースを削除すると、診断スキャンも消えますか。 消えません。昇格したケースと、その元になった診断スキャンは独立しています。ケースを削除しても、紐付いたタイムラインイベントが消えるだけです。
関連項目
- セキュリティ診断 —
fail+critの検出結果をこのボードへ自動昇格させる供給元。 - サービスの問題解決 — 同じワークフローの、サービス側(
area='service')のミラー。 - セキュリティ概要 — 脅威 → 検知 → 対応という防御ファネルの物語。
- 脅威 · 検知 · JA3 — ケースへ昇格させる侵害候補の供給元。
- 監査ログ — ケースへの書き込み操作の永続的な記録。
