Microsoft Sentinelで「後からログを検索すると対象イベントが見つかるのに、スケジュール分析ルールのアラートが出ていない」という場合、原因の一つとしてログの取り込み遅延が考えられます。
イベントの発生時刻を表すTimeGeneratedと、Microsoft Sentinelで検索可能になった時刻に差があると、最初のルール実行時にはログが未着で、次の実行時には検索対象期間から外れてしまうことがあります。
対策は、検索対象期間をむやみに延ばすことではありません。まずingestion_time()とTimeGeneratedの差から実際の遅延を測定し、その結果に合わせて検索期間を広げます。そのうえで、検索期間の重複によって同じイベントが複数回検知されないように、取り込み時刻による絞り込みも追加します。([Microsoft Learn][1])
Sentinelにログはあるのに検知されない仕組み
スケジュール分析ルールでは、一定間隔でKQLクエリを実行し、指定された検索対象期間に含まれるログを評価します。
たとえば、次のルールを考えます。
| 設定項目 | 設定値 |
|---|---|
| 実行間隔 | 5分 |
| 検索対象期間 | 過去5分 |
| ログの取り込み遅延 | 2分 |
このとき、イベントが次の時系列で処理されると、アラートが出ない可能性があります。
| 時刻 | 状態 |
|---|---|
| 10:04:30 | 対象イベントが発生し、TimeGeneratedに10:04:30が記録される |
| 10:05:00 | ルールが実行されるが、ログはまだSentinelに到着していない |
| 10:06:30 | ログがSentinelに取り込まれ、検索可能になる |
| 10:10:00 | 次のルールが実行されるが、検索対象はおおむね10:05以降となる |
| 10:10以降 | 手動検索で期間を広く指定すると、10:04:30のログが見つかる |
最初の実行時にはログが未着です。次の実行時にはログが存在しますが、TimeGeneratedが検索対象期間より前であるため、検知対象から外れます。
手動検索では1時間や24時間などの広い期間を指定することが多いため、後から見ると「ログがあるのに、なぜアラートが出なかったのか」という状態になります。
Microsoft Sentinelのスケジュール分析ルールでは、TimeGeneratedが検索対象期間の基準として使われます。クエリの結果からTimeGeneratedを削除している場合や、集計後に適切なTimeGeneratedを返していない場合にも注意が必要です。([Microsoft Learn][2])
取り込み遅延と決めつける前に確認すること
アラートが出ない原因は、取り込み遅延だけではありません。次の順番で切り分けると、不要なルール変更を防げます。
| 確認項目 | 確認する内容 |
|---|---|
| ルールの状態 | 対象のスケジュール分析ルールが有効になっているか |
| 実行間隔 | Run query everyが何分に設定されているか |
| 検索対象期間 | Lookup data from the lastが何分に設定されているか |
| クエリ結果 | 対象時刻を指定したKQLで本当に条件に一致するか |
TimeGenerated | クエリ結果にTimeGeneratedが残っているか |
| しきい値 | クエリ結果数がアラート生成条件を満たしているか |
| 抑制設定 | アラート生成後の一時停止が有効になっていないか |
| イベントのグループ化 | アラートが既存インシデントにまとめられていないか |
| コネクタの状態 | データコネクタで停止や取得失敗が発生していないか |
| 取り込み遅延 | ingestion_time()とTimeGeneratedに差があるか |
スケジュール分析ルールでは、検索対象期間を実行間隔以上にする必要があります。たとえば5分間隔で実行するルールに、3分の検索対象期間を設定することはできません。([Microsoft Learn][2])
ログそのものが途切れている場合は、分析ルールより先にデータコネクタの状態を確認します。Microsoft Sentinelには、データ収集状態を確認するワークブックや、対応コネクタの正常性情報を保存するSentinelHealthテーブルがあります。([Microsoft Learn][3])
実行間隔と検索対象期間を確認する
最初に、対象ルールから次の値を記録します。
- ルールの実行間隔
- 検索対象期間
- 対象テーブル名
- 検知されなかったイベントの
TimeGenerated - 後から検索した時刻
- イベントを一意に識別できるIDや識別情報
たとえば、次のように整理します。
| 項目 | 確認例 |
|---|---|
| 対象テーブル | CommonSecurityLog |
| 実行間隔 | 5分 |
| 検索対象期間 | 5分 |
対象イベントのTimeGenerated | 10:04:30 |
| 検索可能になった時刻 | 10:06:30 |
| 推定遅延 | 2分 |
ここで重要なのは、ポータルで後から見つけた時刻ではなく、イベントがいつ検索可能になったかを確認することです。
それを調べるためにingestion_time()を使用します。
ingestion_time()で取り込み遅延を測定する
TimeGeneratedは、原則としてログが生成された時刻を表します。一方、ingestion_time()は、そのレコードがワークスペースに保存され、クエリで利用できるようになった時刻の確認に使用できます。
両者の差を計算すると、イベント発生から検索可能になるまでの遅延を見積もれます。([Microsoft Learn][4])
個々のログの遅延を確認するKQL
次の例ではCommonSecurityLogを使用しています。実際には、分析ルールが参照しているテーブル名へ置き換えてください。
let measurement_period = 24h;
CommonSecurityLog
| where TimeGenerated >= ago(measurement_period)
| extend IngestionTime = ingestion_time()
| where isnotnull(IngestionTime)
| extend IngestionDelay = IngestionTime - TimeGenerated
| project-reorder TimeGenerated, IngestionTime, IngestionDelay
| order by IngestionDelay desc
結果では、主に次の列を確認します。
| 列 | 意味 |
|---|---|
TimeGenerated | イベントの発生時刻 |
IngestionTime | Sentinelで検索可能になった時刻 |
IngestionDelay | 取り込みまでにかかった時間 |
説明用の例として、次のような結果が得られたとします。
| TimeGenerated | IngestionTime | IngestionDelay |
|---|---|---|
| 10:04:30 | 10:06:30 | 00:02:00 |
| 10:12:10 | 10:12:45 | 00:00:35 |
| 10:18:00 | 10:22:20 | 00:04:20 |
この場合、遅延は常に2分ではありません。通常は数十秒でも、一部のログで4分以上遅れる可能性があります。
遅延の傾向を集計するKQL
数件だけを見ると、一時的な遅延を見落とします。一定期間の中央値、95パーセンタイル、99パーセンタイル、最大値を確認すると、ルール設計に使いやすくなります。
let measurement_period = 7d;
CommonSecurityLog
| where TimeGenerated >= ago(measurement_period)
| extend IngestionTime = ingestion_time()
| where isnotnull(IngestionTime)
| extend IngestionDelay = IngestionTime - TimeGenerated
| summarize
Records = count(),
P50 = percentile(IngestionDelay, 50),
P95 = percentile(IngestionDelay, 95),
P99 = percentile(IngestionDelay, 99),
Maximum = max(IngestionDelay)
by bin(TimeGenerated, 1h)
| order by TimeGenerated asc
Microsoftの資料でも、一般的な遅延傾向にはパーセンタイルを使い、短時間の急激な遅延を確認するときは最大値が有効とされています。([Microsoft Learn][4])
実務では、次のように判断します。
| 指標 | 主な用途 |
|---|---|
| P50 | 通常時の代表的な遅延を把握する |
| P95 | 多くのログを取りこぼさない設定を検討する |
| P99 | 重要度が高く、見逃しをさらに減らしたいルールで参考にする |
| 最大値 | 障害や一時的な遅延スパイクを調べる |
最大値が極端に大きいからといって、すべてのルールの検索対象期間をその値まで広げるとは限りません。検索負荷や重複検知とのバランスを考える必要があります。
また、同じテーブルに複数製品や複数拠点からログが入る場合は、ベンダー、製品、デバイス、コネクタなどの列で分けて集計します。複数テーブルを結合するルールでは、テーブルごとに遅延を調べてください。データソースによって取り込み遅延が異なるためです。([Microsoft Learn][1])
実測値に合わせて検索対象期間を広げる
遅延が確認できたら、元の検索対象期間に遅延分を加えます。
Microsoftの資料では、次の例が示されています。
| 項目 | 値 |
|---|---|
| 実行間隔 | 5分 |
| 元の検索対象期間 | 5分 |
| 取り込み遅延 | 2分 |
| 調整後の検索対象期間 | 7分 |
計算式は次のとおりです。
調整後の検索対象期間
= 元の検索対象期間
+ 考慮する取り込み遅延
ただし、5分間隔なら必ず7分にすればよいわけではありません。2分という値は公式資料の説明例であり、すべての環境に共通する遅延ではないためです。自組織の対象テーブルとデータソースで測定した値を使用してください。([Microsoft Learn][1])
たとえば、実測結果が次のようになったとします。
| 指標 | 遅延 |
|---|---|
| P50 | 25秒 |
| P95 | 1分40秒 |
| P99 | 3分10秒 |
| 最大値 | 18分 |
この場合、どの値を採用するかはルールの重要度によって変わります。
- 情報提供を目的とした低重要度ルールでは、P95を基準にする
- 認証攻撃など見逃しを抑えたいルールでは、P99を基準にする
- 最大18分の原因が一時障害なら、検索窓を18分広げる前にコネクタやネットワークを調査する
これは固定ルールではありません。検索対象期間を広げたときのクエリ負荷、アラート件数、重複の有無を含めて決定します。
検索期間を広げるだけでは重複検知が発生する
5分間隔のルールで検索対象期間を7分にすると、前回と今回の検索範囲が2分間重複します。
前回の検索範囲:09:58~10:05
今回の検索範囲:10:03~10:10
重複する範囲 :10:03~10:05
10:04に発生し、遅延なく取り込まれたイベントは、前回と今回の両方の検索範囲に入る可能性があります。その結果、同じイベントからアラートが2回生成されることがあります。
Microsoftの資料では、広げたTimeGeneratedの検索範囲に加えて、ingestion_time()で直近の取り込み分だけを対象にする方法が示されています。([Microsoft Learn][1])
let ingestion_delay = 2min;
let rule_look_back = 5min;
CommonSecurityLog
| where TimeGenerated >= ago(ingestion_delay + rule_look_back)
| where ingestion_time() > ago(rule_look_back)
このクエリでは、2種類の時間条件を組み合わせています。
| 条件 | 目的 |
|---|---|
TimeGenerated >= ago(7m) | 2分遅れて到着したイベントも検索対象に含める |
ingestion_time() > ago(5m) | 直近5分間に新しく取り込まれたレコードだけを評価する |
これにより、イベント発生時刻が古くても、今回の実行周期で新たに取り込まれたログを検知できます。一方、前回の実行時にすでに取り込まれていたイベントは除外されるため、検索期間の重複による二重検知を抑えられます。
公式例をそのままコピーしない
このクエリ例は、元の検索対象期間と実行間隔がどちらも5分である単純なケースです。
次のようなルールでは、同じ書き方をそのまま適用できない場合があります。
- 5分ごとに実行し、過去30分間の件数を集計するルール
- 複数テーブルを結合するルール
- 一定時間内の複数イベントを相関させるルール
- 同一ユーザーの連続失敗回数を数えるルール
- ベースラインや履歴データと比較するルール
たとえば過去30分間の失敗回数を集計するルールに、直近5分の取り込みデータだけを残す条件を追加すると、本来必要な30分間の集計対象まで減らしてしまう可能性があります。
集計ルールでは、次の役割を分けて設計します。
- 検知判断に必要なイベント期間
- 今回の実行で新たに評価する対象
- 重複アラートを防ぐためのイベント識別方法
必要に応じて、送信元が付与したイベントIDや、ユーザー、端末、イベント種別、発生時刻などを組み合わせ、同一イベントを識別します。
変更後は取りこぼしと重複を同時に試験する
検索対象期間を広げたら、「以前見逃していたイベントが検知されるようになった」だけで完了にしてはいけません。
次のケースを確認します。
| 試験ケース | 期待結果 |
|---|---|
| 遅延なしで到着したイベント | 1回だけ検知される |
| 想定範囲内で遅延したイベント | 次回実行で検知される |
| 検索窓の境界付近で発生したイベント | 取りこぼされず、重複もしない |
| 同じイベントが複数の検索窓に含まれる | アラートは1回だけ生成される |
| 送信元が同じイベントを再送した | ルールの設計に応じて適切に重複排除される |
| しきい値の直前・直後となる件数 | 想定した条件でのみアラートが生成される |
| 複数テーブルの片方だけが遅延した | 結合条件による欠落が発生しない |
比較するときは、単純なクエリ結果件数だけでなく、イベントを識別できる値を確認します。
たとえば、次の情報です。
- 送信元のイベントID
- デバイス名
- ユーザー名
- 接続元IPアドレス
- イベント種別
TimeGeneratedingestion_time()
アラートのイベントグループ化やインシデントのグループ化も確認してください。アラートが生成されていても、既存インシデントに追加されたため、新しいインシデントが増えていないように見える場合があります。([Microsoft Learn][2])
取り込み遅延以外を疑うべきケース
次の状況では、検索対象期間を延ばす前に別の原因を調べます。
広い期間で検索してもログが存在しない
データコネクタ、エージェント、ネットワーク、送信元システムなどの問題が考えられます。
ルールの検索窓を広げても、到着していないログは検知できません。
対象時刻のログはあるが、KQLの結果に出ない
解析クエリの条件を確認します。
特に注意したいのは次の項目です。
where条件が厳しすぎる- 文字列の大文字・小文字や表記が想定と異なる
joinの結合キーが一致していないsummarize後に必要なイベントが集約されている- 数値や時刻の型変換に失敗している
- 除外リストやウォッチリストで対象が除外されている
手動クエリでは結果があるが、アラート条件を満たしていない
クエリ結果が1件あっても、アラートのしきい値が「100件を超えた場合」ならアラートは生成されません。
イベントグループ化、アラート抑制、実行停止設定も併せて確認します。
TimeGeneratedの値が不自然
TimeGeneratedが送信元の時計や解析処理によって設定されている場合、実際の発生時刻とずれることがあります。
取り込み遅延が負の値になっている場合や、数時間から数日単位の不自然な値が出る場合は、ネットワーク遅延だけでなく、送信元の時刻同期やTimeGeneratedの割り当て方法を確認してください。
対象は既存のスケジュール分析ルール
ここで説明した方法は、既存のMicrosoft Sentinelスケジュール分析ルールにおける取り込み遅延対策です。
次の検知方式へ同じ設定をそのまま適用しないでください。
- Near-real-time detection rules
- Microsoft Defender XDRのカスタム検出
- 製品側でリアルタイム処理される検知
- ストリーミングやイベント駆動型の処理
Microsoftの資料では、スケジュール分析ルールの遅延対策とは別の選択肢としてNRTルールが案内されています。また、新しいルールについては、Microsoft Defender XDRと統合されたカスタム検出も案内されています。既存ルールの修正と、新しい検知方式の設計は分けて判断する必要があります。([Microsoft Learn][1])
まず実施するべき対応
後からログが見つかるのにアラートが出ない場合は、次の順番で確認します。
- 対象ルールの実行間隔と検索対象期間を記録する
- 検知されなかったログの
TimeGeneratedを確認する ingestion_time()との差を計算する- 数日分のP95、P99、最大遅延を確認する
- 実測した遅延に合わせて検索対象期間を調整する
ingestion_time()などを使って重複検知を防ぐ- 遅延イベント、通常イベント、境界イベントで試験する
- アラート件数だけでなく、同一イベントが二重検知されていないか確認する
重要なのは、公式例の「5分+2分=7分」をそのまま設定することではありません。
自組織のログで遅延を測定し、検索対象期間の拡張と重複防止を一組で設計することが、取りこぼしと二重アラートの両方を防ぐ基本となります。
[1]: https://learn.microsoft.com/en-us/azure/sentinel/ingestion-delay “Handle Ingestion Delay in Microsoft Sentinel | Microsoft Learn”
[2]: https://learn.microsoft.com/en-us/azure/sentinel/create-analytics-rules “Create scheduled analytics rules in Microsoft Sentinel | Microsoft Learn”
[3]: https://learn.microsoft.com/en-us/azure/sentinel/monitor-data-connector-health “Monitor the health of your Microsoft Sentinel data connectors | Microsoft Learn”
[4]: https://learn.microsoft.com/en-us/azure/azure-monitor/logs/data-ingestion-time “Log data ingestion time in Azure Monitor – Azure Monitor | Microsoft Learn”

コメント