Microsoft Purviewの監査ログとAPIアクセス記録の完全ガイド|Unified Audit Log・Log Analytics・Private Endpoint対応

Microsoft Purview へのアクセスや Data Map API 呼び出しを「誰が・いつ・どこから・何をしたか」まで追跡できると、事故対応とコンプライアンスは一気に楽になります。本記事では、Purview 監査(Unified Audit Log)と Azure Monitor(診断ログ)を組み合わせ、ポータル・API・ネットワークの各層で確実に記録を残し、プログラムから検索・取得・可視化するための実践手順とサンプルを余すことなくまとめます。

目次

Purview の監査とログがカバーする範囲をまず整理

Microsoft Purview の「誰が・どこから・何をしたか」を可観測化するには、主に次の 3 レイヤーを使います。

  • Microsoft 365 統合監査ログ(Unified Audit Log; UAL):Purview Studio で行われた操作や Data Map API に対する論理操作(例えば検索、アセットの閲覧、用語集操作など)を記録。ユーザー/アプリ、操作名、時刻、クライアント IP、対象オブジェクトなどが入ります。
  • Azure Monitor(診断設定/リソース ログ):Purview アカウントが受けたデータプレーン要求の事実(HTTP メソッド、URI、ステータス、処理時間、呼び出し元 IP など)を記録。Log Analytics / Event Hub / Storage に送信可能。
  • Azure AD(Entra ID)サインイン/ディレクトリ監査:誰がどこから認証したかの証跡。Purview そのものの操作ログとは別ですが、IP やデバイス情報と照合する際に有用。
目的推奨するログ/機能主なフィールド長所補足
「誰が」「どの操作」を行ったかMicrosoft 365 統合監査ログ(Purview のレコード種別)CreationDate, UserId, Operation, Workload, ObjectId, ClientIP, UserAgent, ResultStatusコンプライアンス用途に適合、検索 UI と PowerShell/API 両対応保持はライセンスと保持ポリシーに依存
HTTP レベルでの API 呼び出し状況Purview の診断ログ(例:アカウント/データプレーン要求カテゴリ)TimeGenerated, OperationName, RequestUri, HttpStatusCode, DurationMs, CallerIpAddress, Identity遅延や 4xx/5xx の可視化が容易、SIEM 連携しやすいAzure Monitor 側の保持/コスト設計が必要
発信元ネットワークの特定Entra ID サインインログ(Graph / ポータル)UserId, AppId, IPAddress, ConditionalAccessStatus, DeviceDetail異常な場所/デバイス検知に有効Purview 操作ログと時刻・ユーザーで照合

最短で「監査できる状態」にする 6 ステップ

手順具体的な操作ポイント
1. 統合監査ログの取り込みを有効化Microsoft 365 管理センター/コンプライアンス ポータルから「監査」を有効化。PowerShell では次のコマンドで有効化できます。 # Exchange Online 管理モジュール(EXO V3)を使用 Connect-ExchangeOnline Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true Get-AdminAuditLogConfig | fl UnifiedAuditLogIngestionEnabled有効化後、取り込み開始まで数十分のラグが出ることがあります。
2. Purview 監査ソリューションを有効化Purview Studio にサインインし、ホームの「監査」カードまたは「すべてのソリューション > 監査」からセットアップを完了します。表示されない場合はロールとライセンスを確認。
3. API 呼び出しを捕捉するレコード種別を確認Purview の監査検索でレコード種別を Purview Data Map に関する操作(例:「PurviewDataMapOperation」等、テナントで表示される名称)に絞ると、検索/参照/用語集/スキャン構成などの操作が抽出できます。命名はテナント/地域/更新で変わることがあります。UI 上の表記を優先してください。
4. 診断ログの送信先を設計Purview アカウント > 診断設定 から、以下のカテゴリを Log Analytics / Event Hub / Storage に送信します。 アカウント操作/要求(例:PurviewAccountLogs) データプレーン要求(例:PurviewDataPlaneRequests)Log Analytics は即時分析、Event Hub は SIEM/ストリーム処理、Storage は長期保管に最適。
5. ログの検索・取得方法を用意ポータル:Purview Studio > 監査 PowerShell:Search-UnifiedAuditLog Office 365 Management Activity API:Audit.General を購読 Microsoft 365 Audit(Premium)Export API:継続エクスポート Log Analytics(KQL):リアルタイム分析・検知API 経由の取得は自動化しやすく、SIEM 連携の起点になります。
6. Private Endpoint 前段のリバースプロキシ/ロードバランサ指針を適用必須:Host ヘッダーと SNI は Private Link 側 FQDN を指すよう維持/再設定 推奨:X-Forwarded-For で元クライアント IP を継承 推奨:エンドツーエンド TLS(終端する場合は再暗号化し SNI を厳密指定)公式ガイドの構成例(Application Gateway + Private Link 等)の要点を下段のセクションで整理しています。

「誰が・どこから・何をしたか」を把握するための実用パターン

1) まずは Unified Audit Log(Purview 監査)で論理操作をつかむ

Purview Studio からの検索、データ アセットの表示、用語集(Glossary)の作成・更新、スキャンの開始/停止など、ユーザーやアプリがビジネス上どの操作を行ったかは UAL 側が最も見やすいです。PowerShell での基本は次の通り:

$start = (Get-Date).AddDays(-7)
$end   = Get-Date
$op    = @("PurviewDataMapOperation","PurviewCatalogOperation") # 表示される実際の名前を使用

$logs = Search-UnifiedAuditLog -StartDate $start -EndDate $end -Operations $op -ResultSize 5000
$logs |
Select-Object CreationDate, UserIds, Operation, ClientIP, UserAgent, Workload, ObjectId, ResultStatus |
Format-Table -Auto 

ポイント:UserIds は複数の識別子が入ることがあり、AuditData(JSON)に詳細なパラメータ(実行された API の種類やパス)が含まれます。必要に応じて次のように展開します。

$logs | ForEach-Object {
  $j = $_.AuditData | ConvertFrom-Json
  [PSCustomObject]@{
    Time        = $_.CreationDate
    User        = $_.UserIds
    Operation   = $_.Operation
    ClientIP    = $_.ClientIP
    ApiName     = $j.Operation
    Target      = $j.ObjectId
    Parameters  = ($j.Parameters | ConvertTo-Json -Compress)
    Result      = $j.ResultStatus
  }
} | Format-Table -Auto

2) Azure Monitor(診断ログ)で HTTP レベルの事実をつかむ

Unified Audit Log が「論理操作」を示すのに対し、診断ログは「HTTP リクエストの事実」を示します。たとえば Data Map API への /catalog/api/search/query や /glossary 呼び出しが どの URI に、どのメソッドで、どのステータスで返ったかが記録されます。Log Analytics での KQL 例を 2 つの取り込み方式(リソース固有テーブル/旧 AzureDiagnostics)に分けて示します。

// 新しい「リソース固有」スキーマ例(テーブル名は環境により異なる)
PurviewDataPlaneRequests_CL
| where TimeGenerated > ago(24h)
| project TimeGenerated, OperationName_s, httpMethod_s, RequestUri_s, HttpStatusCode_d,
          DurationMs_d, CallerIpAddress_s, Identity_s, CorrelationId_g
| order by TimeGenerated desc
// 旧 AzureDiagnostics 統合テーブルを使う場合の例
AzureDiagnostics
| where TimeGenerated > ago(24h)
| where ResourceProvider == "MICROSOFT.PURVIEW"
| project TimeGenerated, Category, OperationName, httpMethod_s=HttpMethod_s,
          RequestUri_s, statusCode_d=StatusCode_d, DurationMs_d=DurationMs,
          CallerIpAddress_s=CallerIpAddress, Identity

コツ:クライアント側で x-ms-client-request-id を付与すると、同 ID を診断ログとアプリ ログで突合でき、トラブル時の切り分けが一気に速くなります。

