Microsoft SentinelでUEBA(User and Entity Behavior Analytics)っぽいユーザー行動分析を自前で組もうとすると、多くの人がSigninLogsやSecurityEventのような生テーブル(raw table)に直接クエリを投げるところから始めます。動くには動くのですが、この「生テーブルに直接依存する」設計が、実運用に乗せた途端にじわじわ効いてくる問題の元になります。
一番の理由はシンプルで、認証イベントはシステムごとに送り先のテーブルが違うからです。Entra IDのサインインはSigninLogs、オンプレADのイベントログはSecurityEvent、他のIdPやVPN機器はまた別のカスタムログテーブル――という具合に、同じ「ログイン」という行為でも、どのシステム経由かによって全然違うテーブルに入ってきます。SIEM+のSentinel統合で、ほとんどのケースでASIM(Advanced Security Information Model)を使っているのは、まさにこの「テーブルがシステムごとにバラバラ」という問題を、統合・正規化されたスキーマで一本化するためです。
具体的には、こんな問題が出てきます。
- データソースが増えるたびにテーブルが分岐する
- そして地味に厄介なのが結果上限
- コネクタ障害やログ転送遅延の影響をそのまま受ける
テナント全体のユーザーを母集団にして集計をかけると、Advanced Huntingのポータル実行では30,000件、APIでも最大100,000件という上限にすぐ届いてしまい、途中で結果が切り捨てられます。厄介なのは、切り捨てられていること自体に気づきにくい点です。「異常なユーザーがいない」という結果を見て安心してしまっても、それが検知ロジックの精度ではなく、単なる結果上限によるデータ欠損だったというケースは珍しくありません。
この記事では、生テーブル直接依存がどういう場面で足を引っ張るのかを具体的に見た上で、SIEM+がその対策としてimAuthenticationをどう使っているかを説明します。「APIをつないでデータを取得しました」で終わる連携紹介ではなく、実運用で必ず突き当たる課題への向き合い方が主眼です。
生テーブルに直接依存する設計の課題
典型的な失敗パターンは、以下のようなクエリです。
SigninLogs
| where TimeGenerated > ago(30d)
| summarize LoginCount = count() by UserPrincipalName, IPAddress
一見シンプルですが、SigninLogsという特定の生テーブルに直接依存しているせいで、実運用では以下の問題が出てきます。
1. データソースが増えるたびにテーブルが分岐する
これが一番厄介な部分です。認証イベントは、どのシステムが発行したかによって、送り先のテーブルがバラバラになります。
- Entra ID(旧Azure AD)のクラウド側サインイン →
SigninLogs - オンプレミスADのWindowsイベントログ(Event ID 4624/4625) →
SecurityEvent - サードパーティのIdPやVPN機器の認証ログ → コネクタごとのカスタムログテーブル(
CommonSecurityLogなど)
つまり「ユーザーの認証イベント」という1つの概念が、システム構成次第で複数のテーブルに散らばります。ハイブリッドID環境(オンプレAD + Entra ID)や、複数のIdP・VPN機器が混在する環境では、これが即座に問題になります。ユーザーの行動を正しく捉えるには、これら全部のテーブルを個別にクエリして、後から手動で突き合わせる羽目になるからです。しかもテーブルごとにスキーマが違うので、UserPrincipalNameとTargetUserNameのようにフィールド名すら揃っていません。1つのシステムだけを見ているうちは気づきませんが、統合先が増えるたびに「どのテーブルに何のフィールド名で入っているか」を個別に把握して書き分ける必要が出てきます。
2. 生ログの件数がそのまま結果上限に直結する
SigninLogsに直接依存していると、結果件数は「認証イベントの発生数」に比例します。30日分のサインインログをテナント全体のユーザー母集団に対して集計しようとすると、中堅〜大企業規模の環境ではあっさり数十万行を超えてきます。Advanced Huntingのポータル実行では30,000件、APIでも100,000件が上限で、これを超えると結果は切り捨てられます。
明示的にエラーが返るならまだいいのですが、厄介なのはsummarize後の集計結果として一部のユーザーだけが欠けた状態で返ってくるパターンです。クエリ自体は正常終了して見えるので、分析者は結果が欠けていることに気づけません。「異常な行動をしたユーザーはいませんでした」という結果の裏で、実は「結果上限に収まらなかったユーザーが単に除外されていただけ」というオチは、意外とありがちです。突き詰めると、これは結果上限そのものが悪いわけではなく、生テーブル(=イベント単位の粒度)に直接依存しているせいで、集計の母集団が「ユーザー」ではなく「イベント」のまま扱われてしまっていることが根本原因です。
3. コネクタ障害・遅延の影響をそのまま受ける
生テーブルは接続元コネクタの仕様にそのまま依存するため、コネクタの一時的な障害やログ転送遅延で特定期間のデータが欠けることがあります。生テーブルを直接参照する設計だと、この欠損を検知・補正するロジックをテーブルごとに個別に持つ必要があり、統合先が増えるほどメンテナンスコストが積み上がっていきます。
ASIM Authenticationを母集団にして生テーブル依存を切り離す
これらの課題に共通する原因は「認証イベントがシステムごとに別々の生テーブルに入ってくること」です。SIEM+のSentinel統合では、ASIMのimAuthentication正規化スキーマをユーザー母集団の基盤に据えることで、この分岐そのものを設計から切り離しています。
imAuthentication
| where TimeGenerated > ago(30d)
| where EventType == "Logon"
| summarize LoginCount = count(), DistinctIPs = dcount(SrcIpAddr) by TargetUsername
ASIMは、Entra IDのサインインログ、オンプレミスAD、その他対応済みの認証ソースをTargetUsername・SrcIpAddr・EventResultといった共通スキーマにマッピングしてくれるパーサー層です。これを間に挟むことで、次のようなメリットが出てきます。
データソースの差異を吸収し、スキーマを一本化する
さっき挙げた「Entra IDはSigninLogs、オンプレADはSecurityEvent、他のIdPはカスタムログテーブル」という分岐が、ASIMを挟んだ瞬間になくなります。imAuthenticationを参照するクエリは、背後のログソースがEntra IDなのかオンプレADなのかを一切気にする必要がありません。顧客ごとに認証基盤の組み合わせがバラバラでも、同じクエリでそのまま動きます。複数顧客・複数環境に同一の検知ロジックを横展開するSIEM+のような製品にとって、これは保守性の面でかなり効いてきます。
集計を早い段階で行い、結果件数を抑える
ASIMベースの設計では、ユーザー単位・IPアドレス単位でsummarizeによる事前集計をかけてから結果を取り出すのを基本にしています。生ログを1件ずつ返すのではなく、ユーザーごとに集約した行だけを返すので、結果行数の上限にかかってくるのは「認証イベントの件数」ではなく「テナント全体のユーザー数」になります。数万ユーザー規模の組織でも、集計後の行数はユーザー数を大きく超えないので、30,000件・100,000件の上限に対して安全マージンを確保しやすくなります。
スキーマ変更への耐性
Microsoft側がSigninLogsのスキーマにフィールドを追加・変更しても、ASIMパーサーがそれを吸収してくれるので、正規化スキーマ側には影響が出ません。生テーブルを直接参照していると、Microsoft側のスキーマ変更のたびに自社クエリを見直す羽目になりますが、ASIMを間に挟むことでこの追従コストを構造的に下げられます。
まとめ
| 項目 | 生テーブル直接依存 | ASIM(imAuthentication)ベース |
|---|---|---|
| データソースへの依存 | 特定の生テーブルにロジックが縛られる | データソースの差異をパーサー層が吸収 |
| 複数認証ソースの統合 | テーブルごとに個別クエリが必要 | 単一スキーマで統合済み |
| 結果上限への耐性 | 生ログ行数がそのまま上限にかかりやすい | 事前集計によりユーザー数ベースに圧縮 |
| スキーマ変更への耐性 | Microsoft側の変更に追従が必要 | パーサー層が吸収 |
| 複数顧客環境への横展開 | 環境ごとにロジック調整が必要 | 同一ロジックを共通適用しやすい |
SIEM+がSentinel統合の大部分でASIMを設計の基盤に置いているのは、「新しい正規化スキーマだから」という理由だけではなく、特定の生テーブルへの依存を切り離すことで、結果上限・データソースの多様性・欠損データといった、実運用で必ずぶつかる課題を構造ごと解消できるからです。結果上限は、あくまで生テーブル依存が引き起こす症状のひとつに過ぎません。
Sentinelでユーザー行動分析やUEBA的なロジックを自前で組もうとしている方は、対象を生テーブルのままにするか、ASIMのような正規化レイヤーを経由して生テーブル依存を最初から切り離すかを、設計の初期段階で決めておくことをお勧めします。後から生テーブルベースの実装をASIMに移行するのは、地味に手間がかかります。
質問やツッコミがあれば、コメントで教えてください。