Azure ADの監査ログを取得 ~ポータルダウンロード編~

◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

こんにちは、サイオステクノロジーの小川です。

今回はAzure ADの監査ログ30日を超えて保持する方法として、Azureポータルからダウンロードし、CSV形式でローカルに取得する方法を紹介します。

Microsoft Graph APIを利用した監査ログの取得方法については以下の記事をご覧ください。

Azure ADの監査ログを取得 ~Microsoft Graph API編~

監査ログとは

Azure AD 内のさまざまな機能によって行われたすべての変更についてログによる追跡可能性を提供します。 
監査ログの例として、ユーザー、アプリ、グループ、ロール、ポリシーの追加や削除など、Azure AD 内のあらゆるリソースに加えられた変更が記録されます。

Azure ADのログは30日(P1, P2ライセンス保持の場合。Azure AD Freeは7日)しか保持できません。
例えば、Azureのサブスクリプションを持っていないけれども、ログは30日以上保持する必要がある。といった場合はこちらの方法でログを保持することが可能です。

詳細はこちらに公開情報があるのでご参照下さい。

Azure ADから監査ログをダウンロードする

Azureポータルにアクセスし、管理者権限を持つアカウントでサインインします。

Azure Active Directoryの「監視」の「監査ログ」を選択します。
許可された時刻でダウンロードするログの期間を選択します。

上部にある「ダウンロード」をクリックすると右側にダウンロード設定項目が表示されます。
出力するファイル形式と、ファイル名を入力して「ダウンロード」をクリックします。

CSVファイル形式

今回の標題にあるように、「ここでCSV形式に設定すればいいじゃん!」とまず考えるでしょう。私も考えました。
しかし、ここでCSV形式にしてダウンロードした場合、すべてのデータが保存されるわけではないのです!

実際に見てみましょう。

CSVをダウンロードして、ファイルを開くと、Azureポータルのログと同様の内容が記載されています。
今回はAzure AD Connectで同期したユーザのログを例に確認してみます。

ActorUserPrincipalNameがSync_で始まるものがAzure AD Connectから同期した際のログになります。

"日付 (UTC)","CorrelationId","サービス","カテゴリ","アクティビティ","結果","ResultReason","ActorType","ActorDisplayName","ActorObjectId","ActorUserPrincipalName","IPAddress","ActorServicePrincipalId","ActorServicePrincipalName",
"Target1Type","Target1DisplayName","Target1ObjectId","Target1UserPrincipalName","Target1ModifiedProperty1Name","Target1ModifiedProperty1OldValue","Target1ModifiedProperty1NewValue","Target1ModifiedProperty2Name",
"Target1ModifiedProperty2OldValue","Target1ModifiedProperty2NewValue","Target1ModifiedProperty3Name","Target1ModifiedProperty3OldValue","Target1ModifiedProperty3NewValue","Target1ModifiedProperty4Name","Target1ModifiedProperty4OldValue",
"Target1ModifiedProperty4NewValue","Target1ModifiedProperty5Name","Target1ModifiedProperty5OldValue","Target1ModifiedProperty5NewValue","Target2Type","Target2DisplayName","Target2ObjectId","Target2UserPrincipalName",
"Target2ModifiedProperty1Name","Target2ModifiedProperty1OldValue","Target2ModifiedProperty1NewValue","Target2ModifiedProperty2Name","Target2ModifiedProperty2OldValue","Target2ModifiedProperty2NewValue","Target2ModifiedProperty3Name",
"Target2ModifiedProperty3OldValue","Target2ModifiedProperty3NewValue","Target2ModifiedProperty4Name","Target2ModifiedProperty4OldValue","Target2ModifiedProperty4NewValue","Target2ModifiedProperty5Name","Target2ModifiedProperty5OldValue",
"Target2ModifiedProperty5NewValue","Target3Type","Target3DisplayName","Target3ObjectId","Target3UserPrincipalName","Target3ModifiedProperty1Name","Target3ModifiedProperty1OldValue","Target3ModifiedProperty1NewValue",
"Target3ModifiedProperty2Name","Target3ModifiedProperty2OldValue","Target3ModifiedProperty2NewValue","Target3ModifiedProperty3Name","Target3ModifiedProperty3OldValue","Target3ModifiedProperty3NewValue","Target3ModifiedProperty4Name",
"Target3ModifiedProperty4OldValue","Target3ModifiedProperty4NewValue","Target3ModifiedProperty5Name","Target3ModifiedProperty5OldValue","Target3ModifiedProperty5NewValue","AdditionalDetail1Key","AdditionalDetail1Value","AdditionalDetail2Key",
"AdditionalDetail2Value","AdditionalDetail3Key","AdditionalDetail3Value","AdditionalDetail4Key","AdditionalDetail4Value","AdditionalDetail5Key","AdditionalDetail5Value","AdditionalDetail6Key","AdditionalDetail6Value"

"2021-05-18T12:01:28.9201835+00:00","7f0e7ab8-1c69-4fc0-9104-xxxxxx","Core Directory","UserManagement","Add user","Success","","ユーザー","","9269f7b4-c7f6-4db5-a06e-xxxxxx","Sync_AD_xxxxxx@xxx.onmicrosoft.com","","","","User","",
"8fe29c9d-a905-404d-b2a6-xxxxxx","test001@xxx.xxx.com","AccountEnabled","[]","[true]","DisplayName","[]","[""test 001""]","GivenName","[]","[""001""]","JobTitle","[]","[""一般""]","LastDirSyncTime","[]","[""2021-05-18T12:01:28Z""]",
"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","{81}","{82}

カラムが多すぎて、ものすごく見にくい。。。
(Excleで開くと少し見やすくなるかも。。。)

よく見ると、Target~ というカラムがたくさんあります。
ここの値にAzure ADで更新された情報が記録されています。

監査ログの詳細はAzure ADの監査ログでも詳細を見ると「変更されたプロパティ」の項目に記録されます。
出力されたCSVを見ると、確かに「Target1ModifiedPropertyxName」がプロパティ名「oldvalue」、「newvalue」に古い値、新しい値が入力されています。

Azure ADの監査ログでアカウント追加時に更新された属性のとしてログに記録されていのは
「AccountEnabled, DisplayName, GivenName, JobTitle, LastDirSyncTime, MailNickname, ProxyAddresses, SourceAnchor, Surname, UserPrincipalName, UserType」です。

しかし、CSVで記載されているのは「AccountEnabled, DisplayName, GivenName, JobTitle, LastDirSyncTime」の5属性となっています。
このoldvalueとnewvalue 。CSVのカラムには一つのプロパティに対して、5項目までしか表示がありません。

5項目以上の行使があった場合、CSV形式ではすべてを記録することができないものになっています。

JSONファイル形式

CSV形式はすべての更新のログが記録できないことが分かりました。そこで、監査ログをJSON形式でダウンロードしてみます。

[{"id":"Directory_7f0e7ab8-1c69-4fc0-9104-xxxxxxx","category":"UserManagement","correlationId":"7f0e7ab8-1c69-4fc0-9104-xxxxxxx","result":"success","resultReason":"","activityDisplayName":"Add user","activityDateTime":"2021-05-18T12:01:28.9801885+00:00","loggedByService":"Core Directory","initiatedBy":{"user":{"id":"9269f7b4-c7f6-4db5-a06e-xxxxxx","displayName":null,"userPrincipalName":"Sync_AD_xxxxx@xxx.onmicrosoft.com","ipAddress":""}},"targetResources":[{"id":"fa99359e-f502-4e95-925a-xxxxxx","displayName":null,"type":"User","userPrincipalName":"test003@xxx.xxx.com","groupType":null,"modifiedProperties":[{"displayName":"AccountEnabled","oldValue":"[]","newValue":"[true]"},{"displayName":"DisplayName","oldValue":"[]","newValue":"[\"test 001\"]"},{"displayName":"GivenName","oldValue":"[]","newValue":"[\"001\"]"},{"displayName":"JobTitle","oldValue":"[]","newValue":"[\"一般\"]"},{"displayName":"LastDirSyncTime","oldValue":"[]","newValue":"[\"2021-05-18T12:01:28Z\"]"},{"displayName":"MailNickname","oldValue":"[]","newValue":"[\"test003\"]"},{"displayName":"ProxyAddresses","oldValue":"[]","newValue":"[\"SMTP:test003@xxx.xxx.com\",\"smtp:test003@xxx.onmicrosoft.com\"]"},{"displayName":"SourceAnchor","oldValue":"[]","newValue":"[\"test003\"]"},{"displayName":"Surname","oldValue":"[]","newValue":"[\"test\"]"},{"displayName":"UserPrincipalName","oldValue":"[]","newValue":"[\"test003@xxx.xxx.com\"]"},{"displayName":"UserType","oldValue":"[]","newValue":"[\"Member\"]"},{"displayName":"Included Updated Properties","oldValue":null,"newValue":"\"AccountEnabled, DisplayName, GivenName, JobTitle, LastDirSyncTime, MailNickname, ProxyAddresses, SourceAnchor, Surname, UserPrincipalName, UserType\""},{"displayName":"Action Client Name","oldValue":null,"newValue":"\"DirectorySync\""}]}],"additionalDetails":[]}]

一行でとても見づらいです。なのでこのログの情報や更新されているプロパティが分かりやすくなるようにJSON形式のファイルを整形してみましょう。

PoserShellスクリプトを使用して、ダウンロードしたファイルをCSV形式に整形します。
以下をコピーして、適当なフォルダに拡張子.ps1で保存します。

$data = @()
$getfile = Read-Host "Enter the path of the file to read."

if((Test-Path $getfile) -eq $true){
    $myReportValue = ((Get-Content $getfile -Encoding UTF8) | ConvertFrom-Json | ConvertTo-Json -Depth 4 | ConvertFrom-Json).value
    
    ForEach ($values In $myReportValue) {
        $data += New-Object PSObject ($values | Select id, 
            category, 
            correlationId, 
            result, 
            resultReason, 
            activityDisplayName, 
            activityDateTime, 
            loggedByService, 
            operationType, 
            initiatedBy, 
            targetId, 
            displayName, 
            type, 
            userPrincipalName, 
            modifiedProperties, 
            key, 
            value)
        ForEach ($resources In $values.targetResources) {
            $data += New-Object PSObject ($resources | Select @{label = "operationType" ;expression = {$values.operationType}}, 
                @{label = "targetId" ;expression = {$resources.id}}, 
                displayName, 
                userPrincipalName, 
                groupType)
            ForEach ($properties In $resources.modifiedProperties) {
                $data += New-Object PSObject ($properties | Select @{label = "operationType" ;expression = {$values.opexrationType}}, 
                    @{label = "userPrincipalName" ;expression = {$resources.userPrincipalName}}, 
                    @{label = "modifiedProperties" ;expression = {$properties}})
            }
        }
        ForEach ($details In $values.additionalDetails) {
            $data += New-Object PSObject ($details | Select key, value)
        }
    }
    $data | Export-CSV "output.csv" -encoding "utf8" -NoTypeInformation
    Write-Host "Audit log is exported to output.csv"
}else{
    Write-Host "ERROR: No File Exist"
}

PowerShellを開きます。上記スクリプトを配置したフォルダに移動し、スクリプトを実行します。
(今回はC:¥AuditLogは以下にスクリプトを配置しました。)
ダウンロードしたJSONファイル名を入力すると、ファイルを整形しCSV形式に変換します。

PS C:\Users\Admin>cd C:\AuditLog
PS C:\AzureLog> .\ChangeFormatAuditLog.ps1
Enter the path of the file to read.: <ダウンロードしたjsonファイル名を入力>

Audit log is exported to output.csv

output.csvでファイルが出力されるので、開いて確認してみます。

"id","category","correlationId","result","resultReason","activityDisplayName","activityDateTime","loggedByService","operationType","initiatedBy","targetId","displayName","type","userPrincipalName","modifiedProperties","key","value"

"Directory_7f0e7ab8-1c69-4fc0-9104-xxxxxx","UserManagement","7f0e7ab8-1c69-4fc0-9104-xxxxxx","success","","Add user","2021-05-18T12:01:28.9201835+00:00","Core Directory",,"@{user=}",,,,,,,
,,,,,,,,,,"8fe29c9d-a905-404d-b2a6-eff1c89f9fe3",,,"test001@xxx.xxx.com",,,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=AccountEnabled; oldValue=[]; newValue=[true]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=DisplayName; oldValue=[]; newValue=[""test 001""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=GivenName; oldValue=[]; newValue=[""001""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=JobTitle; oldValue=[]; newValue=[""一般""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=LastDirSyncTime; oldValue=[]; newValue=[""2021-05-18T12:01:28Z""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=MailNickname; oldValue=[]; newValue=[""test001""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=ProxyAddresses; oldValue=[]; newValue=[""SMTP:test001@xxx.xxx.com"",""smtp:test001@xxx.onmicrosoft.com""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=SourceAnchor; oldValue=[]; newValue=[""test001""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=Surname; oldValue=[]; newValue=[""test""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=UserPrincipalName; oldValue=[]; newValue=[""test001@xxx.xxx.com""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=UserType; oldValue=[]; newValue=[""Member""]}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=Included Updated Properties; oldValue=; newValue=""AccountEnabled, DisplayName, GivenName, JobTitle, LastDirSyncTime, MailNickname, ProxyAddresses, SourceAnchor, Surname, UserPrincipalName, UserType""}",,
,,,,,,,,,,,,,"test001@xxx.xxx.com","@{displayName=Action Client Name; oldValue=; newValue=""DirectorySync""}",,

一目でユーザのどの属性の値が更新されているかが分かるようになりました。
CSVで記録する項目を制限したい場合は、スクリプトの「select」項目で調整可能です。

まとめ

Azure ADから監査ログをダウンロードする場合、ファイルはCSVではなくJSON形式を指定することですべてのログの記録が取得可能です。
CSV形式でダウンロードした場合、ユーザの更新属性が最大5属性しか保持することができません。

またJSON形式でもAzure AD Connectで同期するすべての属性がこちらで確認できるわけではありません。
ID同期で反映される監査ログの主な属性は以下になります。
「AccountEnabled, City, Country, Department, DisplayName, GivenName, JobTitle, LastDirSyncTime, MailNickname, Mobile, ProxyAddresses, SourceAnchor, Surname, TelephoneNumber, UserPrincipalName, UserType, StreetAddress, State, PhysicalDeliveryOfficeName, PostalCode」など

Microsoft365に関連する属性「preferredLanguage」や「msExchHideFromAddressLists」などのAzure ADには関わりのない属性については、Azure ADの監査ログには記録されないので、ダウンロードするファイルにも記録されません。

 

アバター画像
About 小川雄大 27 Articles
IDaaSプロジェクトを担当。
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる