次の方法で共有


チュートリアル: Microsoft Entra のデータを使用した Azure Data Explorer でのカスタマイズされたレポート

このチュートリアルでは、Microsoft Entra ID と Microsoft Entra ID ガバナンス サービスのデータを使用して、Azure Data Explorer (ADX) でカスタマイズされたレポートを作成する方法について説明します。 このチュートリアルは、Azure Monitor とエンタイトルメント管理によるアーカイブとレポートなどのその他のレポート オプションを補完するもので、監査ログを Azure Monitor にエクスポートして保持と分析することに重点を置いています。 これに対して、Microsoft Entra ID データを Azure Data Explorer にエクスポートすると、履歴や削除済みのオブジェクトを含む Microsoft Entra オブジェクトのカスタム レポートを柔軟に作成できます。 さらに、Azure Data Explorer を使用すると、スケーラビリティが非常に高く、柔軟なスキーマと保持ポリシーを備えた追加のソースからのデータ集約が可能になります。 Azure Data Explorer は、長年にわたってアクセス データを保持する必要がある場合や、アドホックな調査を行う必要がある場合、あるいはユーザーのアクセス データに対してカスタム クエリを実行する必要がある場合に特に役立ちます。

この記事では、Microsoft Entra からエクスポートした構成、ユーザー、アクセス権を、独自の SQL データベースにアクセス権を持つアプリケーションなどの他のソースからエクスポートしたデータと一緒に表示する方法を説明します。 次に、Azure Data Explorer で Kusto 照会言語 (KQL) を使用して、組織の要件に基づくカスタムレポートを構築します。

これらのレポートを作成するには、次の手順に従います。

  1. Azure サブスクリプションで Azure Data Explorer を設定するか、無料のクラスターを作成する。
  2. PowerShell スクリプトと Microsoft Graph を使用して、Microsoft Entra ID からデータを抽出する。
  3. テーブルを作成し、そのデータを Microsoft Entra ID から Azure Data Explorerにインポートする。
  4. Microsoft Entra ID ガバナンスからデータを抽出する。
  5. テーブルを作成し、そのデータを Microsoft Entra ID ガバナンスから Azure Data Explorer にインポートする
  6. Kusto クエリ言語を使用してカスタム クエリを作成します。

このチュートリアルを終了する頃には、ユーザーのアクセス権とアクセス許可に関するカスタマイズされたビューを作成できるようになります。 Microsoft がサポートするツールを使用して、これらのビューは異なるアプリケーションにまたがっています。 また、サードパーティのデータベースやアプリケーションからデータを取得し、それらをレポートに含めることもできます。

前提条件

Azure Data Explorer を初めて使用し、この記事で紹介するシナリオを確認したい場合は、無料の Azure Data Explorer クラスターを入手できます。 Azure Data Explorer のサービス レベル アグリーメントによるサポート付きの運用を行うには、完全な Azure Data Explorer クラスターをホストするための Azure サブスクリプションが必要です。

レポートに含めるデータを決定します。 この記事内のスクリプトでは、Microsoft Entra のユーザー、グループ、アプリケーションから取得した特定のデータを含むサンプルが提供されています。 これらのサンプルは、この方法で生成できるレポートの種類を示すことを目的としたものです。レポート作成のニーズはさまざまであり、それに応じて異なるデータや追加のデータが必要になる場合があります。 これらのオブジェクトから始めて、徐々に Microsoft Entra のオブジェクトの種類を増やしていくことができます。

  • この記事では、サインインしたユーザーとして Microsoft Entra からデータを取得する方法を説明します。 これを行うには、Microsoft Entra からデータを取得するために必要なロールが割り当てられていることを確認してください。 また、作業対象の Microsoft Entra データの種類のエクスポートに必要な適切なアクセス許可を持つロールが必要です。
    • ユーザー データ: グローバル管理者、特権ロール管理者、ユーザー管理者
    • グループ データ: グローバル管理者、特権ロール管理者、グループ管理者
    • アプリケーション/アプリ ロールの割り当て: グローバル管理者、特権ロール管理者、アプリケーション管理者、クラウド アプリケーション管理者
  • Microsoft Graph 経由で Microsoft Entra オブジェクトを取得できるようにするため、Microsoft Graph PowerShell に同意する必要があります。 このチュートリアルの例では、委任された User.Read.All、Group.Read.All、Application.Read.All、Directory.Read.All アクセス許可が必要です。 サインインしたユーザーを使用せずに自動化でデータを取得する場合は、代わりに該当するアプリケーション アクセス許可の付与に同意します。 詳細については、「Microsoft Graph のアクセス許可のリファレンス」を参照してください。 これらのアクセス許可の Microsoft Graph PowerShell への付与にまだ同意していない場合は、この同意の操作を実行するためにグローバル管理者である必要があります。
  • このチュートリアルでは、カスタム セキュリティ属性については説明しません。 既定では、グローバル管理者およびその他の管理者のロールには、Microsoft Entra ユーザーからカスタム セキュリティ属性を読み取るためのアクセス許可は含まれていません。 カスタム セキュリティ属性を取得する場合は、さらに多くのロールとアクセス許可が必要になる場合があります。
  • Microsoft Graph PowerShell がインストールされているコンピューターで、ファイル システム ディレクトリへの書き込みアクセス権があることを確認します。 ここに、必要な Microsoft Graph PowerShell モジュールをインストールし、エクスポートされた Microsoft Entra データが保存されます。
  • Azure Data Explorer にそのデータを統合する場合は、Microsoft Entra 以外の他のデータ ソースからデータを取得するアクセス許可があることを確認してください。

1: Azure Data Explorer を設定する

Azure Data Explorer を以前に使用したことがない場合は、まずこれを設定する必要があります。 Azure サブスクリプションまたはクレジット カードなしで作成できる無料のクラスター、または Azure サブスクリプションが必要な完全なクラスターを作成できます。 開始するには、「クイック スタート: Azure Data Explorer クラスターとデータベースを作成する」を参照してください。

2: PowerShell を使用して Microsoft Entra ID データを抽出する

このセクションでは、Microsoft Graph PowerShell モジュールをインストールし、PowerShell で、Microsoft Graph に接続して Microsoft Entra ID データを抽出します。

このシナリオで組織が初めてこれらのモジュールを使用する場合は、Microsoft Graph PowerShell がテナントで使用するための同意を付与できるように、グローバル管理者ロールである必要があります。 後続のインタラクションでは、低権限のロールを使用できます。

  1. PowerShell を開きます。
  2. インストールされていない Microsoft Graph PowerShell モジュールがある場合は、必要な Microsoft Graph モジュールをインストールします。 チュートリアルのこのセクションには、Microsoft.Graph.AuthenticationMicrosoft.Graph.UsersMicrosoft.Graph.GroupsMicrosoft.Graph.ApplicationsMicrosoft.Graph.DirectoryObjects の各モジュールが必要です。 これらのモジュールが既にインストールされている場合は、次の手順に進みます。
   $modules = @('Microsoft.Graph.Users', 'Microsoft.Graph.Groups', 'Microsoft.Graph.Applications', 'Microsoft.Graph.DirectoryObjects') 
   foreach ($module in $modules) { 
   Install-Module -Name $module -Scope CurrentUser -AllowClobber -Force
   } 
  1. モジュールを現在の PowerShell セッションにインポートします。
  $modules = @('Microsoft.Graph.Users', 'Microsoft.Graph.Groups', 'Microsoft.Graph.Applications', 'Microsoft.Graph.DirectoryObjects') 
  foreach ($module in $modules) { 
  Import-Module -Name $module 
  } 
  1. Microsoft Graph に接続します。 このチュートリアルのセクションでは、ユーザー、グループ、アプリケーションの読み取り方法を説明します。そのため、User.Read.AllGroup.Read.AllApplication.Read.AllDirectory.Read.All のアクセス許可スコープが必要です。 アクセス許可の詳細については、Microsoft Graph のアクセス許可リファレンスをご覧ください。
  Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All", "Application.Read.All", "Directory.Read.All" -ContextScope Process -NoWelcome

このコマンドを実行すると、Microsoft Entra の資格情報でサインインするよう求められます。 サインイン後、初めて接続する場合や新しいアクセス許可が必要な場合は、必要なアクセス許可に同意する必要がある場合があります。

Azure Data Explorer でカスタム レポートを作成するために必要な Microsoft Entra ID データを抽出するための PowerShell クエリ

次のクエリは、PowerShell を使用して Microsoft Graph から Microsoft Entra ID データを抽出し、そのデータを JSON ファイルにエクスポートして、その後のセクション 3 で Azure Data Explorer にインポートします。 この種類のデータを使用してレポートを生成することについて、以下のような複数のシナリオが考えられます。

  • ある監査担当者は、10 個のグループのグループ メンバーを、メンバーの部署別に一覧表示するレポートを表示したいと考えます。
  • ある監査担当者は、2 つの日付の間にアプリケーションにアクセスしたすべてのユーザーのレポートを表示したいと考えます。

また、Microsoft Entra 以外のソースから Azure Data Explorer にデータをインポートすることもできます。 これにより、次のようなシナリオが可能になります。

  • 管理者が、Microsoft Entra ID からアプリケーションに追加されたすべてのユーザーと、SQL データベースなどのアプリケーション独自のレポジトリにおけるそれらのユーザーのアクセス権を表示したい場合。

このタイプのレポートは、Microsoft Entra ID に組み込まれていません。 ただし、Entra からデータを抽出し、Azure Data Explorer でカスタム クエリを使用してそれらを組み合わせることで、これらのレポートを自分で作成できます。 この方法については、このチュートリアルの後ほど、他のソースからのデータの取り込みのセクションで説明します。

このチュートリアルでは、Microsoft Entra ID のデータを以下の領域から抽出します。

  • 表示名、UPN、ジョブの詳細などのユーザー情報
  • メンバーシップを含むグループ情報
  • アプリケーションとアプリケーションロールの割り当て

このデータ セットを使用すると、アプリケーションへのアクセス権が与えられたユーザー、そのアプリケーション ロールの情報、関連する時間枠に関する幅広いクエリを実行できます。 これらはサンプル クエリであり、データと要件は、ユーザーのニーズに応じてここに示すものと異なることに注意してください。

Note

大規模なテナントでは、Microsoft Graph モジュールによって処理されるスロットリング/429 エラーが発生することがあります。 Azure Data Explorer では、ファイルのアップロード サイズが制限される場合もあります。

これらの PowerShell スクリプトでは、Microsoft Entra オブジェクトから選択したプロパティを JSON ファイルにエクスポートします。 これらのエクスポートされたプロパティのデータは、Azure Data Explorer でカスタム レポートを生成するために使用されます。 これらの例には、以下の特定のプロパティが含まれています。Azure Data Explorer で作成できるレポートの種類を説明するためにこのデータを使用しているためです。 お客様の具体的なレポートのニーズは、おそらくここに示されている内容とは異なる可能性がありますので、レポートに表示したい特定のプロパティをこれらのスクリプトに含める必要があります。 ただし、スクリプトの作成は、ここで示したのと同じパターンに従って行うことができます。

スナップショットの日付を選択する

JSON ファイル内のデータを特定の日付で識別する、ハードコードされたスナップショット日付が含まれています。これにより、Azure Data Explorer で長期間にわたって類似したデータ セットを追跡できるようになります。 スナップショット日付は、2 つのスナップショット日付間のデータの変更を比較する場合にも役立ちます。

$SnapshotDate = Get-Date -AsUTC -Format "yyyy-MM-dd"

Entra ユーザー データを取得する

このスクリプトにより、Entra ユーザー オブジェクトから選択したプロパティが JSON ファイルにエクスポートされます。 このデータとその他の JSON ファイルからのデータを、このチュートリアルの次のセクションで Azure Data Explorer にインポートします。

  function Export-EntraUsersToJson { 

  # Define a hash table for property mappings 
   $propertyMappings = @{ 
    "Id" = "ObjectID" 
    "DisplayName" = "DisplayName" 
    "UserPrincipalName" = "UserPrincipalName" 
    "EmployeeId" = "EmployeeId" 
    "UserType" = "UserType" 
    "CreatedDateTime" = "CreatedDateTime" 
    "JobTitle" = "JobTitle" 
    "Department" = "Department" 
    "AccountEnabled" = "AccountEnabled" 

   # Add custom properties as needed 
    "custom_extension" = "CustomExtension" 
   } 
  # Retrieve users with specified properties and create custom objects directly 
   $users = Get-MgUser -Select ($propertyMappings.Keys) -All | ForEach-Object { 
      $userObject = @{} 
      foreach ($key in $propertyMappings.Keys) { 
        if ($key -eq "CreatedDateTime") { 
          # Convert date string directly to DateTime and format it 
          $date = [datetime]::Parse($_.$key) 
          $userObject[$propertyMappings[$key]] = $date.ToString("yyyy-MM-dd") 
        } else { 
          $userObject[$propertyMappings[$key]] = $_.$key 
        } 
      } 
      # Additional properties or transformations 
      $userObject["SnapshotDate"] = $SnapshotDate
      [pscustomobject]$userObject 
    } 
    # Convert the user data to JSON and save it to a file 
    $users | ConvertTo-Json -Depth 2 | Set-Content ".\EntraUsers.json" 
  } 
  # Execute the function 
  Export-EntraUsersToJson 

グループ データを取得する

Azure Data Explorer でカスタム ビューを作成するために使用する、グループ名と ID を含む JSON ファイルを生成します。 このサンプルにはすべてのグループが含まれていますが、必要に応じて追加のフィルター処理を含めることができます。 特定のグループのみを含めるようにフィルター処理する場合は、入れ子になったグループを確認するロジックをスクリプトに含められます。

    # Get all groups and select Id and DisplayName 
    $groups = Get-MgGroup -All | Select-Object Id,DisplayName 
    # Export the groups to a JSON file 
    $groups | ConvertTo-Json | Set-Content ".\EntraGroups.json" 

グループ メンバーシップ データを取得する

Azure Data Explorer でカスタム ビューを作成するために使用される、グループ メンバーシップを含めた JSON ファイルを生成します。 このサンプルにはすべてのグループが含まれていますが、必要に応じて追加のフィルター処理を含めることができます。

    # Retrieve all groups from Microsoft Entra (Azure AD) 
    $groups = Get-MgGroup -All 
    # Initialize an array to store results 
    $results = @() 
    # Iterate over each group 
    foreach ($group in $groups) { 
      # Extract the group ID 
      $groupId = $group.Id 
      # Get members of the current group and select their IDs 
      $members = Get-MgGroupMember -GroupId $groupId | Select-Object -ExpandProperty Id 
      # Add a custom object with group ID and member IDs to the results array 
      $results += [PSCustomObject]@{ 
        GroupId = $groupId 
        Members = $members 
        SnapshotDate = $SnapshotDate
      } 
      # Pause for a short time to avoid rate limits 
      Start-Sleep -Milliseconds 200 
    } 
    # Convert the results array to JSON format and save it to a file 
    $results | ConvertTo-Json | Set-Content "EntraGroupMembership.json" 

アプリケーション データとサービス プリンシパル データを取得する

テナント内のすべてのアプリケーションと対応するサービス プリンシパルを含む JSON ファイルを生成します。 このデータをこのチュートリアルの次のセクションで Azure Data Explorer にインポートし、このデータに基づいてアプリケーションに関連するカスタム レポートを生成できるようにします。

    # Fetch applications and their corresponding service principals, then export to JSON 
    Get-MgApplication -All | ForEach-Object { 
      $app = $_ 
      $sp = Get-MgServicePrincipal -Filter "appId eq '$($app.AppId)'" 
      [pscustomobject]@{ 
        Name        = $app.DisplayName 
        ApplicationId   = $app.AppId 
        ServicePrincipalId = $sp.Id 
        SnapshotDate = $SnapshotDate
      } 
    } | ConvertTo-Json -Depth 10 | Set-Content "Applications.json" 

AppRole データを取得する

Microsoft Entra のエンタープライズ アプリのすべてのアプリ ロールの JSON ファイルを生成します。 Azure Data Explorer にインポートしたら、このデータを利用して、ユーザーのアプリ ロール割り当てに関するレポートを生成します。

    # Get a list of all applications, handle pagination manually if necessary 
    $apps = Get-MgApplication -All 
    # Loop through each application to gather the desired information 
    $results = foreach ($app in $apps) { 
      # Get the service principal for the application using its appId 
      $spFilter = "appId eq '$($app.AppId)'" 
      $sp = Get-MgServicePrincipal -Filter $spFilter | Select-Object -First 1 
      # Process AppRoles, if any, for the application 
      $appRoles = if ($app.AppRoles) { 
        $app.AppRoles | Where-Object { $_.AllowedMemberTypes -contains "User" } | 
        Select-Object Id, Value, DisplayName 
      } 
      # Construct a custom object with application and service principal details 
      [PSCustomObject]@{ 
        ApplicationId    = $app.AppId 
        DisplayName     = $app.DisplayName 
        ServicePrincipalId = $sp.Id 
        AppRoles      = $appRoles 
        SnapshotDate = $SnapshotDate
      } 
    } 
    # Export the results to a JSON file 
    $results | ConvertTo-Json -Depth 4 | Out-File 'AppRoles.json' 

AppRole の割り当てデータを取得する

テナント内のユーザーのすべてのアプリ ロール割り当ての JSON ファイルを生成します。

    $users = Get-MgUser -All 
    $result = @() 
    foreach ($user in $users) { 
      Get-MgUserAppRoleAssignment -UserId $user.Id | ForEach-Object { 
        # Use the same date formatting approach 
        $createdDateTime = $_.CreatedDateTime -replace "\\/Date\((\d+)\)\\/", '$1' 
        # Convert the milliseconds timestamp to a readable date format if needed 
        $result += [PSCustomObject]@{ 
          AppRoleId      = $_.AppRoleId 
          CreatedDateTime   = $createdDateTime 
          PrincipalDisplayName = $_.PrincipalDisplayName 
          PrincipalId     = $_.PrincipalId 
          ResourceDisplayName = $_.ResourceDisplayName 
          ResourceId      = $_.ResourceId 
          SnapshotDate     = $SnapshotDate
        } 
      } 
    } 
    $result | ConvertTo-Json -Depth 10 | Out-File "AppRoleAssignments.json" 

3: テーブルを作成し、Microsoft Entra ID からのデータを含む JSON ファイルを Azure Data Explorer にインポートする

このセクションでは、Microsoft Entra ID サービスの新規作成した JSON ファイルを Azure Data Explorer のテーブルとしてインポートし、さらに分析を行います。 Azure Data Explorer Web UI を使用した最初のインポートでは、Web UI が各 JSON ファイルから提案するスキーマに基づいてテーブルを作成します。

この記事の最初のセクションで説明されているように、Azure Data Explorer クラスターまたは無料クラスターにデータベースを設定したら、そのデータベースに移動します。

  1. Azure Data Explorer Web UI にサインインします。
  2. 左側のメニューから、[クエリ] を選択します。

次に、エクスポートした各 JSON ファイルに対して、以下の手順に従ってエクスポートしたデータを新しいテーブルとしてその Azure Data Explorer データベースに取り込みます。

  1. データを取り込みたいデータベースのデータベース名を右クリックします。 [データの取得] を選択します。

    データベースを右クリックし、[オプションの取得] ダイアログが開いている [クエリ] タブのスクリーンショット。

  2. 使用可能なリストからデータ ソースを選択します。 このチュートリアルでは、ローカル ファイルからデータを取り込みます。

  3. [+ 新規テーブル] を選択し、インポートする JSON ファイルの名前に基づいてテーブル名を入力します。たとえば、EntraUsers.json をインポートする場合は、テーブル名を EntraUsers とします。 最初のインポート後、テーブルは既に存在しているので、その後のインポートのターゲット テーブルとして選択できます。

  4. [ファイルの参照] を選択し、JSON ファイルを選択して、[次へ] を選択します。

  5. Azure Data Explorer によって自動的にスキーマが検出され、[検査] タブにプレビューが表示されます。[完了] を選択してテーブルを作成し、そのファイルからデータをインポートします。 データが取り込まれたら、[閉じる] をクリックします。

  6. 前のセクションで生成した各 JSON ファイルについて、上記の各手順を繰り返します。

これらの手順の最後には、データベースにテーブル EntraUsersEntraGroupsEntraGroupMembershipApplicationsAppRoles、および AppRoleAssignments があります。

4: PowerShell を使用して Microsoft Entra ID ガバナンス データを抽出する

このセクションでは、PowerShell を使用して Microsoft Entra ID ガバナンス サービスからデータを抽出します。 Microsoft Entra ID Governance、Microsoft Entra ID P2、または Microsoft Entra Suite をお持ちでない場合は、Azure Data Explorer を使用してカスタム レポートを作成 セクションに進んでください。

この場合、Microsoft Entra ID ガバナンス データを抽出するには、Microsoft Graph PowerShell モジュールをインストールする必要がある場合があります。 このシナリオで組織が初めてこれらのモジュールを使用する場合は、Microsoft Graph PowerShell がテナントで使用するための同意を付与できるように、グローバル管理者ロールである必要があります。 後続のインタラクションでは、低権限のロールを使用できます。

  1. PowerShell を開きます。
  2. インストールされていない Microsoft Graph PowerShell モジュールがある場合は、必要な Microsoft Graph モジュールをインストールします。 チュートリアルのこのセクションでは、次のモジュールが必要です: Microsoft.Graph.Identity.Governance。 これらのモジュールが既にインストールされている場合は、次の手順に進みます。
   $modules = @('Microsoft.Graph.Identity.Governance')
   foreach ($module in $modules) {
   Install-Module -Name $module -Scope CurrentUser -AllowClobber -Force
   }
  1. モジュールを現在の PowerShell セッションにインポートします。
  $modules = @('Microsoft.Graph.Identity.Governance')
  foreach ($module in $modules) {
  Import-Module -Name $module
  } 
  1. Microsoft Graph に接続します。 このセクションでは、エンタイトルメント管理とアクセス レビューからのデータの取得方法を説明します。そのため、AccessReview.Read.AllEntitlementManagement.Read.All のアクセス許可スコープが必要です。 PIM やライフサイクル ワークフローなど、その他のレポートのユース ケースについては、必要な権限を指定して Scopes パラメーターを更新します。 アクセス許可の詳細については、Microsoft Graph のアクセス許可リファレンスをご覧ください。
  Connect-MgGraph -Scopes "AccessReview.Read.All, EntitlementManagement.Read.All" -ContextScope Process -NoWelcome

このコマンドを実行すると、Microsoft Entra の資格情報でサインインするよう求められます。 サインイン後、初めて接続する場合や新しいアクセス許可が必要な場合は、必要なアクセス許可に同意する必要がある場合があります。

Azure Data Explorer でカスタム レポートを作成するために必要な Microsoft Entra ID ガバナンス データを抽出するための PowerShell クエリ

PowerShell のクエリを使用して、Microsoft Graph から Microsoft Entra ID ガバナンス データを抽出し、そのデータを JSON ファイルにエクスポートします。これは、次のセクションで Azure Data Explorer にインポートされます。 この種類のデータを使用してレポートを生成することについて、以下のような複数のシナリオが考えられます。

  • 過去のアクセス レビューに関するレポート
  • エンタイトルメント管理による割り当てに関するレポート

アクセスレビューのスケジュール定義データを取得する

アクセス レビュー定義名と ID を含む JSON ファイルを生成します。これは、Azure Data Explorer でカスタム ビューを作成する際に使用します。 このサンプルにはすべてのアクセス レビューが含まれていますが、必要に応じて追加のフィルター処理を含めることができます。 詳細については、フィルター クエリ パラメーターの使用をご覧ください。

   $allsched = Get-MgIdentityGovernanceAccessReviewDefinition -All
   $definitions = @()
   # Iterate over each definition
   foreach ($definition in $allsched) {
      $definitions += [PSCustomObject]@{
         Id = $definition.Id
         DisplayName = $definition.DisplayName
         SnapshotDate = $SnapshotDate
      }
   }
   $definitions | ConvertTo-Json -Depth 10 | Set-Content "EntraAccessReviewDefinitions.json"

アクセス レビュー インスタンス データを取得する

PowerShell を使用して、すべての Access Review の定義、インスタンス、および決定を構造化フォルダー形式にエクスポートするには、Microsoft Graph API を利用できます。 この方法により、指定したフォルダー構造に合わせてデータが階層的に編成されます。

開始する前に、次の点に注意してください。

  • Microsoft Graph の Access Reviews データにアクセスするために必要なアクセス許可があることを確認します。
  • データの量によっては、スクリプトの実行時間が異なる場合があります。 プロセスを監視し、必要に応じてパラメーターを調整します。
  1. Export_Access_Reviews.ps1 スクリプトをダウンロードし、ローカルに保存します。
  2. エクスプローラーでスクリプトのブロックを解除し、PowerShell で実行できるようにします。
  3. 次のコマンドを実行すると、すべてのデータが ReviewInstancesReviewInstanceDecisionItemsReviewInstanceContactedReviewersの 3 つのサブフォルダーに出力されます。
 .\ExportAccessReviews.ps1 -InstanceStartDate "11/15/2024" -InstanceEndDate "12/15/2024" -ExportFolder "C:\AccessReviewsExport\11_15_to_12_15" 

エンタイトルメント管理アクセス パッケージ データを取得する

Azure Data Explorer でカスタム ビューを作成するために使用する、アクセス パッケージ名と ID を含む JSON ファイルを生成します。 このサンプルにはすべてのアクセス パッケージが含まれていますが、必要に応じて追加のフィルター処理を含めることができます。

   $accesspackages1 = Get-MgEntitlementManagementAccessPackage -All
   $accesspackages2 = @()
   # Iterate over each access package
   foreach ($accesspackage in $accesspackages1) {
      $accesspackages2 += [PSCustomObject]@{
         Id = $accesspackage.Id
         DisplayName = $accesspackage.DisplayName
         SnapshotDate = $SnapshotDate
      }
   }
   $accesspackages2 | ConvertTo-Json -Depth 10 | Set-Content "EntraAccessPackages.json"

エンタイトルメント管理アクセス パッケージの割り当てデータを取得する

Azure Data Explorer でカスタム ビューを作成するために使用する、パッケージへのアクセス権を含む JSON ファイルを生成します。 このサンプルには、配信されるすべての割り当てが含まれていますが、必要に応じて追加のフィルター処理を含めることができます。

   $apassignments1 = Get-MgEntitlementManagementAssignment -ExpandProperty target,accessPackage -filter "state eq 'Delivered'" -all
   $apassignments2 = @()
   # Iterate over each access package assignment
   foreach ($assignment in $apassignments1) {
      $apassignments2 += [PSCustomObject]@{
         Id = $assignment.Id
         ScheduleStartDateTime = $assignment.Schedule.StartDateTime -replace "\\/Date\((\d+)\)\\/", '$1' 
         AccessPackageId = $assignment.AccessPackage.Id
         AccessPackageDisplayName = $assignment.AccessPackage.DisplayName
         TargetId = $assignment.Target.Id
         TargetDisplayName = $assignment.Target.DisplayName
         TargetEmail = $assignment.Target.Email
         TargetObjectId = $assignment.Target.ObjectId
         TargetPrincipalName = $assignment.Target.PrincipalName
         TargetSubjectType = $assignment.Target.SubjectType
         SnapshotDate = $SnapshotDate
      }
   }
   $apassignments2 | ConvertTo-Json -Depth 10 | Set-Content "EntraAccessPackageAssignments.json"

5: テーブルを作成し、Microsoft Entra ID ガバナンスのデータを含む JSON ファイルを Azure Data Explorer にインポートする

このセクションでは、Microsoft Entra ID ガバナンス サービス用に新たに作成した JSON ファイルを、Microsoft Entra ID サービス用に既にインポートされているデータとともに Azure Data Explorer にインポートし、さらなる分析を行います。 Azure Data Explorer Web UI を使用した最初のインポートでは、Web UI が各 JSON ファイルから提案するスキーマに基づいてテーブルを作成します。

Azure Data Explorer クラスターまたは無料クラスターで、Microsoft Entra ID データを保持するデータベースに移動します。

  1. Azure Data Explorer Web UI にサインインします。
  2. 左側のメニューから、[クエリ] を選択します。

次に、前のセクションでエクスポートした各 JSON ファイルに対して以下の手順を実行し、エクスポートしたデータを新しいテーブルとして Azure Data Explorer データベースに取り込みます。

  1. データを取り込みたいデータベースのデータベース名を右クリックします。 [データの取得] を選択します。

    データベースを右クリックし、[オプションの取得] ダイアログが開いている [クエリ] タブのスクリーンショット。

  2. 使用可能なリストからデータ ソースを選択します。 このチュートリアルでは、ローカル ファイルからデータを取り込みます。

  3. [+ 新規テーブル] を選択し、インポートする JSON ファイルの名前に基づいてテーブル名を入力します。最初のインポート後、テーブルは既に存在しているので、そのテーブルをその後のインポートのターゲット テーブルとして選択できます。

  4. [ファイルの参照] を選択し、JSON ファイルを選択して、[次へ] を選択します。

  5. Azure Data Explorer によって自動的にスキーマが検出され、[検査] タブにプレビューが表示されます。[完了] を選択してテーブルを作成し、そのファイルからデータをインポートします。 データが取り込まれたら、[閉じる] をクリックします。

  6. 各フォルダーについて、前のセクションで生成した各 JSON ファイルについて、上記の各手順を繰り返します。

  7. フォルダーに多数のファイルがある場合は、lightingest を使用して、テーブルの作成後に残りのファイルをインポートできます。

これらの手順の最後には、セクション 3 で作成したテーブルに加えて、データベースにテーブル EntraAccessReviewDefinitionsEntraAccessPackagesEntraAccessPackageAssignmentsReviewInstancesReviewInstanceDecisionItemsReviewInstanceContactedReviewers があります。

6: Azure Data Explorer を使用してカスタム レポートを作成する

Azure Data Explorer でデータが利用可能になったので、ビジネス要件に基づくカスタマイズされたレポートの作成を開始する準備が整いました。

Azure Data Explorer は、高度にスケーラブルで柔軟な強力なデータ分析ツールであり、カスタマイズされたユーザー アクセス レポートを生成するための理想的な環境を提供します。 Azure Data Explorer では、Kusto 照会言語 (KQL) が使用されます。

  1. Azure Data Explorer Web UI にサインインします。
  2. 左側のメニューから、[クエリ] を選択します。

次のクエリでは、一般的なレポートの例を示しますが、ニーズに合わせてこれらのレポートをカスタマイズし、追加のレポートを作成できます。

[エクスポート] タブを選択し、[Excel で開く] を選択することで、Excel でレポートを表示することもできます。

例 1: 特定のスナップショット日付の直接割り当て用とグループ割り当て用のアプリ ロールの割り当てを生成する

このレポートでは、ターゲット アプリに対するアクセス許可を得たユーザー、許可の種類、その日時を表示するビューを提供します。これは、組織内のセキュリティ監査、コンプライアンス検証、アクセス パターンの理解に使用できます。

このクエリは、Microsoft Entra AD 内の特定のアプリケーションを対象とし、特定の日付時点でのロールの割り当てを分析します。 このクエリは、直接およびグループベースのロールの割り当ての両方を取得し、このデータを EntraUsers テーブルのユーザー詳細と AppRoles テーブルのロール情報と統合します。 次のクエリでは、targetSnapshotDate を、データの読み込み時に使用された snapshotDate 値に設定します。

/// Define constants 
let targetServicePrincipalId = "<your service principal-id>"; // Target Service Principal ID 
let targetSnapshotDate = datetime("2024-01-13"); // Target Snapshot Date for the data 

// Extract role assignments for the target Service Principal and Snapshot Date 
let roleAssignments = AppRoleAssignments 
    | where ResourceId == targetServicePrincipalId and startofday(SnapshotDate) == targetSnapshotDate 
    | extend AppRoleIdStr = tostring(AppRoleId); // Convert AppRoleId to string for easier comparison 

// Prepare user data from EntraUsers table 
let users = EntraUsers 
    | project ObjectID, UserPrincipalName, DisplayName, ObjectIDStr = tostring(ObjectID); // Include ObjectID as string for joining 

// Prepare role data from AppRoles table 
let roles = AppRoles 
    | mvexpand AppRoles // Expand AppRoles to handle multiple roles 
    | extend RoleName = AppRoles.DisplayName, RoleId = tostring(AppRoles.Id) // Extract Role Name and ID 
    | project RoleId, RoleName; 
// Process direct assignments 
let directAssignments = roleAssignments 
    | join kind=inner users on $left.PrincipalId == $right.ObjectID // Join with EntraUsers on PrincipalId 
    | join kind=inner roles on $left.AppRoleIdStr == $right.RoleId // Join with roles to get Role Names 
    | project UserPrincipalName, DisplayName, CreatedDateTime, RoleName, AssignmentType = "Direct", SnapshotDate; 

// Process group-based assignments 

let groupAssignments = roleAssignments 
    | join kind=inner EntraGroupMembership on $left.PrincipalId == $right.GroupId // Join with Group Membership 
    | mvexpand Members // Expand group members 
    | extend MembersStr = tostring(Members) // Convert member ID to string 
    | distinct MembersStr, CreatedDateTime, AppRoleIdStr, SnapshotDate // Get distinct values 
    | join kind=inner users on $left.MembersStr == $right.ObjectIDStr // Join with EntraUsers for user details 
    | join kind=inner roles on $left.AppRoleIdStr == $right.RoleId // Join with roles for role names 
    | project UserPrincipalName, DisplayName, CreatedDateTime, RoleName, AssignmentType = "Group", SnapshotDate; 

// Combine results from direct and group-based assignments 
directAssignments 
| union groupAssignments 

例 2: これら 2 つの日付の間にアプリへのアクセス許可を持ったユーザーを示す Entra データを含む基本的な監査担当者レポートを作成する

このレポートでは、2 つの日付の間にターゲット アプリのアクセス許可を得たユーザーと許可の種類のビューを提供します。これはセキュリティ監査、コンプライアンス検証、組織内のアクセス パターンの理解に使用できます。

このクエリは、Microsoft Entra ID 内の特定のアプリケーションを対象とし、2 つの日付間のロールの割り当てを分析します。 このクエリは、AppRoleAssignments テーブルから直接ロール割り当てを取得し、このデータを EntraUsers テーブルのユーザー詳細と AppRoles テーブルの役割情報とマージします。

// Set the date range and service principal ID for the query 
let startDate = datetime('2024-01-01'); 
let endDate = datetime('2024-03-14'); 
let servicePrincipalId = "<your service principal-id>"; 

// Query AppRoleAssignments for the specified service principal within the date range 
AppRoleAssignments 
| where ResourceId == servicePrincipalId and 
    todatetime(CreatedDateTime) between (startDate .. endDate) 

// Extend AppRoleId to a string for joining 
| extend AppRoleIdStr = tostring(AppRoleId) 

// Project the necessary fields for the join with EntraUsers and AppRoles 
| project PrincipalId, AppRoleIdStr, CreatedDateTime 

// Join with EntraUsers to get user details 
| join kind=inner (EntraUsers | project UserPrincipalName, DisplayName, ObjectID) on $left.PrincipalId == $right.ObjectID 

// Join with AppRoles to get the role display names 
| join kind=inner ( 
  AppRoles | mvexpand AppRoles | project RoleIdStr = tostring(AppRoles.Id), RoleDisplayName = tostring(AppRoles.DisplayName) 
) on $left.AppRoleIdStr == $right.RoleIdStr 

// Final projection of the report with the current date and time 
| project UserPrincipalName, DisplayName, RoleDisplayName, CreatedDateTime, ReportDate = now() 

例 3: 2 つのデータ スナップショットの日付の間にアプリに追加されたユーザーを取得する

これらのレポートには、2 つの日付の間にターゲット アプリケーションにアプリ ロールの割り当てが与えられたユーザーのビューが表示されます。 これらのレポートは、時間の経過に伴うアプリ アクセスの変化を追跡するために使用できます。

このクエリは、Microsoft Entra ID 内の特定のアプリケーションを対象とし、開始日と終了日の間のロールの割り当てに対する変更を対象とします。

// Define the date range and service principal ID for the query 

let startDate = datetime("2024-03-01"); 
let endDate = datetime("2024-03-14"); 
let servicePrincipalId = "<your service principal-id>"; 
let earlierDate = startDate; // Update this to your specific earlier date 

AppRoleAssignments 
| where SnapshotDate < endDate and ResourceId == servicePrincipalId
| project PrincipalId, AppRoleId2 = tostring(AppRoleId), CreatedDateTime 
| join kind=anti ( 
    AppRoleAssignments 
    | where SnapshotDate < earlierDate and ResourceId == servicePrincipalId 
    | project PrincipalId, AppRoleId1 = tostring(AppRoleId) 
) on PrincipalId 
| join kind=inner (EntraUsers) on $left.PrincipalId == $right.ObjectID 
| join kind=inner (AppRoles 
                   | mvexpand AppRoles 
                   | project AppRoleId=tostring(AppRoles.Id), RoleDisplayName=tostring(AppRoles.DisplayName) 
                  ) on $left.AppRoleId2 == $right.AppRoleId 
| project UserPrincipalName, DisplayName, RoleDisplayName, CreatedDateTime, PrincipalId, Change = "Added" 

例 4: アクセス レビュー

レビューの完了とタイムライン情報

データがアップロードされたら、次の Kusto クエリを使用して確認します。

  • 最後のアクセス レビュー サイクルが完了したのはいつですか? 所要時間はどのくらいでしたか?
ReviewInstances 
| summarize LastCompletedDate = max(ReviewInstanceEndDateTime),  
            ReviewDuration = datetime_diff('minute', max(ReviewInstanceEndDateTime), min(ReviewInstanceStartDateTime))  
  • アクセス レビュー プロセスは時間通り (四半期ごと、毎年など) に行われますか?
ReviewInstances 
| extend ExpectedFrequency = "Quarterly" // Replace with organization's frequency 
| summarize ReviewsCompleted = count(), LastReviewEndDate = max(ReviewInstanceEndDateTime) 
| extend CurrentDate = now(),  
         TimeSinceLastReview = datetime_diff('day', now(), LastReviewEndDate) 
| extend IsOnSchedule = iff(TimeSinceLastReview <= 90, "Yes", "No") // Assuming quarterly = 90 days  

レビューの参加とエンゲージメント

  • レビュー担当者が割り当てられたのは誰ですか?
ReviewInstanceContactedReviewers 
| project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerName = DisplayName, ReviewerUserPrincipalName = UserPrincipalName, CreatedDateTime  
  • どの校閲者が積極的に参加し、回答を提供しましたか?
ReviewInstanceDecisionItems 
| where ReviewedBy_DisplayName != "AAD Access Reviews" 
| where Decision in ("Approve", "Deny") 
| project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerName = ReviewedBy_DisplayName, 
ReviewerUserPrincipalName = ReviewedBy_UserPrincipalName, Decision, ReviewedDateTime 
| distinct AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerName, ReviewerUserPrincipalName, Decision   
  • アクセス レビュー要求に応答したレビュー担当者の割合。
let TotalReviewers = ReviewInstanceContactedReviewers 
    | summarize Total = dcount(Id) by AccessReviewDefinitionId, AccessReviewInstanceId;  

let RespondedReviewers = ReviewInstanceDecisionItems 
    | where ReviewedBy_DisplayName != "AAD Access Reviews" 
    | where ReviewedBy_Id != "00000000-0000-0000-0000-000000000000" 
    | where Decision in ("Approve", "Deny") 
    | summarize Responded = dcount(ReviewedBy_Id) by AccessReviewDefinitionId, AccessReviewInstanceId;  

TotalReviewers 
| join kind=leftouter RespondedReviewers on AccessReviewDefinitionId, AccessReviewInstanceId 
| extend Responded = coalesce(Responded, 0)  // Replace null with 0 for Responded 
| extend NotResponded = Total - Responded   // Calculate the number of non-responders 
| extend ResponsePercentage = (Responded * 100.0) / Total  // Percentage of those who responded 
| extend NonResponsePercentage = (NotResponded * 100.0) / Total  // Percentage of those who didn’t respond 
| project AccessReviewDefinitionId, AccessReviewInstanceId, Total, Responded, ResponsePercentage, NotResponded, NonResponsePercentage  
  • 各校閲者がタスクを完了したのはいつですか?
ReviewInstanceDecisionItems 
| where Decision in ("Approve", "Deny") 
| project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerName = ReviewedBy_DisplayName, ReviewerUserPrincipalName = ReviewedBy_UserPrincipalName, ReviewedDateTime  
  • どの校閲者が決定を下さなかったのですか?
let AllReviewers = ReviewInstanceContactedReviewers 
    | project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerId = Id, ReviewerUserPrincipalName = UserPrincipalName, ReviewerName = DisplayName; 
  
let ActiveReviewers = ReviewInstanceDecisionItems 
    | where Decision in ("Approve", "Deny") 
    | where ReviewedBy_DisplayName != "AAD Access Reviews" 
    | where ReviewedBy_Id != "00000000-0000-0000-0000-000000000000" 
    | summarize ActiveReviewers = make_set(ReviewedBy_Id) by AccessReviewDefinitionId, AccessReviewInstanceId; 

AllReviewers 
| extend ReviewerId = tostring(ReviewerId)  // Ensure ReviewerId is a string 
| join kind=leftanti ( 
    ActiveReviewers 
    | mv-expand ActiveReviewers 
    | extend ActiveReviewers = tostring(ActiveReviewers)  // Cast ActiveReviewers to a string 
) on $left.ReviewerId == $right.ActiveReviewers 
| project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerUserPrincipalName, ReviewerName 
  • 対話しなかった校閲者の割合。
let TotalReviewers = ReviewInstanceContactedReviewers 
    | summarize Total = dcount(Id) by AccessReviewDefinitionId, AccessReviewInstanceId; 

let RespondedReviewers = ReviewInstanceDecisionItems 
    | where ReviewedBy_DisplayName != "AAD Access Reviews" 
    | where ReviewedBy_Id != "00000000-0000-0000-0000-000000000000" 
    | where Decision in ("Approve", "Deny") 
    | summarize Responded = dcount(ReviewedBy_Id) by AccessReviewDefinitionId, AccessReviewInstanceId; 
  
TotalReviewers 
| join kind=leftouter RespondedReviewers on AccessReviewDefinitionId, AccessReviewInstanceId 
| extend Responded = coalesce(Responded, 0)  // Replace null with 0 for Responded 
| extend NotResponded = Total - Responded   // Calculate the number of non-responders 
| extend ResponsePercentage = (Responded * 100.0) / Total  // Percentage of those who responded 
| extend NonResponsePercentage = (NotResponded * 100.0) / Total  // Percentage of those who didn’t respond 
| project AccessReviewDefinitionId, AccessReviewInstanceId, Total, Responded, ResponsePercentage, NotResponded, NonResponsePercentage  
  • 応答のないレビュー担当者に対してリマインダーがトリガーされましたか? 決定は保留中ですか?
// Step 1: Get the list of all reviewers 
let TotalReviewers = ReviewInstanceContactedReviewers 
    | project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerId = Id, ReviewerUserPrincipalName = UserPrincipalName, ReviewerName = DisplayName; 
 
// Step 2: Get the list of reviewers who have responded 
let RespondedReviewers = ReviewInstanceDecisionItems 
    | where ReviewedBy_DisplayName != "AAD Access Reviews" 
    | where ReviewedBy_Id != "00000000-0000-0000-0000-000000000000" 
    | where Decision in ("Approve", "Deny") 
    | project AccessReviewDefinitionId, AccessReviewInstanceId, RespondedReviewerId = ReviewedBy_Id; 

// Step 3: Get the list of review instances 
let ReviewInstancesWithDetails = ReviewInstances 
    | project AccessReviewDefinitionId = ReviewDefinitionId,  
              AccessReviewInstanceId = ReviewInstanceId,  
              RemindersSent = ReviewDefinitionSettings_ReminderNotificationsEnabled,  
              StartDate = todatetime(ReviewInstanceStartDateTime),  
              EndDate = todatetime(ReviewInstanceEndDateTime) 
    | extend 
              ReminderSentDate = iif(RemindersSent, StartDate + (EndDate - StartDate) / 2, datetime(null)); 

// Step 4: Identify non-responsive reviewers and join with review instance details 
TotalReviewers 
| join kind=leftouter (ReviewInstancesWithDetails) on AccessReviewDefinitionId, AccessReviewInstanceId 
| join kind=leftanti RespondedReviewers on $left.ReviewerId == $right.RespondedReviewerId 
| project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerUserPrincipalName, ReviewerName, RemindersSent, ReminderSentDate 

ユーザー & のアクセス変更

  • アクセス レビュー中に特定のリソースへのアクセスを失ったユーザー
ReviewInstanceDecisionItems 
| where Decision == "Deny" 
| project User = Principal_DisplayName, Resource = Resource_DisplayName, Decision, Justification 
  • ユーザーに非アクティブが原因でフラグが設定されましたか?
ReviewInstanceDecisionItems 
| where Insights contains "inactive" 
| project User = Principal_DisplayName, Resource = Resource_DisplayName, Insights, Decision 
  • アクセスの削除日とアクセスを失う理由。
ReviewInstanceDecisionItems 
| where Decision == "Deny" 
| project User = Principal_DisplayName, Resource=Resource_DisplayName, AccessRemovalDate = AppliedDateTime, Reason = Justification  
  • 意思決定を行っていないユーザー。
ReviewInstanceDecisionItems 
| where Decision == "NotReviewed" 
| project User = Principal_DisplayName, Resource=Resource_DisplayName 
  • レビュー担当者がいないレビュー。
ReviewInstances 
| join kind=leftanti ( 
    ReviewInstanceContactedReviewers 
    | summarize by AccessReviewInstanceId 
) on $left.ReviewInstanceId == $right.AccessReviewInstanceId  
  • ユーザーなしのレビュー。
ReviewInstances 
| join kind=leftanti ( 
    ReviewInstanceDecisionItems 
    | summarize by AccessReviewInstanceId 
) on $left.ReviewInstanceId == $right.AccessReviewInstanceId 

意思決定データの確認

  • 行われた決定: 承認、拒否、または変更なし。
ReviewInstanceDecisionItems 
| summarize count() by Decision 
  • アクセスが承認または拒否されたユーザーの数。
ReviewInstanceDecisionItems 
| summarize ApprovedCount = countif(Decision == "Approve"), DeniedCount = countif(Decision == "Deny") 
  • 承認の理由は文書化されましたか?
ReviewInstanceDecisionItems 
| where Decision == "Approve" and isnotempty(Justification) 
| summarize count() by ReviewedBy_DisplayName 

アクセス レビューの品質とコンプライアンスのチェック

  • 休止中のユーザーのアクセス失効は考慮されましたか?
ReviewInstanceDecisionItems 
| where Insights contains "inactive" and Decision == "Deny" 
| project User = Principal_DisplayName, Decision 
  • アクセス権が適切に削除されませんでしたか?
ReviewInstanceDecisionItems 
| where ApplyResult != "New" and ApplyResult != "AppliedSuccessfully" 
  • 校閲者は自分の決定を文書化しましたか?
ReviewInstanceDecisionItems 
| where isnotempty(Justification) 
| summarize count() by ReviewedBy_DisplayName 
  • 各ユーザーのコメントはキャプチャされましたか?
ReviewInstanceDecisionItems 
| where isnotempty(Justification) 
| project User = Principal_DisplayName, Resource = Resource_DisplayName, Comments = Justification 

     

進行中のインポートを設定する

このチュートリアルでは、レポート用に Azure Data Explorer に単一のスナップショットを追加する、1 回限りのデータ抽出、変換、読み込み (ETL) プロセスを説明します。 継続的なレポート作成や、時間の経過に伴う変更の比較を行う場合は、Microsoft Entra から Azure Data Explorer にデータを追加するプロセスを自動化し、データベースに常に最新のデータが保持されるようにすることができます。

Azure クラウド サービスである Azure Automation を使用して、Microsoft Entra ID および Microsoft Entra ID ガバナンスからデータを抽出するために必要な PowerShell スクリプトをホストすることができます。 詳細については、Azure Automation を使用して Microsoft Entra ID ガバナンス タスクを自動化するをご覧ください。

また、Azure の機能や lightingest などのコマンド ライン ツールを使用してデータを取得し、既存のテーブルにデータを設定することもできます。 詳細については、LightIngest を使用して Azure Data Explorer にデータを取り込むをご覧ください。

たとえば、現在のディレクトリにあるファイル EntraAccessPackages.json を、現在ログインしているユーザーとして EntraAccessPackages テーブルに読み込むには、次のようにします。

az login
LightIngest.exe "https://ingest-CLUSTERHOSTNAME;Fed=True" -database:"DATABASE" -table:EntraAccessPackages -sourcepath:"." -pattern:"EntraAccessPackages.json" -format:multijson -azcli:true

Azure Monitor でデータのクエリを実行する

監査、サインイン、またはその他の Microsoft Entra ログを Azure Monitor に送信する場合は、その Azure Monitor Log Analytics ワークスペースのログをクエリに組み込むことができます。 Azure Monitor と Azure Data Explorer の関係の詳細については、「Azure Data Explorer を使用した Azure Monitor でのデータのクエリの」を参照してください。

  1. Microsoft Entra 管理センターにサインインします。

  2. [診断設定 を選択します。

  3. ログを送信する Log Analytics ワークプレースを選択します。

  4. Log Analytics ワークスペースの概要で、ワークスペースのサブスクリプション ID、リソース グループ名、ワークスペース名を記録します。

  5. Azure portal にサインインします。

  6. Azure Data Explorer Web UIに移動します。

  7. Azure Data Explorer クラスターが一覧表示されていることを確認します。

  8. [+ 追加][接続] の順に選択します。

  9. Log Analytics ワークスペースの追加で説明されているように、[接続の追加] ウィンドウで、Azure Monitor Log Analytics ワークスペースのクラウド固有のホスト名、サブスクリプション ID、リソース グループ名、ワークスペース名から構成される Log Analytics ワークスペースの URL を入力します。

  10. 接続が確立されると、Log Analytics ワークスペースが、ネイティブの Azure Data Explorer クラスターと共に左側のウィンドウに表示されます。

  11. 左側のメニュー [クエリ] を選択し、Azure Data Explorer クラスターを選択します。

  12. クエリ ウィンドウで、Azure Data Explorer クエリの Microsoft Entra ログを含む Azure Monitor テーブルを参照できます。 次に例を示します。

    let CL1 = 'https://ade.loganalytics.io/subscriptions/*subscriptionid*/resourcegroups/*resourcegroupname*/providers/microsoft.operationalinsights/workspaces/*workspacename*';
    cluster(CL1).database('*workspacename*').AuditLogs | where Category == "EntitlementManagement"  and OperationName == "Fulfill access package assignment request"
    | mv-expand TargetResources | where TargetResources.type == 'AccessPackage' | project ActivityDateTime,APID = toguid(TargetResources.id)
    | join EntraAccessPackage on $left.APID == $right.Id
    | limit 100
    

他のソースからデータを取り込む

また、Azure Data Explorer で追加のテーブルを作成し、他のソースからのデータを取り込むこともできます。 上記の例や CSV ファイルと同様に、データが JSON ファイル内にある場合は、初めてファイルからデータを取得するときにテーブルを作成できます。 テーブルが作成されたら、LightIngest を使用して、JSON または CSV ファイルから Azure Data Explorer にデータを取り込むこともできます。

データ インジェストの詳細については、Azure Data Explorer データ インジェストの概要をご覧ください。

例 5: Entra からのアプリの割り当てと 2 つ目のソースを組み合わせて、2 つの日付の間にアプリケーションにアクセスしたすべてのユーザーのレポートを作成する

このレポートは、Azure Data Explorer で 2 つの別々のシステムからのデータを組み合わせてカスタム レポートを作成する方法を示します。 2 つのシステムのユーザー、ロール、その他の属性に関するデータを、分析またはレポート用に統合された形式に集計します。

この例では、UserNameNameEmployeeIdDepartmentJobTitleAppNameRole、および CreatedDateTime の列を持つ salesforceAssignments という名前のテーブルが、別のアプリケーションからデータを取り込むことによって設定されていることを前提としています。

// Define the date range and service principal ID for the query 

let startDate = datetime("2023-06-01"); 
let endDate = datetime("2024-03-13"); 
let servicePrincipalId = "<your service principal-id>"; 

// Pre-process AppRoleAssignments with specific filters and projections 
let processedAppRoleAssignments = AppRoleAssignments 
    | where ResourceId == servicePrincipalId and todatetime(CreatedDateTime) between (startDate .. endDate) 
    | extend AppRoleId = tostring(AppRoleId) 
    | project PrincipalId, AppRoleId, CreatedDateTime, ResourceDisplayName; // Exclude DeletedDateTime and keep ResourceDisplayName 

// Pre-process AppRoles to get RoleDisplayName for each role 
let processedAppRoles = AppRoles 
    | mvexpand AppRoles 
    | project AppRoleId = tostring(AppRoles.Id), RoleDisplayName = tostring(AppRoles.DisplayName); 

// Main query: Process EntraUsers by joining with processed role assignments and roles 
EntraUsers 
    | join kind=inner processedAppRoleAssignments on $left.ObjectID == $right.PrincipalId // Join with role assignments 
    | join kind=inner processedAppRoles on $left.AppRoleId == $right.AppRoleId // Join with roles to get display names 

    // Summarize to get the latest record for each unique combination of user and role attributes 
    | summarize arg_max(AccountEnabled, *) by UserPrincipalName, DisplayName, tostring(EmployeeId), Department, JobTitle, ResourceDisplayName, RoleDisplayName, CreatedDateTime 

    // Final projection of relevant fields including source indicator and report date 
    | project UserPrincipalName, DisplayName, EmployeeId=tostring(EmployeeId), Department, JobTitle, AccountEnabled=tostring(AccountEnabled), ResourceDisplayName, RoleDisplayName, CreatedDateTime, Source="EntraUsers", ReportDate = now() 

// Union with processed salesforceAssignments to create a combined report 
| union ( 
    salesforceAssignments 

    // Project fields from salesforceAssignments to align with the EntraUsers data structure 
    | project UserPrincipalName = UserName, DisplayName = Name, EmployeeId = tostring(EmployeeId), Department, JobTitle, AccountEnabled = "N/A", ResourceDisplayName = AppName, RoleDisplayName = Role, CreatedDateTime, Source = "salesforceAssignments", ReportDate = now() 
) 

次のステップ