M365監査ログ「AuditData」カラムのJSONデータを変換し、CSVへ出力するPowerShellスクリプト

# はじめに
以前下記URLの記事にて、M365監査ログ「AuditData」カラムのJSONデータをCSVへ出力する方法について解説いたしました。

https://qiita.com/B001173/items/4aa30b22551fa3ae50b9

PowerShellのコマンドを利用した分解方法は解説したものの、毎回コマンドを実行してJSONデータを分解していくのはとてもめんどくさいです。

自分なりにJSONデータを変換しCSVへ出力するという手順をPowerShellスクリプト化してみました。


## 出力する内容について

前回の記事でも記載しましたが、改めて今回出力する内容について記載しておきます。
今回記載以外のデータを出力したい場合は、下記URLを参考にしていただければ幸いです。

https://learn.microsoft.com/ja-jp/purview/audit-log-detailed-properties?view=o365-worldwide

前回と同様、下記プロパティを抽出し新規CSVに出力したいと思います。
CreationTime：レコードが作成された時間（UTC表記）
UserId：ユーザ名
Workload：利用されたサービス名
Operation：実行された操作

# 本題
先にPowerShellスクリプト全文を記載しておきます。
本項目以降の項番にて、各処理について説明いたします。

```PowerShell:ConvertAuditdata.ps1
# Windows Formsをロード
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# ファイル選択ダイアログを表示する関数
function Get-FileName($initialDirectory, $filter, $title) {
    $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $OpenFileDialog.InitialDirectory = $initialDirectory
    $OpenFileDialog.Filter = $filter
    $OpenFileDialog.Title = $title
    $OpenFileDialog.ShowDialog() | Out-Null
    return $OpenFileDialog.FileName
}

# 入力ファイルを選択
Write-Host "M365監査ログを選択してください。"
$inputfile = Get-FileName -initialDirectory $PSScriptRoot -filter "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*" "M365監査ログを選択してください"
if ([string]::IsNullOrEmpty($inputfile)) {
    Write-Host "M365監査ログが選択されませんでした。スクリプトを終了します。" -ForegroundColor DarkYellow
    Read-Host "Enterキーを押してスクリプトを終了してください" 
    exit
}

# 入力ファイルから情報を取得
$InputData = Import-Csv -Path $inputfile -Encoding UTF8

# 「AuditData」カラムのJSON文字列を変換
$JsonData = $InputData.AuditData | ConvertFrom-Json

# 出力用オブジェクトの初期化
$ExportData = @()

# 必要な情報のみを抜き取り出力する
foreach ($Data in $JsonData) {
    # 出力用オブジェクトの作成
    $ExportData += [PSCustomObject]@{
        CreationTime = $Data.CreationTime # レコードが作成された時間(UTC表記)
        UserId = $Data.UserId # ユーザ名
        Workload = $Data.Workload # 利用サービス
        Operation = $Data.Operation # 実行した操作内容
    }
}

# 本スクリプトを配置しているディレクトリにCSVを出力
$ExportData | Export-Csv -Path ($PSScriptRoot + "\" + "AuditData.csv") -Encoding UTF8 -NoTypeInformationｚ

# 終了処理
Write-Host "処理が完了しました。" -ForegroundColor DarkGreen
Read-Host "Enterキーを押してスクリプトを終了してください"
exit
```

# PowerShellスクリプト詳細について
## 1.Windows Formsのロード
```PowerShell
# Windows Formsをロード
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
```
Add-Type コマンドレットを使用し、ファイル選択ダイアログを表示するために必要となる「.NET Framework」のアセンブリ「System.Windows.Forms」と「System.Drawing」をロードする。

## 2.ファイル選択ダイアログを表示する関数
```PowerShell
# ファイル選択ダイアログを表示する関数
function Get-FileName($initialDirectory, $filter, $title) {
    $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
    $OpenFileDialog.InitialDirectory = $initialDirectory
    $OpenFileDialog.Filter = $filter
    $OpenFileDialog.Title = $title
    $OpenFileDialog.ShowDialog() | Out-Null
    return $OpenFileDialog.FileName
}
```
各処理は下記記載の通り。
・New-Object で OpenFileDialog オブジェクトを作成。

