Didacticiel : rapports personnalisés dans Azure Data Explorer (ADX) à l’aide des données de Microsoft Entra ID
Dans ce didacticiel, vous allez découvrir comment créer des rapports personnalisés dans Azure Data Explorer (ADX) à l’aide des données de Microsoft Entra ID. Ce didacticiel complète d’autres options de création de rapports, telles que Archiver et créer des rapports avec Azure Monitor et la gestion des droits d’utilisation, qui se concentrent sur l’exportation des données du journal d’audit pour une rétention et une analyse plus longues. Par comparaison, l’exportation des données de Microsoft Entra ID vers Azure Data Explorer offre une plus grande flexibilité pour créer des rapports personnalisés en permettant l’agrégation de données à partir de plusieurs sources avec une immense extensibilité et des stratégies de schéma et de rétention flexibles.
Ce rapport illustre comment afficher la configuration, les utilisateurs et les droits d’accès exportés à partir de Microsoft Entra, ainsi que les données exportées à partir d’autres sources, telles que des applications avec des bases de données SQL. Vous pouvez ensuite utiliser le langage de requête Kusto (KQL) pour créer des rapports personnalisés en fonction des exigences de votre organisation. La génération de ces types de rapports dans Azure Data Explorer peut s’avérer très utile si vous devez conserver les données d’accès pendant des périodes plus longues, pour effectuer des enquêtes ad hoc ou pour exécuter des requêtes personnalisées sur les données d’accès utilisateur.
Exécutez les étapes suivantes pour créer ces rapport :
- Configurez Azure Data Explorer dans un abonnement Azure.
- Extrayez des données de Microsoft Entra et de bases de données ou d’applications tierces à l’aide de scripts PowerShell et MS Graph.
- Importez les données dans Azure Data Explorer, un service d’analytique des données rapide et évolutif.
- Créez une requête personnalisée à l’aide du langage de requête Kusto.
À la fin de ce didacticiel, vous disposerez des compétences pour développer des vues personnalisées des droits d’accès et des autorisations des utilisateurs sur différentes applications à l’aide des outils pris en charge par Microsoft.
Prérequis
Vérifiez que vous disposez des autorisations requises. Vous aurez besoin des autorisations appropriées pour exporter le type de données Entra que vous souhaitez utiliser et les autorisations nécessaires pour enregistrer les fichiers JSON exportés.
- Données utilisateur : Administrateur général, Administrateur de rôle privilégié, Administrateur d’utilisateur
- Données de groupes : Administrateur général, Administrateur de rôle privilégié, Administrateur de groupe
- Attribution de rôle d’application : Administrateur de rôle privilégié, Administrateur d’application cloud ou Administrateur d’application
PowerShell doit être défini pour autoriser User.Read.All, Group.Read.All, Application.Read.All, et Directory.Read.All. Consultez la documentation de référence sur les autorisations Microsoft Graph pour plus d’informations.
Vérifiez que vous disposez d’un accès en écriture au répertoire dans lequel vous installerez les modules PowerShell MS Graph requis et où les données Entra exportées seront enregistrées.
Déterminez les données que vous souhaitez inclure dans vos rapports. Les scripts de cet article fournissent des exemples avec des données spécifiques provenant d’utilisateurs, de groupes et d’applications Entra. Ces exemples sont destinés à illustrer les types de rapports que vous pouvez générer avec cette approche, mais vos besoins de création de rapports spécifiques peuvent varier et nécessiter des données différentes ou supplémentaires.
Étape 1 : Configurer Azure Data Explorer
Si vous n’avez pas déjà utilisé Azure Data Explorer, vous devez d’abord le configurer. Vous pouvez créer un cluster gratuit sans abonnement Azure ou carte de crédit, ou bien un cluster complet qui nécessite un abonnement Azure. Consultez Démarrage rapide : Créer un cluster et une base de données pour l’Explorateur de données Azure pour commencer.
Étape 2 : Se connecter à MS Graph et extraire des données Entra avec PowerShell
Installez des modules PowerShell MS Graph et connectez-vous à MS Graph.
- Installez les modules MS Graph requis. Les modules suivants sont requis pour ce didacticiel : 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
}
- Importez les modules :
$modules = @('Microsoft.Graph.Users', 'Microsoft.Graph.Groups', 'Microsoft.Graph.Applications', 'Microsoft.Graph.DirectoryObjects')
foreach ($module in $modules) {
Import-Module -Name $module
}
- Se connecter à Microsoft Graph
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All", "Application.Read.All", "Directory.Read.All"
Cette commande vous invite à vous connecter avec vos informations d’identification MS Graph. Sélectionnez Autorisations requises : après vous être connecté, vous devrez peut-être donner votre consentement aux autorisations requises s’il s’agit de votre première connexion ou si de nouvelles autorisations sont requises.
Requêtes PowerShell pour extraire des données nécessaires pour générer des rapports personnalisés dans ADX
Les requêtes suivantes extraient les données Entra à partir de MS Graph à l’aide de PowerShell et exportent les données vers des fichiers JSON qui seront importés dans Azure Data Explorer à l’étape 3. Il peut y avoir plusieurs scénarios pour générer des rapports avec ce type de données :
- Un auditeur souhaite voir un rapport qui réunit les membres de 10 groupes, organisés par le département des membres.
- Un auditeur souhaite voir un rapport de tous les utilisateurs qui ont accédé à une application entre deux dates.
- Un administrateur souhaite voir tous les utilisateurs ajoutés à une application à partir de Microsoft Entra ID et de bases de données SQL.
Ces types de rapports ne sont pas intégrés à Microsoft Entra ID, mais vous pouvez créer ces rapports vous-même en extrayant des données Entra et en les combinant à l’aide de requêtes personnalisées dans Azure Data Explorer.
Pour ce didacticiel, nous allons extraire les données Entra de plusieurs domaines :
- Les informations utilisateur telles que le nom d’affichage, l’UPN et les détails du travail
- Les informations du groupe
- Les attributions d’applications et de rôles
Ce jeu de données nous permettra d’effectuer un large ensemble de requêtes concernant la personne qui a reçu l’accès à une application, les informations du rôle et la période associée. Notez qu’il s’agit d’exemples de requêtes, et que vos données et exigences spécifiques peuvent différer de ce qui est affiché ici.
Remarque
Les locataires plus volumineux peuvent rencontrer des erreurs de limitation / 429 erreurs qui seront gérées par le module MS Graph.
Dans ces scripts PowerShell, nous allons exporter les propriétés sélectionnées des objets Entra vers des fichiers JSON. Les données de ces propriétés exportées seront ensuite utilisées pour générer des rapports personnalisés dans Azure Data Explorer. Les propriétés spécifiques ci-dessous ont été incluses dans ces exemples, car nous utilisons ces données pour illustrer les types de rapports que vous pouvez créer dans Azure Data Explorer. Étant donné que vos besoins spécifiques en matière de création de rapports varient probablement de ce qui est indiqué ci-dessous, vous devez inclure les propriétés spécifiques de ces scripts qui vous intéressent dans vos rapports, mais vous pouvez aussi suivre le modèle ci-dessous pour vous aider à générer vos scripts.
Nous avons également inclus une date d’instantané codée en dur ci-dessous, qui identifie les données du fichier JSON avec une date spécifique et nous permettra de suivre les jeux de données similaires au fil du temps dans Azure Data Explorer. La date d’instantané est également utile pour comparer les modifications apportées aux données entre deux dates d’instantané.
Obtenir les données utilisateur Entra
Ce script exporte les propriétés sélectionnées de l’objet utilisateur Entra vers un fichier JSON. Nous allons importer ces données dans Azure Data Explorer à l’étape 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
Obtenir des données de groupe
Générez un fichier JSON avec des noms de groupe et des ID qui seront utilisés pour créer des vues personnalisées dans ADX. L’exemple inclut tous les groupes, mais un filtrage supplémentaire peut être inclus si nécessaire. Si vous filtrez pour inclure uniquement certains groupes, vous pouvez inclure la logique dans votre script pour rechercher des groupes imbriqués.
# 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"
Obtenir les données d’appartenance de groupe
Générez un fichier JSON avec des appartenances de groupe qui sera utilisé pour créer des vues personnalisées dans 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"
Obtenir des données d’application et de principal de service
Génère un fichier JSON avec toutes les applications et les principaux de service correspondants dans le locataire. Nous allons importer ces données dans ADX à l’étape 3, ce qui nous permettra de générer des rapports personnalisés liés aux applications en fonction de ces données.
# 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"
Obtenir des données AppRole
Générez un fichier JSON de toutes les applications appRoles pour les applications d’entreprise dans Entra. Une fois importés dans ADX, nous allons utiliser ces données pour générer des rapports impliquant des attributions de rôles d’application pour les utilisateurs.
# 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'
Obtenir les données d’affectation AppRole
Générez un fichier JSON de toutes les attributions de rôles d’application dans le locataire.
$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"
Étape 3 : Importer des données de fichier JSON dans Azure Data Explorer
À l’étape 3, nous allons importer les fichiers JSON nouvellement créés pour une analyse plus approfondie. Si vous n’avez pas encore configuré Azure Data Explorer, consultez l’étape 1 ci-dessus.
Azure Data Explorer est un puissant outil d’analyse des données hautement évolutif et flexible qui fournit un environnement idéal pour générer des rapports d’accès utilisateur personnalisés. ADX utilise le langage de requête Kusto (KQL).
Une fois que vous avez configuré une base de données, procédez de la manière suivante pour obtenir vos données exportées dans ADX.
- Cliquez avec le bouton droit sur le nom de la base de données et choisissez Obtenir les données
- Choisissez Nouvelle table et entrez le nom du fichier JSON que vous importez, par exemple, si vous importez EntraUsers.json, nommez la table EntraUsers. Une fois la première importation terminée, la table existe déjà et vous pouvez la sélectionner comme table cible pour l’importation.
- Sélectionnez le fichier JSON.
- ADX détecte automatiquement le schéma et fournit une préversion. Cliquez sur Terminer pour créer la table et importer les données.
- Suivez les étapes 1 à 4 pour chacun des fichiers JSON que vous avez générés à l’étape 1.
Étape 4 : Utiliser ADX pour générer des rapports personnalisés
Maintenant que les données sont disponibles dans ADX, vous êtes prêt à commencer à créer des rapports personnalisés en fonction des besoins de votre entreprise. Les requêtes suivantes fournissent des exemples de rapports courants, mais vous pouvez personnaliser ces rapports en fonction de vos besoins et créer des rapports supplémentaires.
Exemple 1 : Générer des attributions de rôles d’application pour les attributions de groupes et directes pour une date d’instantané spécifique
Ce rapport permet de voir qui a eu accès à l’application cible et quand, et peut être utilisé pour les audits de sécurité, la vérification de conformité et pour comprendre des modèles d’accès au sein de l’organisation.
Cette requête cible une application spécifique dans Entra AD et analyse les attributions de rôles à partir d’une certaine date. La requête récupère des attributions de rôles directes et basées sur des groupes, en fusionnant ces données avec les détails de l’utilisateur à partir de la table EntraUsers et des informations de rôle de la table 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
Exemple 2 : Créer un rapport d’auditeur de base avec des données Entra montrant qui avait accès à une application entre ces deux dates
Ce rapport permet de voir qui a eu accès à l’application cible entre deux dates, et peut être utilisé pour les audits de sécurité, la vérification de conformité et pour comprendre des modèles d’accès au sein de l’organisation.
Cette requête cible une application spécifique dans Microsoft Entra ID et analyse les attributions de rôles entre deux dates. La requête récupère les attributions de rôles directes à partir de la table AppRoleAssignments et fusionne ces données avec les détails de l’utilisateur de la table EntraUsers et les informations de rôle de la table 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()
Exemple 3 : Obtenir des utilisateurs ajoutés à une application entre deux dates d’instantané de données
Ces rapports permettent de voir quels utilisateurs ont reçu une attribution de rôle d’application à l’application cible entre deux dates. Ces rapports peuvent être utilisés pour suivre les modifications apportées à l’accès aux applications au fil du temps.
Cette requête cible une application spécifique dans Microsoft Entra ID et change les attributions de rôles entre une date de début et de fin.
// 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"
Exemple 4 : Combiner des affectations d’application à partir d’Entra et d’une deuxième source (par exemple, une exportation SQL) pour créer un rapport de tous les utilisateurs (affectations Entra et affectations locales) ayant accès à Salesforce entre deux dates
Ce rapport montre comment combiner des données à partir de deux systèmes distincts pour créer des rapports personnalisés dans ADX. Il agrège les données sur les utilisateurs, sur leurs rôles et sur d’autres attributs de deux systèmes dans un format unifié pour l’analyse ou la création de rapports.
// 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()
)