こんにちは、Power Platform サポートの清水です。
今回は、よくお問い合わせをいただく題材の一つとして、クラウド フローを使用して、Microsoft Purview の監査ログを取得する方法について紹介します。  
2023 年 10 月現時点では、監査ログを取得できるようなコネクタ・アクションは存在しないため、監査ログを取得するには、Office 365 Management API を使用する必要があります。
少し複雑なフローになりますが、最後までお付き合いいただければと思います。  
必要なライセンスについて
プレミアム コネクタを使用するフローとなりますので、有償ライセンスが必要です。
以下のいずれかのライセンス/環境があれば、フローを実行可能です。  
- Power Automate Premium (※ 旧名: Power Automate per user with attended RPA)
 - Power Automate Process
 - Power Automate per user (※ 2023/8/1~ レガシー)
 - Power Automate per flow (※ 2023/8/1~ レガシー)
 - 従量課金制環境
 
必要な権限について
Office 365 Management API を使用するために必要なアクセス許可を付与する際、テナント管理者の同意が必要となります。
同意の付与には、グローバル管理者の権限が必要です。
手順の概要
フローは大きく 7 つのステップで構成されます。
- 事前準備
Office 365 Management API を使用する準備として、Azure AD へのアプリケーションの登録およびアクセス許可の付与などを行います。
ここでは Power Automate は使用いたしません。 - 事前準備で取得したパラメータを変数に格納
 - Office 365 Management API で既存のサブスクリプションの確認
監査ログを API から取得するために、まずはサブスクリプションを開始する必要があります。
既に開始済みで有効な状態であれば、サブスクリプションを新しく開始する必要はないので、本ステップでは、既存のサブスクリプションがあるかどうかを確認します。 - (既存のサブスクリプションが存在しない場合) Office 365 Management API でサブスクリプションの開始
手順 1 で既存のサブスクリプションの一覧を取得したので、目的のサブスクリプションがないか、無効な状態の場合には、サブスクリプションを開始します。 - Office 365 Management API でコンテンツ リストの取得
コンテンツ (監査ログ) 自体を取得するために、まずは取得可能なコンテンツ リストを取得する必要があります。
このコンテンツ リストで得られた値を使用して、後続のステップでコンテンツ自体を取得していきます。 - Office 365 Management API でコンテンツの取得
コンテンツを取得し、変数に格納していきます。 - CSVファイルの作成・保存
CSV ファイルを作成し、クラウド ストレージに保存したら完了です。 
それでは、詳細な手順について見ていきましょう。
0. 事前準備
0-1.アプリの登録
Office 365 Management API の利用を開始するため、Office 365 Management API の使用を開始する の下記の箇所を実施してください。  
- Azure portal を使用してアプリケーションを Azure AD で登録する
※リダイレクト URI は空のまま作成します。 - アプリケーションの新しいキーを生成する
 - アプリが Office 365 Management APIにアクセスするために必要な許可を指定します。
※今回は HTTP コネクタを使用するため、手順 3 では「b. アプリケーションのアクセス許可」を選択してください。 
手順の完了後、フローで使用する以下 3 つの値を控えておきます。
- アプリケーション (クライアント) ID
 - ディレクトリ (テナント) ID

 - 作成したシークレットの値

 
0-2.Office 365 Management API のエンドポイントの確認
Office 365 Management API のエンドポイントを以下から確認します。
アクティビティ API の操作  
今回使用する検証用のテナントでは、パブリック クラウドを使用しているため、”Enterprise プラン” の URL を使用します。
1  | https://manage.office.com/api/v1.0/{tenant_id}/activity/feed/{operation}  | 
{tenant_id}部分には、ご使用のテナント ID を指定します。{operation}部分には、これから使用する API の “パス” を指定します。
0-3.Office 365 Management API のコンテンツタイプの確認
このフローで取得したい監査ログの種類を以下から確認します。
Office 365 管理アクティビティ API の操作  
本ブログでは、Audit.AzureActiveDirectory を対象とすることとします。  
1. 事前準備で取得したパラメータをフローの変数に格納
ここからフローの作成に入っていきます。
1-1.トリガーを決定し、フローを一から作成
今回は日次でログを取得することにしたいので、繰り返しトリガーを選択します。
トリガーの設定は要件に合わせてご設定ください。  
  
1-2.事前準備で取得した 5 つの値を変数に格納
変数コネクタ「変数を初期化する」アクションを 5 つフローに追加し、それぞれ以下のように設定します。
- テナント ID
 
  
| パラメータ | 値 | 
|---|---|
| 名前 | tenantID | 
| 種類 | 文字列 | 
| 値 | 0-1 で取得した「ディレクトリ (テナント) ID」 | 
- クライアント ID
 
  
| パラメータ | 値 | 
|---|---|
| 名前 | clientID | 
| 種類 | 文字列 | 
| 値 | 0-1 で取得した「アプリケーション (クライアント) ID」 | 
- シークレット
 
  
| パラメータ | 値 | 
|---|---|
| 名前 | secret | 
| 種類 | 文字列 | 
| 値 | 0-1 で取得した「シークレット」 | 
- エンドポイント
 
  
| パラメータ | 値 | 
|---|---|
| 名前 | endpoint | 
| 種類 | 文字列 | 
| 値 | 0-2 で取得したエンドポイントの “/{operation}” の直前まで 例: https://manage.office.com/api/v1.0/@{variables('tenantID')}/activity/feed  | 
- コンテンツタイプ
 
  
| パラメータ | 値 | 
|---|---|
| 名前 | contentType | 
| 種類 | 文字列 | 
| 値 | 0-3 で取得した「コンテンツ タイプ」 例: Audit.AzureActiveDirectory | 
2.Office 365 Management API で既存のサブスクリプションの確認
監査ログを API から取得するために、まずはサブスクリプションを開始する必要があります。
既に開始済みで有効な状態であれば、サブスクリプションを新しく開始する必要はないので、本ステップでは、既存のサブスクリプションがあるかどうかを確認します。  
ここでは、以下の API を使用します。
現在のサブスクリプションのリストの作成  
2-1.サブスクリプション リストの作成
HTTP コネクタ「HTTP」アクションをフローに追加し、API のリファレンスに従って、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 方法 | GET | 
| URI | @{variables('endpoint')}/subscriptions/list | 
| 認証 | Active Directory OAuth | 
| テナント | 動的なコンテンツ > tenantID | 
| 対象ユーザー | https://manage.office.com/ | 
| クライアント ID | 動的なコンテンツ > clientID | 
| 資格情報の種類 | シークレット | 
| シークレット | 動的なコンテンツ > secret | 
まずはここまででフローを実行してみましょう。
フローの実行が成功し、下図赤枠のような出力が得られました。  
  
詳しく見てみると、以下のような JSON が出力されています。
1  | [  | 
Audit.General と Audit.SharePoint のサブスクリプションがリストされていて、どちらも status が enabled になっていますね。Audit.General と Audit.SharePoint のコンテンツタイプのサブスクリプションは有効のようですが、今回取得したい Audit.AzureActiveDirectory については開始されていないようなので、次のステップで追加していきます。  
3. (既存のサブスクリプションが存在しない場合) Office 365 Management API でサブスクリプションの開始
まずは、既存のサブスクリプションが存在するかどうかを「条件」アクションでチェックします。
条件の結果が「はい」の場合、既存の有効なサブスクリプションが存在しないので、Office 365 Management API を使用して、新たにサブスクリプションを開始します。
ここでは、以下の API を使用します。
サブスクリプションの開始  
3-1. 既存の有効なサブスクリプションを抽出
データ操作コネクタ「アレイのフィルター処理」アクションを追加し、以下のように設定します。
以下のアクションでは、HTTP | サブスクリプションリストを確認 アクションの出力から、status が enabled かつ contentType が contentType 変数の値 に等しいオブジェクトのみを抽出します。  
  
| パラメータ | 値 | 
|---|---|
| 差出人 | 動的なコンテンツ > HTTP | サブスクリプションリストを確認 - 本文 | 
| 条件 | [詳細設定モードで編集] をクリック > 下式を入力 @and(equals(item()?['status'], 'enabled'), equals(item()?['contentType'], variables('contentType'))) | 
3-2.既存の有効なサブスクリプションが存在するかどうかを判定
コントロールコネクタ「条件」アクションを追加し、以下のように設定します。
以下のアクションでは、アレイのフィルター処理 アクションの出力が空かどうかを判定します。  
  
| パラメータ | 値 | 
|---|---|
| 左辺 | 式 > empty(body('アレイのフィルター処理')) | 
| 条件 | 次の値に等しい | 
| 右辺 | 式 > true | 
3-3.サブスクリプションの開始はいの場合 内にHTTP コネクタ「HTTP」アクションをフローに追加し、API のリファレンスに従って、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 方法 | POST | 
| URI | @{variables('endpoint')}/subscriptions/start?contentType=@{variables('contentType')} | 
| ヘッダー | Content-Type: application/json; utf-8 | 
| 認証 | Active Directory OAuth | 
| テナント | 動的なコンテンツ > tenantID | 
| 対象ユーザー | https://manage.office.com/ | 
| クライアント ID | 動的なコンテンツ > clientID | 
| 資格情報の種類 | シークレット | 
| シークレット | 動的なコンテンツ > secret | 
4. Office 365 Management API でコンテンツリストの取得
無事サブスクリプションが開始できたので、続いて、目的のコンテンツ タイプで現在取得できるコンテンツ一覧を取得します。
ここでは、以下の API を使用します。
利用可能なコンテンツのリストの作成  
API のリファレンスを読むと、取得したいコンテンツの時間範囲をパラメータとして指定できるようですが、時間範囲は 24 時間以内とするよう推奨されています。
そのため、本フローでは、フロー実行日の前日 24 時間分のコンテンツを取得するよう設定します。  
また、本 API では、改ページが発生する可能性があるようです。
大量の監査ログが存在する場合に、改ページの処理を行わないと、全てのデータが取得できない恐れがあるため、Do until アクションを使用して、改ページへの対応も行っていきます。
4-1.startTime を前日の 00:00 JST (UTC: 15:00) に指定
変数コネクタ「変数を初期化する」アクションを追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 名前 | startTime | 
| 種類 | 文字列 | 
| 値 | @{addDays(convertFromUtc(utcNow(), 'Tokyo Standard Time'), -2, 'yyyy-MM-dd')}T15:00:00Z | 
4-2.endTime を前日の 23:59 JST (UTC: 14:59) に指定
変数コネクタ - 変数を初期化するアクションを追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 名前 | endTime | 
| 種類 | 文字列 | 
| 値 | @{addDays(convertFromUtc(utcNow(), 'Tokyo Standard Time'), -1, 'yyyy-MM-dd')}T14:59:59Z | 
4-3.配列変数を 2 つ用意
監査ログの取得結果を格納するための変数を事前に用意します。
変数コネクタ「変数を初期化する」アクションを 2 つフローに追加し、それぞれ以下のように設定します。   
  
| パラメータ | 値 | 
|---|---|
| 名前 | contents | 
| 種類 | アレイ | 
| 値 | 空欄のまま | 
  
| パラメータ | 値 | 
|---|---|
| 名前 | contentsAll | 
| 種類 | アレイ | 
| 値 | 空欄のまま | 
4-4.改ページに対応するための変数と繰り返しアクションを用意
変数コネクタ「変数を初期化する」アクションを追加し、以下のように設定します。
ここでは、コンテンツリストを取得するための URI を変数に格納します。リファレンスに従って設定してください。  
  
| パラメータ | 値 | 
|---|---|
| 名前 | contentsListUri | 
| 種類 | 文字列 | 
| 値 | @{variables('endpoint')}/subscriptions/content?contentType=@{variables('contentType')}&startTime=@{variables('startTime')}&endTime=@{variables('endTime')} | 
コントロールコネクタ「Do until」アクションを追加し、以下のように設定します。
    
| パラメータ | 値 | 
|---|---|
| 左辺 | 動的なコンテンツ > contentListUri | 
| 条件 | 次のもので始まらない | 
| 右辺 | https://manage.office.com/ | 
4-5.コンテンツリストの取得
Do until 内で HTTP コネクタ「HTTP」アクションをフローに追加し、API のリファレンスに従って、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 方法 | GET | 
| URI | 動的なコンテンツ > contentListUri | 
| 認証 | Active Directory OAuth | 
| テナント | 動的なコンテンツ > tenantID | 
| 対象ユーザー | https://manage.office.com/ | 
| クライアント ID | 動的なコンテンツ > clientID | 
| 資格情報の種類 | シークレット | 
| シークレット | 動的なコンテンツ > secret | 
さて、ここまでで一度フローを実行してみましょう。
フローが正常に実行され、HTTP | コンテンツリストの作成 アクションまで正常に完了しました。  
  
さらに「HTTP | コンテンツリストの作成」アクションの本文を詳しく見てみると、以下のようなデータが取得されています。
1  | [  | 
このデータをどう活用していくのかを確認するために、Office 365 Management API のリファレンスを見てみると、上記のコンテンツ リストに含まれる contentUri に対して GET 要求を行うことで、コンテンツ (=アクションまたはイベントのコレクション) が取得できるようです。  
そこで、次のアクションでは、コンテンツリスト内の各 contentUri に対して GET 要求を行っていきます。
5. Office 365 Management API でコンテンツの取得
コンテンツの取得には、以下の API を使用します。
コンテンツの取得  
リファレンスの “応答のサンプル” を見てみると、一つの contentUri に対して GET 要求を行うと、配列形式で複数のコンテンツが返却されるようです。
今回は、複数の contentUri に対して繰り返し GET 要求を行い、得られた配列を 1 つの CSV に出力したいので、事前に CSV 作成のための変数を用意しておき、各 contentUri から得られた配列は変数に格納していくこととします。
Power Automate の「変数の設定」アクションでは、自己参照ができないため、配列を結合しながら CSV にまとめていくために、手順 4-3 で 2 つの変数を用意しています。  
5-1.GET 要求を繰り返すためのループアクションを作成
Do until 内でコントロールコネクタ「Apply to each」アクションをフローに追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 以前の手順から出力を選択 | 動的なコンテンツ > HTTP | コンテンツリストの作成 > 本文 | 
5-2.コンテンツの取得
Apply to each 内で HTTP コネクタ「HTTP」アクションを追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 方法 | GET | 
| URI | 式 > items('Apply_to_each')?['contentUri'] | 
| 認証 | Active Directory OAuth | 
| テナント | 動的なコンテンツ > tenantID | 
| 対象ユーザー | https://manage.office.com/ | 
| クライアント ID | 動的なコンテンツ > clientID | 
| 資格情報の種類 | シークレット | 
| シークレット | 動的なコンテンツ > secret | 
5-3.contentsAll 変数の値を一時的に contents 変数に退避
Apply to each 内で変数コネクタ「変数の設定」アクションを追加し、以下のように設定します。  

| パラメータ | 値 | 
|---|---|
| 名前 | contents | 
| 値 | 動的なコンテンツ > 変数 > contentsAll | 
5-4.contents 変数の値と「HTTP | コンテンツの取得」アクションの本文を結合して contentsAll に格納
Apply to each 内で変数コネクタ「変数の設定」アクションを追加し、以下のように設定します。
配列の結合には、union 関数 を使用します。  
  
| パラメータ | 値 | 
|---|---|
| 名前 | contentsAll | 
| 値 | 式 > union(json(body('HTTP_|_コンテンツの取得')), variables('contents')) | 
5-5.「HTTP | コンテンツリストの作成」のヘッダーに NextPageUri があるかを確認
Do until 内でコントロールコネクタ「条件」アクションを追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 左辺 | 式 > outputs('HTTP_|_コンテンツリストの作成')['headers']?['NextPageUri'] | 
| 条件 | 次の値に等しくない | 
| 右辺 | 式 > Null | 
5-6.NextPageUri が存在する場合、contentsListUri 変数を NextPageUri で更新はいの場合 内に変数コネクタ「変数の設定」アクションをフローに追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 名前 | contentsListUri | 
| 値 | 式 > outputs('HTTP_|_コンテンツリストの作成')['headers']?['NextPageUri'] | 
5-7.NextPageUri が存在しない場合、contentsListUri 変数を 0 で更新いいえの場合 内に変数コネクタ「変数の設定」アクションをフローに追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 名前 | contentsListUri | 
| 値 | 0 | 
6. CSVファイルの作成・保存
これで監査ログの値を全て取得できたので、最後に CSV を作成してクラウド ストレージに保存します。
6-1.CSV ファイルの作成
データ操作コネクタ「CSV テーブルの作成」アクションを追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| 開始 | 動的なコンテンツ > 変数 > contentsAll | 
6-2.CSV ファイルの保存
今回は SharePoint のドキュメントライブラリに保存しますが、こちらはアクションの一例ですので、任意のストレージに保存してください。
SharePoint コネクタ「ファイルの作成」アクションを追加し、以下のように設定します。  
  
| パラメータ | 値 | 
|---|---|
| サイトのアドレス | 任意のサイト | 
| フォルダ―のパス | 任意のパス | 
| ファイル名 | 任意のファイル名(拡張子: .csv) | 
| ファイル コンテンツ | 動的なコンテンツ > CSV テーブルの作成 > 出力 | 
まとめ
長大なフローになりましたので、最後にフローの全体像を貼っておきます。
全体の構成に誤りがないか、以下のキャプチャと見比べて確認してみてください。  
今回は Audit.AzureActiveDirectory のコンテンツ タイプを対象に API を実行しましたが、SharePoint など他のコンテンツ タイプについても同じ構成のフローで実行できますので、ぜひカスタマイズして便利なフローを作ってみてください。  

補足
Power Autoamte のテンプレートギャラリーには、”Office 365 の監査ログで特定の詳細を監視してアラートを送信“ というテンプレートがありますが、こちらは古い API を使用しているため、現時点では使用が推奨されておりません。
監査ログの取得については、Office 365 Management API でのフローの作成をご検討ください。
※本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります。