コンテンツへスキップ
DedicatedPHP 接触

PHPデータベースの変更監査を設計する方法

PHPアプリケーションで、誰が、何を、いつ、どのような状況で変更したかを記録し、履歴を保護して、データベース全体を複製せずに完全性を確認する方法を解説します。

PHPアプリケーションの変更を、実行者、日時、コンテキスト、対象オブジェクトに関連付けるデータ監査の図

PHPデータベースの変更監査では、重要な変更について、どのオブジェクトが変更されたか、誰が操作を開始したか、いつ発生したか、どのような状況だったかを再構成できます。適切な設計とは、すべての行のコピーを永久に保存することではありません。目的は、信頼でき、範囲が適切で保護された記録によって、運用や統制に関する問いに答えることです。

テーブルやライブラリを選ぶ前に、履歴がどのような判断を支える必要があるかを明確にしましょう。誤った変更の調査、顧客への操作説明、自動処理の検知は、それぞれ異なるニーズです。何を記録するか、誰が参照できるか、どのくらいの期間保持するかは、そのニーズによって決まります。

監査、技術ログ、ユーザー向け履歴は別物

監査、技術ログ、ユーザー向け履歴は別物 — guía visual de DedicatedPHP

技術ログは、エラー、リクエスト、レイテンシ、依存関係の障害など、アプリケーションの実行状況を記録します。システムの診断には役立ちますが、短期間でローテーションされることがあり、操作と影響を受けた業務オブジェクトが構造化された形で関連付けられているとは限りません。

一方、ユーザー向けの履歴には通常、「住所を更新しました」のように、理解しやすい操作の一部が表示されます。内部の詳細が省かれることがあり、インシデント調査に十分な記録とは限りません。変更監査では、機微な操作として定義された操作について、実行者を特定し、確実に再構成できることを優先します。

これらの仕組みは併用できますが、混同してはいけません。監査イベントは、ログの一行が残っていることに依存すべきではありません。また、運用やサポートのために保存したすべてのメタデータを、エンドユーザーに自動的に公開してはいけません。

追跡が必要な操作を決める

重要なエンティティと具体的なリスクを洗い出すことから始めます。たとえば、権限、請求データ、注文の状態、アカウント情報の変更を記録する必要があるアプリケーションがあります。対象の選定では、「このデータが変わったとき、説明や調査が必要になるのはどのような場合か」という実務上の問いに答えましょう。

作成、変更、削除、承認、取り消し、状態変更など、対象となる操作を定義します。多くの場合、技術的な書き込みをすべて記録するより、意味のある状態遷移を記録する方が有用です。表示用フィールドの更新と、アカウントの所有者変更では、必要な詳細度が異なることがあります。

各ケースについて、目的、対象フィールド、想定される実行者、参照を許可する人、予定する保持期間を文書化します。行全体を無差別に取得することは避けましょう。個人データや秘密情報を重複して保存するおそれがあり、アクセスや削除に関するポリシーへの準拠も難しくなります。値の比較が必要な場合は、正当化できるフィールドに記録を限定します。

実行者、操作、コンテキストを含む記録を設計する

有用な記録には通常、固有のID、対象オブジェクトの種別とID、操作、日時、実行者を含めます。日時の意味を解釈できるよう、操作の開始時点か変更の確定時点かを定義します。日時は通常UTCなど、共通の規約で記録します。データベースまたはアプリケーションの時計など、一貫した時刻ソースを使い、利用可能な運用上の仕組みでサーバー間の時刻を同期してください。明示せずに時刻ソースやタイムゾーンを混在させてはいけません。

実行者は、個人、サービスアカウント、自動処理のいずれでもかまいません。責任を持つプロセスを管理された形で特定できるなら、「システム」のような曖昧な値は使わないでください。コンテキストには、リクエストIDや相関ID、発生元のチャネル、必要に応じてユーザーが提示した理由を含められます。必要な情報だけを記録してください。IPアドレス、ユーザーエージェントなどのメタデータは、機微な情報である場合や、プライバシー上の影響を伴う場合があります。

変更された値については、変更前後のフィールドを範囲を限定して保存するか、値が不要なら変更されたフィールド名の一覧を保存します。認証情報、トークン、秘密情報は除外してください。オブジェクトへの参照があれば履歴から移動できますが、対象オブジェクトが存在し続ける保証にはなりません。予定している調査に十分なコンテキストを記録に残す必要があります。

実行者とイベントの関係では、単にリクエストで認証されていたユーザーではなく、誰が操作を開始したかを表す必要があります。管理者が他者に代わって操作する場合は、開始者と影響を受ける対象者を区別し、その委任が関連性と許可要件を満たす場合にのみ記録します。

イベント、監査テーブル、個別履歴を選ぶ

オブジェクト、実行者、操作、期間を指定して直接検索する必要がある場合、リレーショナルな監査テーブルが適していることがよくあります。調査しやすいシンプルなモデルを提供し、既存アプリケーションのニーズに合わせられます。想定する検索に必要なインデックスを定義し、すべてのフィールドを無差別にインデックス化することは避けてください。

ドメインイベントは、承認やキャンセルなど、業務上重要な事実を表します。事実が明確で、その意味が保持される場合、後続処理と監査の両方に利用できます。ただし、データベースへのすべての書き込みがドメインイベントになるわけではありません。また、イベントを使うことがイベントソーシングを意味するとも限りません。これは異なるアーキテクチャ上の判断です。

検索やルールがエンティティごとに異なるなら、個別の履歴の方がシンプルな場合があります。その反面、複数の実装が分岐し、記録漏れが生じる可能性があります。決定する前に、データ量、検索方法、スキーマの変化、書き込み箇所の数を評価しましょう。高度な形式を採用しても、実行者の特定が不完全なら補えません。

業務操作との整合性を確保する

変更とその記録を一つの操作として扱う必要がある場合は、同じトランザクション内で両方を永続化します。これにより、監査記録なしで変更が確定したり、ロールバックされた変更を表すイベントが保存されたりするのを防げます。データベースが実際に提供する保証と、各書き込みのエラーをアプリケーションがどう処理するかを確認してください。

操作をキューや外部サービスにも送る必要がある場合、データベースのトランザクションだけではそのシステムをカバーできません。トランザクショナルアウトボックスなどのパターンが役立ちます。変更と未送信メッセージをまとめて保存し、後続のプロセスが配信します。重複や欠落を防ぐため、再試行と冪等性を管理する必要があります。

定期タスク、インポート、コマンド、連携など、インターフェースを介さない変更にも同じ注意が必要です。共通の記録方法と、明示的なサービスIDを定義してください。アプリケーション外からの直接書き込みがある場合は、禁止するのか、統制するのか、別の層で監査するのかを決めます。PHPコードが自動的に実行者を特定できると想定してはいけません。

アクセスを制御し、安全に検索できるようにする

履歴は機微な情報として扱います。書き込みと参照の権限を分離し、最小権限を適用します。リスクに応じて、サポート担当者によるアクセスも記録してください。通常のアプリケーションが、制御なしに履歴を変更・削除できないようにします。データベース管理者が誰か、特権による変更を検知できる仕組みがあるかも検討してください。

目的、適用される義務、運用上のニーズに応じて保持期間を定めます。必要に応じて記録をアーカイブまたは削除する、検証可能なプロセスを定義してください。不要になったデータを無期限に保持する口実として、監査を利用してはいけません。

検索では、結果をページ分割し、オブジェクト、実行者、操作、日時で絞り込みます。画面には、順序を理解するために必要な情報を、適切な権限と分かりやすい形式で優先して表示します。画面、エクスポート、APIレスポンスに機微な値を完全な形で含めないでください。検索パラメーターを悪用して、権限のない他者のオブジェクトにアクセスされないよう保護します。

完全性を検証し、記録漏れを検知する

完全性を検証し、記録漏れを検知する — guía visual de DedicatedPHP

テストでは、行の存在だけでなく、想定される各操作について、正しい実行者、オブジェクト、関連フィールド、有効な日時が記録されることを確認します。業務データの書き込みと監査記録の間で発生する障害に加え、トランザクションのロールバックや再試行もシミュレートしてください。

ユーザー操作、サービスアカウント、インポート、定期処理のテストも含めます。除外対象のデータが記録に現れないこと、権限のないユーザーが他者の履歴を参照できないことを検証してください。トランザクションの挙動はデータベースとアプリケーションの利用方法に左右されるため、統合テストが重要です。

定期的な運用チェックは、テストでは見つからない漏れの発見に役立ちます。監査対象となるべき操作の一覧と、定めたサンプルまたは期間内に実際に記録された操作を比較します。イベントのない機微な操作、実行者やオブジェクトが欠けた記録、日時の欠落や順序の乱れ、確定した変更と記録イベントの不一致を探してください。傾向を把握できるだけのデータがあれば、イベント数の予期しない減少や異常な増加も確認します。

監査記録の書き込み失敗、必須フィールドの空欄、非同期処理の配信遅延、チェックで検出された不一致など、対応につながる兆候にアラートを設定します。担当者と調査手順を定めてください。追跡されないアラートでは、記録漏れは解消されません。イベント数の変化を自動的にインシデントとみなさず、想定される稼働状況やタスクのスケジュールと照らし合わせます。

既存アプリケーションに追跡機能を導入する場合は、まずリスクの高いエンティティと操作を洗い出します。共通形式を実装し、特定した書き込み箇所をカバーしたうえで、対象範囲を広げる前に検索、権限、定期チェックを追加してください。管理された環境で記録サンプルを確認します。具体的な問いに一貫して答えられるとき、監査は役立ちます。誰も解釈できないデータを蓄積するだけでは不十分です。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る