3) Graph のサインイン ログと照合して「どこから」を確定

Graph の /auditLogs/signIns ではユーザーやアプリのサインイン元 IP・デバイスが分かります。Purview の UAL レコードと ユーザー+時刻で突合すると、NAT/プロキシ配下でも「実ユーザー位置の推定」が精度向上します。

# Microsoft Graph PowerShell
Connect-MgGraph -Scopes "AuditLog.Read.All"
Select-MgProfile beta

$since = (Get-Date).AddHours(-24).ToString("o")
$signins = Invoke-MgGraphRequest -Method GET -Uri "/beta/auditLogs/signIns?`$filter=createdDateTime ge $since"

# UAL 側の Purview 操作(前述 $logs)と簡易突合(擬似例)

$join = foreach ($l in $logs) {
$s = $signins.value | Where-Object { $*.userPrincipalName -in $l.UserIds -and
([datetime]$*.createdDateTime) -ge (([datetime]$l.CreationDate).AddMinutes(-10)) -and
([datetime]$_.createdDateTime) -le (([datetime]$l.CreationDate).AddMinutes(10)) } |
Select-Object -First 1
[PSCustomObject]@{
Time      = $l.CreationDate
User      = ($l.UserIds -join ",")
Operation = $l.Operation
UAL_IP    = $l.ClientIP
SignIn_IP = $s.ipAddress
App       = $s.appDisplayName
Device    = $s.deviceDetail?.displayName
}
}
$join | Format-Table -Auto 

これにより「Purview で用語集を変更したのは社外 IP からのアクセスだった」といった異常検知が容易になります。

ログ保管・クエリ・自動化の設計(実装例付き)

Log Analytics を中心に据えた構成

  • Purview 診断ログは Log Analytics に送信し、KQL で分析・アラート。
  • Unified Audit Log は PowerShell(Search-UnifiedAuditLog)で取得し、週次/日次で Log Analytics のカスタム テーブルへ取り込み。
  • Entra ID サインインは Graph API で取得し、同じワークスペースで保持。
データ ソース取り込み手段宛先主な用途
Purview 診断ログ診断設定(Azure Monitor)Log AnalyticsAPI 失敗率、遅延、Top 呼び出し URI
Unified Audit Log(Purview)PowerShell / O365 Management Activity APILog Analytics(カスタム テーブル)論理操作の追跡、監査証跡
サインイン ログGraph Audit(signIns)Log Analytics発信元 IP・デバイスの特定、条件付きアクセス検証

Log Analytics(KQL)サンプル集

// 直近 1 日の API 失敗(5xx/429)トップ URI
PurviewDataPlaneRequests_CL
| where TimeGenerated > ago(1d)
| where HttpStatusCode_d >= 500 or HttpStatusCode_d == 429
| summarize count() by RequestUri_s, HttpStatusCode_d
| top 20 by count_ desc
// 組織外(許可サブネット外)からの Purview 操作(UAL 側)
let allow = dynamic(["203.0.113.0/24","198.51.100.0/24"]);
PurviewDataMapOperation_CL
| where TimeGenerated > ago(7d)
| extend IP = tostring(ClientIP_s)
| where not(ipv4_is_in_range(IP, allow[0]) or ipv4_is_in_range(IP, allow[1]))
| project TimeGenerated, UserId_s, OperationName_s, IP, ObjectId_s, ResultStatus_s
// 用語集(Glossary)に対する変更操作の抽出(UAL 側)
PurviewDataMapOperation_CL
| where TimeGenerated > ago(30d)
| where OperationName_s has_any ("Glossary","Term","Category")
| summarize count() by OperationName_s, UserId_s
| order by count_ desc
// API 応答遅延のパーセンタイル
PurviewDataPlaneRequests_CL
| where TimeGenerated > ago(7d)
| summarize p50=percentile(DurationMs_d,50), p95=percentile(DurationMs_d,95) by bin(TimeGenerated, 1h)
// UAL とサインイン ログの簡易ジョイン(ユーザー+時間窓)
PurviewDataMapOperation_CL
| where TimeGenerated > ago(1d)
| project UTime=TimeGenerated, UUser=UserId_s, UOp=OperationName_s, UIP=ClientIP_s
| join kind=leftouter (
  SignInLogs
  | where TimeGenerated > ago(1d)
  | project STime=TimeGenerated, SUser=UserPrincipalName, SIP=IPAddress, AppDisplayName
) on $left.UUser == $right.SUser and abs(datetime_diff("minute", UTime, STime)) <= 10
| project UTime, UUser, UOp, UIP, SIP, AppDisplayName