・InitialDirectory: ダイアログが開くときの初期ディレクトリ。

・Filter: 表示するファイルの種類を制限するフィルター (例: CSV ファイルのみ)。

・Title: ダイアログのタイトル。

・ShowDialog(): ダイアログを表示し、ユーザーの操作 (ファイル選択またはキャンセル) を待機。

・Out-Null: ShowDialog()メソッドの戻り値 (ダイアログの結果) を無視。

・return $OpenFileDialog.FileName: 選択されたファイルのフルパスを返す。ファイルが選択されなかった場合は空文字列を返す。

## 3.入力ファイルの選択
```Powershell
# 入力ファイルを選択
Write-Host "M365監査ログを選択してください。"
$inputfile = Get-FileName -initialDirectory $PSScriptRoot -filter "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*" "M365監査ログを選択してください"
if ([string]::IsNullOrEmpty($inputfile)) {
    Write-Host "M365監査ログが選択されませんでした。スクリプトを終了します。" -ForegroundColor DarkYellow
    Read-Host "Enterキーを押してスクリプトを終了してください" 
    exit
}
```
・Write-HostでPowerShell上にメッセージを表示。

・Get-FileName関数を呼び出してファイル選択ダイアログを表示。

・スクリプトが配置されているパスをダイアログが開いた際の初期ディレクトリとして設定。

・フィルターは CSV ファイルとすべてのファイルを指定。

・[string]::IsNullOrEmpty($inputfile):選択されたファイルパスが存在するかチェック。

・ファイルが選択されなかった場合は、警告メッセージを表示してスクリプトを終了。

## 4.項番3で選択したCSVファイルを読み込み
```PowerShell
# 入力ファイルから情報を取得
$InputData = Import-Csv -Path $inputfile -Encoding UTF8
```
選択したCSVファイル内の項目から、テーブルのようなカスタムオブジェクトを作成する。

## 5.「AuditData」カラムのJSON文字列を変換
```PowerShell
$JsonData = $InputData.AuditData | ConvertFrom-Json
```
JavaScript Object Notation (JSON)形式の文字列をカスタムオブジェクトまたはJSON文字列内の各フィールドをプロパティとして持つハッシュテーブルオブジェクトに変換。

## 6.「AuditData」カラムの任意のパラメータをCSVへ出力
```PowerShell
# 出力用オブジェクトの初期化
$ExportData = @()

# 必要な情報のみを抜き取り出力する
foreach ($Data in $JsonData) {
    # 出力用オブジェクトの作成
    $ExportData = [PSCustomObject]@{
        CreationTime = $Data.CreationTime # レコードが作成された時間(UTC表記)
        UserId = $Data.UserId # ユーザ名
        Workload = $Data.Workload # 利用サービス
        Operation = $Data.Operation # 実行した操作内容
    }
}
```
・＄JsonDataの各要素($Data)に対して「foreach」を用いてループ処理の実行。

・[PSCustomObject]:各ループで、CreationTime、UserId、Workload、Operation プロパティを持つカスタム オブジェクトを作成し$ExportDataに代入。

## 7.終了処理
```PowerShell
# 終了処理
# 本スクリプトを配置しているディレクトリにCSVを出力
 $ExportData | Export-Csv -Path ($PSScriptRoot + "\" + "AuditData.csv") -Encoding UTF8 -NoTypeInformation
Write-Host "処理が完了しました。" -ForegroundColor DarkGreen
Read-Host "Enterキーを押してスクリプトを終了してください"
exit
```
・＄ExportData | Export-Csv: $ExportData (現在のループで作成されたオブジェクト) を CSV ファイルに出力。

・-Encoding UTF8: UTF-8 エンコーディングで出力。

・-NoTypeInformation:不要な型情報を出力しないように設定。

完了メッセージを表示し、ユーザがエンターキーを押下することでスクリプトの処理が完了する。

# 最後に
M365監査ログ「AuditData」カラムのJSONデータをPowerShellスクリプトによって分解する方法について解説させていただきました。

素人開発のためスクリプト内の記述に至らない部分はあるかと思いますが、その点はご了承ください。