Självstudie: Anpassade rapporter i Azure Data Explorer (ADX) med data från Microsoft Entra ID
I den här självstudien får du lära dig hur du skapar anpassade rapporter i Azure Data Explorer (ADX) med hjälp av data från Microsoft Entra-ID. Den här självstudien kompletterar andra rapporteringsalternativ som Arkiv och rapport med Azure Monitor och berättigandehantering, som fokuserar på att exportera granskningsloggdata för längre kvarhållning och analys. Som jämförelse ger export av Microsoft Entra-ID-data till Azure Data Explorer större flexibilitet för att skapa anpassade rapporter genom att tillåta dataaggregering från flera källor med massiv skalbarhet och flexibla schema- och kvarhållningsprinciper.
Den här rapporten visar hur du visar konfigurations-, användar- och åtkomsträttigheter som exporteras från Microsoft Entra tillsammans med data som exporteras från andra källor, till exempel program med SQL-databaser. Du kan sedan använda Kusto-frågespråk (KQL) för att skapa anpassade rapporter baserat på organisationens krav. Att generera dessa typer av rapporter i Azure Data Explorer kan vara särskilt användbart om du behöver behålla åtkomstdata under längre perioder, utföra ad hoc-undersökningar eller behöver köra anpassade frågor på användaråtkomstdata.
Du kommer att vidta följande steg för att skapa dessa rapporter:
- Konfigurera Azure Data Explorer i en Azure-prenumeration.
- Extrahera data från Microsoft Entra och databaser eller program från tredje part med hjälp av PowerShell-skript och MS Graph.
- Importera data till Azure Data Explorer, en snabb och skalbar dataanalystjänst.
- Skapa en anpassad fråga med hjälp av Kusto-frågespråk.
I slutet av den här självstudien har du skapat kunskaper för att utveckla anpassade vyer över åtkomsträttigheter och behörigheter för användare i olika program med hjälp av Verktyg som stöds av Microsoft.
Förutsättningar
Kontrollera att du har de behörigheter som krävs. Du behöver rätt behörigheter för att exportera den typ av Entra-data som du vill arbeta med och behörigheter för att spara exporterade JSON-filer.
- Användardata: Global administratör, privilegierad rolladministratör, användaradministratör
- Gruppera data: Global administratör, Privilegierad rolladministratör, Gruppadministratör
- Program-/approlltilldelningar: Global administratör, privilegierad rolladministratör, programadministratör, molnprogramadministratör
PowerShell måste anges för att tillåta User.Read.All, Group.Read.All, Application.Read.All och Directory.Read.All. Mer information finns i Referens för Microsoft Graph-behörigheter.
Se till att du har skrivåtkomst till katalogen där du installerar nödvändiga MS Graph PowerShell-moduler och var de exporterade Entra-data kommer att sparas.
Ta reda på vilka data du vill inkludera i dina rapporter. Skripten i den här artikeln innehåller exempel med specifika data från användare, grupper och program från Entra. De här exemplen är avsedda att illustrera de typer av rapporter som du kan generera med den här metoden, men dina specifika rapporteringsbehov kan variera och kräva olika eller ytterligare data.
Steg 1: Konfigurera Azure Data Explorer
Om du inte tidigare har använt Azure Data Explorer måste du konfigurera detta först. Du kan skapa ett kostnadsfritt kluster utan en Azure-prenumeration eller ett kreditkort eller ett fullständigt kluster som kräver en Azure-prenumeration. Se Snabbstart: Skapa ett Azure Data Explorer-kluster och en databas för att komma igång.
Steg 2: Anslut till MS Graph och extrahera Entra-data med PowerShell
Installera MS Graph PowerShell-moduler och Anslut till MS Graph.
- Installera nödvändiga MS Graph-moduler. Följande moduler krävs för den här självstudien: Microsoft.Graph.Users, Microsoft.Graph.Groups, Microsoft.Graph.Applications, Microsoft.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
}
- Importera modulerna:
$modules = @('Microsoft.Graph.Users', 'Microsoft.Graph.Groups', 'Microsoft.Graph.Applications', 'Microsoft.Graph.DirectoryObjects')
foreach ($module in $modules) {
Import-Module -Name $module
}
- Anslut till Microsoft Graph
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All", "Application.Read.All", "Directory.Read.All"
Med det här kommandot uppmanas du att logga in med dina MS Graph-autentiseringsuppgifter. Välj Nödvändiga behörigheter: När du har loggat in kan du behöva godkänna de behörigheter som krävs om det är första gången du ansluter eller om nya behörigheter krävs.
PowerShell-frågor för att extrahera data som behövs för att skapa anpassade rapporter i ADX
Följande frågor extraherar Entra-data från MS Graph med PowerShell och exporterar data till JSON-filer som ska importeras till Azure Data Explorer i steg 3. Det kan finnas flera scenarier för att generera rapporter med den här typen av data:
- En revisor vill se en rapport som listar gruppmedlemmarna för 10 grupper, ordnade av medlemsavdelningen.
- En granskare vill se en rapport över alla användare som hade åtkomst till ett program mellan två datum.
- En administratör vill visa alla användare som lagts till i ett program från Microsoft Entra-ID och SQL-databaser.
Dessa typer av rapporter är inte inbyggda i Microsoft Entra-ID, men du kan skapa dessa rapporter själv genom att extrahera data från Entra och kombinera dem med hjälp av anpassade frågor i Azure Data Explorer.
I den här självstudien extraherar vi Entra-data från flera områden:
- Användarinformation som visningsnamn, UPN och jobbinformation
- Gruppinformation
- Program- och rolltilldelningar
Med den här datamängden kan vi utföra en bred uppsättning frågor kring vem som fick åtkomst till ett program, rollinformation och den associerade tidsramen. Observera att det här är exempelfrågor och att dina data och specifika krav kan variera från vad som visas här.
Kommentar
Större klienter kan uppleva begränsningar/429-fel som hanteras av MS Graph-modulen.
I dessa PowerShell-skript exporterar vi valda egenskaper från Entra-objekten till JSON-filerna. Data från dessa exporterade egenskaper används sedan för att generera anpassade rapporter i Azure Data Explorer. De specifika egenskaperna nedan inkluderades i de här exemplen eftersom vi använder dessa data för att illustrera de typer av rapporter som du kan skapa i Azure Data Explorer. Eftersom dina specifika rapporteringsbehov sannolikt varierar från vad som visas nedan bör du inkludera de specifika egenskaperna i dessa skript som du är intresserad av att visa i dina rapporter, men du kan följa samma mönster som visas nedan för att skapa skripten.
Vi har också inkluderat ett hårdkodat ögonblicksbildsdatum nedan som identifierar data i JSON-filen med ett specifikt datum och gör att vi kan hålla reda på liknande datamängder över tid i Azure Data Explorer. Ögonblicksbildsdatumet är också användbart för att jämföra ändringar i data mellan två ögonblicksbildsdatum.
Hämta Entra-användardata
Det här skriptet exporterar markerade egenskaper från Entra-användarobjektet till en JSON-fil. Vi importerar dessa data till Azure Data Explorer i steg 3.
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"] = "2024-01-11"
[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
Hämta gruppdata
Generera en JSON-fil med gruppnamn och ID:t som ska användas för att skapa anpassade vyer i ADX. Exemplet innehåller alla grupper, men ytterligare filtrering kan inkluderas om det behövs. Om du filtrerar för att endast inkludera vissa grupper kanske du vill inkludera logik i skriptet för att söka efter kapslade grupper.
# 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"
Hämta gruppmedlemskapsdata
Generera en JSON-fil med gruppmedlemskap som ska användas för att skapa anpassade vyer i ADX.
# 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
}
# 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"
Hämta program- och tjänsthuvudnamnsdata
Genererar JSON-filen med alla program och motsvarande tjänsthuvudnamn i klientorganisationen. Vi importerar dessa data till ADX i steg 3, vilket gör att vi kan generera anpassade rapporter relaterade till program som baseras på dessa data.
# 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
}
} | ConvertTo-Json -Depth 10 | Set-Content "Applications.json"
Hämta AppRole-data
Generera en JSON-fil för alla appRoles för företagsappar i Entra. När de har importerats till ADX använder vi dessa data för att generera rapporter som involverar approlltilldelningar för användare.
# 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
}
}
# Export the results to a JSON file
$results | ConvertTo-Json -Depth 4 | Out-File 'AppRoles.json'
Hämta AppRole-tilldelningsdata
Generera en JSON-fil med alla approlltilldelningar i klientorganisationen.
$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 = "2024-03-13" # Hard-coded date
}
}
}
$result | ConvertTo-Json -Depth 10 | Out-File "AppRoleAssignments.json"
Steg 3: Importera JSON-fildata till Azure Data Explorer
I steg 3 importerar vi de nyligen skapade JSON-filerna för ytterligare analys. Om du ännu inte har konfigurerat Azure Data Explorer kan du läsa steg 1 ovan.
Azure Data Explorer är ett kraftfullt dataanalysverktyg som är mycket skalbart och flexibelt och ger en idealisk miljö för att generera anpassade användaråtkomstrapporter. ADX använder Kusto-frågespråk (KQL).
När du har konfigurerat en databas följer du de här stegen för att hämta dina exporterade data till ADX.
- Högerklicka på databasnamnet och välj Hämta data
- Välj Ny tabell och ange namnet på den JSON-fil som du importerar. Om du till exempel importerar EntraUsers.json ger du tabellen namnet EntraUsers. Efter den första importen finns tabellen redan och du kan välja den som måltabell för importen.
- Välj JSON-filen.
- ADX identifierar automatiskt schemat och tillhandahåller en förhandsversion. Klicka på Slutför för att skapa tabellen och importera data.
- Följ steg 1–4 för var och en av de JSON-filer som du genererade i steg 1.
Steg 4: Använda ADX för att skapa anpassade rapporter
Med de data som nu är tillgängliga i ADX är du redo att börja skapa anpassade rapporter baserat på dina affärsbehov. Följande frågor innehåller exempel på vanliga rapporter, men du kan anpassa rapporterna så att de passar dina behov och skapa ytterligare rapporter.
Exempel 1: Generera approlltilldelningar för direkt- och grupptilldelningar för ett specifikt datum för ögonblicksbild
Den här rapporten ger en vy över vem som hade vilken åtkomst och när till målappen och kan användas för säkerhetsgranskningar, efterlevnadsverifiering och förståelse av åtkomstmönster inom organisationen.
Den här frågan riktar sig mot ett specifikt program i Entra AD och analyserar rolltilldelningarna från och med ett visst datum. Frågan hämtar både direkta och gruppbaserade rolltilldelningar och sammanfogar dessa data med användarinformation från tabellen EntraUsers och rollinformationen från tabellen AppRoles.
/// 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
Exempel 2: Skapa grundläggande granskningsrapport med Entra-data som visar vem som hade åtkomst till en app mellan dessa två datum
Den här rapporten ger en vy över vem som hade vilken åtkomst till målappen mellan två datum och kan användas för säkerhetsgranskningar, efterlevnadsverifiering och förståelse av åtkomstmönster i organisationen.
Den här frågan riktar sig mot ett specifikt program i Microsoft Entra-ID och analyserar rolltilldelningarna mellan två datum. Frågan hämtar direkta rolltilldelningar från tabellen AppRoleAssignments och sammanfogar dessa data med användarinformation från tabellen EntraUsers och rollinformation från tabellen 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()
Exempel 3: Hämta användare som lagts till i en app mellan två datum för ögonblicksbild av data
Dessa rapporter ger en vy över vilka användare som fick en approlltilldelning till målprogrammet mellan två datum. Dessa rapporter kan användas för att spåra ändringar i appåtkomst över tid.
Den här frågan riktar sig till ett specifikt program i Microsoft Entra-ID och ändringar i rolltilldelningarna mellan ett start- och slutdatum.
// 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"
Exempel 4: Kombinera apptilldelningar från en Entra och en andra källa (till exempel SQL-export) för att skapa en rapport över alla användare (Entra-tilldelningar och lokala tilldelningar) som hade åtkomst till Salesforce mellan två datum
Den här rapporten visar hur du kan kombinera data från två separata system för att skapa anpassade rapporter i ADX. Den aggregerar data om användare, deras roller och andra attribut från två system till ett enhetligt format för analys eller rapportering.
// 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()
)