Office 365 Management Activity API(Audit.General)の基本フロー

  1. アプリ登録:適切な権限(例:ServiceHealth.Read は不要、監査には ActivityFeed.Read など)を付与。
  2. サブスクリプション開始:POST /api/v1.0/<tenant>/activity/feed/subscriptions/start?contentType=Audit.General
  3. 内容の一覧取得:GET /api/v1.0/<tenant>/activity/feed/subscriptions/content?contentType=Audit.General&startTime=...&endTime=...
  4. コンテンツのダウンロード:返却されたコンテンツ URI に対して GET。JSON 配列に各イベントが入っています。

返る JSON の Workload が「Microsoft Purview」に相当するイベント、Operation が「Data Map」関連の操作(検索・分類・用語集など)を選択して取り込みましょう。

Microsoft 365 Audit(Premium)の Export API

近リアルタイムで継続的に監査イベントを吐き出せます。SIEM への常時連携や長期保管の要件がある場合に最有力です。取り込み先は Event Hub/Storage/外部 SIEM(例:Microsoft Sentinel 以外)などに合わせて選択します。

API 呼び出し側で仕込むと捗るベストプラクティス

  • x-ms-client-request-id の明示設定(GUID):失敗時の突合を秒で終わらせる鍵。
  • 呼び出しごとに correlationId をアプリ ログ側にも記録。
  • Purview の api-version は更新されます。固定値の更新チェックを CI に組み込む(404/410 増加の早期検知)。
  • 429 対策の 指数バックオフ 実装と Retry-After 尊重。

Private Endpoint × リバースプロキシ/ロードバランサ設計の勘所

ネットワーク経路の前提

  • Purview のアカウント FQDN は <name>.purview.azure.com(Private Link 使用時はプライベート DNS ゾーンで解決)。
  • アプリケーション ゲートウェイや Nginx/Envoy を前段に置く場合、名前解決と SNI が Private Link の FQDN を指すことが肝要。

推奨アーキテクチャ パターン

パターンTLS利点注意点
パススルー(終端なし)クライアント →(SNI=PL FQDN)→ PE最も単純で透過、ヘッダー改変不要WAF 機能は使いにくい
終端+再暗号化クライアント → 逆プロキシ(終端)→ 再暗号化(SNI=PL FQDN)→ PEWAF/DLP/レスポンス圧縮などが可能Host ヘッダーと SNI を Private Link FQDN に揃えること。証明書と SNI ミスマッチに注意

HTTP ヘッダーの扱い

  • Host は <name>.purview.azure.com(Private Link FQDN)を維持。
  • X-Forwarded-For を付加して元クライアント IP を継承(Purview 側がすべてを解釈するわけではありませんが、自組織側の逆プロキシ/WAF ログでは完全追跡が可能)。
  • X-Forwarded-Proto / X-Forwarded-Host も付与しておくと再現テストが容易。

よくあるハマりポイント

  • 逆プロキシが SNI を外した/書き換えたため、Private Endpoint で TLS 失敗。
  • HTTP/2 の一部設定で中間機器がフレームを切り詰め、413/431 が増える(ヘッダー/フレームサイズの上限見直し)。
  • アイドル タイムアウトが短く、長時間検索や大量応答で 504 が出やすい(Application Gateway のバックエンド タイムアウトを十分に)。

検証チェックリスト

  • Private DNS ゾーン(例:privatelink.purview.azure.com)の A レコードが正しく解決されるか。
  • 逆引き/ヘルス プローブはインターネットに出ていないか(強制トンネルの誤設定回避)。
  • Proxy 経路でも x-ms-client-request-id が失われていないか。

運用に効く「アラート・レポート」雛形

アラート(KQL ベース)

  • 社内許可アドレス帯以外からの高感度操作(用語集更新、スキャン設定変更)
  • API 失敗率の急増(5xx/429 が 5 分間で閾値超え)
  • レイテンシ悪化(p95 > 2 秒が 10 分継続)
  • 大量検索(同一ユーザーの検索が 1 分間に 50 回超)

週次レポート(例)

メトリクス定義意義
ユニーク操作ユーザー数Purview(UAL)で 1 週間に操作を実施したユーザーの一意数利用状況を把握し、教育や権限棚卸しの判断材料に
上位 API エンドポイント診断ログでの RequestUri 上位 10最適化対象の特定
失敗率(全体/エンドポイント別)4xx/5xx 件数 ÷ 総件数エラー傾向の早期発見
p95 レイテンシDurationMs の 95 パーセンタイルSLO の監視

権限・ロールの最小化(最小権限で安全に)

  • Purview 監査検索:Audit logs または View‑Only Audit logs ロール。
  • PowerShell(UAL):Exchange 管理権限(監査閲覧に必要な最小)。
  • Graph(signIns):AuditLog.Read.All(アプリ権限)や Directory.Read.All。
  • Purview のデータ面操作:Data Map のロール(Data Reader/Curator など)を最小付与。

ベストプラクティス:監査の取得・分析基盤は運用アカウント/アプリに分離し、MFA/条件付きアクセスで厳格化します。監査基盤のアクセス自体も監査対象に。

保持期間とコストの考え方

  • Unified Audit Log の保持はライセンス(例:Standard/Premium)と監査保持ポリシーで決定。長期保持は Export API/Storage 併用。
  • Log Analytics は保持期間(例:30, 90, 180, 365 日…)をワークスペース単位で調整。長期はテーブル単位のアーカイブ/検索モードも検討。
  • コスト最適化:不要フィールドの投機的取り込みを避ける、サンプリングをせずに 閾値ベースでアラート化、古いデータは Storage に退避してオンデマンド分析。

トラブルシューティングの型

500 エラーが増えたとき

  1. 診断ログで HttpStatusCode = 500 を時間軸にプロット(特定 URI/テナント横断かを判別)。
  2. CorrelationId で該当リクエストをアプリ ログと突合。
  3. UAL に操作失敗があるか確認(ResultStatus)。
  4. 前段のプロキシ/ゲートウェイ ログで同時間帯の 4xx/5xx を確認(タイムアウトやサイズ制限など)。

「誰がどこから?」が不明瞭なとき

  • UAL の ClientIP と診断ログの CallerIpAddress を比較。
  • Graph の signIns(ipAddress)をユーザー+時刻でジョイン。
  • NAT 配下で IP が収束する場合、逆プロキシやファイアウォールのアクセス ログで X-Forwarded-For を確認。

サンプル:プログラムからの取得コード断片

PowerShell(Unified Audit Log)

Connect-ExchangeOnline
$from = (Get-Date).AddDays(-1)
$to   = Get-Date
$ops  = @("PurviewDataMapOperation") # 実際の表示名を使用
$result = Search-UnifiedAuditLog -StartDate $from -EndDate $to -Operations $ops -ResultSize 5000
$result | Export-Csv -Path ".\purview-ual.csv" -NoTypeInformation -Encoding UTF8

cURL(Management Activity API の概念例)

# サブスクリプション開始(テナント ID, トークンは既取得と仮定)
curl -X POST \
  "https://manage.office.com/api/v1.0/&lt;tenant-id&gt;/activity/feed/subscriptions/start?contentType=Audit.General" \
  -H "Authorization: Bearer &lt;access_token&gt;"

# コンテンツ一覧取得

curl -s 
"[https://manage.office.com/api/v1.0/&lt;tenant-id&gt;/activity/feed/subscriptions/content?contentType=Audit.General&amp;startTime=2025-10-26T00:00:00Z&amp;endTime=2025-11-02T00:00:00Z](https://manage.office.com/api/v1.0/&lt;tenant-id&gt;/activity/feed/subscriptions/content?contentType=Audit.General&amp;startTime=2025-10-26T00:00:00Z&amp;endTime=2025-11-02T00:00:00Z)" 
-H "Authorization: Bearer <access_token>" > list.json

# 各 contentUri を GET して JSON を収集

KQL(Purview 操作ログの短時間サマリ)

PurviewDataMapOperation_CL
| where TimeGenerated &gt; ago(1d)
| summarize ops=count(), users=dcount(UserId_s), targets=dcount(ObjectId_s)

KQL(API 呼び出しの発信元 Top /24)

PurviewDataPlaneRequests_CL
| where TimeGenerated &gt; ago(7d)
| extend Subnet24 = strcat(split(CallerIpAddress_s, ".")[0], ".", split(CallerIpAddress_s, ".")[1], ".", split(CallerIpAddress_s, ".")[2], ".0/24")
| summarize count() by Subnet24
| top 20 by count_ desc

公式ガイドを読む時の観点(リンクなし要約)

  • 「監査のオン/オフ」:Unified Audit Log の取り込みを有効化/確認する手順。
  • 「監査の検索」:Purview 監査ソリューションでの検索 UI と、検索式/エクスポート方法。
  • 「Data Map 監査・診断ログ」:Purview アカウントの診断ログ カテゴリ、Log Analytics 送信、フィールド説明。
  • 「Application Gateway + Private Link の構成」:SNI/Host ヘッダーの扱い、WAF と再暗号化、プライベート DNS の作法。

製品の呼称やレコード種別は更新されることがあります。UI に表示される名前・フィールドを基準に読み替えてください。

よくある質問(FAQ)

Q. Microsoft Graph の directoryAudits で Purview の操作は取れますか?
A. directoryAudits は主にテナントのディレクトリ(Entra ID)に対する操作です。Purview の操作は原則、Unified Audit Log(Purview 監査)で取得し、必要に応じてサインイン ログ(auditLogs/signIns)と突合します。

Q. 監査ログの時刻が実際より遅れて見えるのは?
A. 取り込み遅延が発生する場合があります。SLA はリアルタイムではないため、秒単位の相関が必要な分析は診断ログ(Azure Monitor)を併用してください。

Q. Private Endpoint 経由で IP が社内 NAT になる。実ユーザー IP は残せる?
A. UAL の ClientIP は Microsoft 側の観測 IP となるため NAT で収束します。逆プロキシ/WAF のアクセス ログに X-Forwarded-For を残し、サインイン ログと突合するのが実務的です。

Q. どのログをどこに送ればよいか迷う
A. 即時分析やアラートは Log Analytics、長期保管は Storage、外部 SIEM 連携やストリーム処理は Event Hub が基本指針です。すべてに送っても構いませんが、コスト最適化の観点で保持日数や対象カテゴリを選別しましょう。

まとめ

Purview でのアクセス/API 呼び出しの監査は、Unified Audit Log(論理操作)× 診断ログ(HTTP 事実)× サインイン(発信元)の三位一体で設計するのが近道です。x-ms-client-request-id と相関 ID を活用してログ同士をつなぎ、KQL とアラートで「異常が起きたときにすぐ分かる」体制を作りましょう。Private Endpoint の前段にプロキシ/ロードバランサを置く場合は、SNI/Host の整合と X-Forwarded-* の継承を徹底し、ネットワーク層の証跡も欠かさず残してください。これらを組み合わせれば、「誰が・いつ・どこから・何をしたか」を自信を持って説明できる監査基盤が完成します。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次