Tutorial: Relatórios personalizados no Azure Data Explorer usando dados do Microsoft Entra
Neste tutorial, você aprenderá a criar relatórios personalizados no ADX (Azure Data Explorer) usando dados dos serviços Microsoft Entra ID e Microsoft Entra ID Governance. Este tutorial complementa outras opções de relatório, como Arquivar e relatar com o Azure Monitor e o gerenciamento de direitos, que se concentram na exportação do log de auditoria para o Azure Monitor para retenção e análise. Em comparação, a exportação de dados do Microsoft Entra ID para o Azure Data Explorer fornece flexibilidade para criar relatórios personalizados em objetos do Microsoft Entra, incluindo objetos históricos e excluídos. Além disso, o uso do Azure Data Explorer permite a agregação de dados de fontes adicionais, com escalabilidade em massa, esquema flexível e políticas de retenção. O Azure Data Explorer é especialmente útil quando você precisa reter dados de acesso por anos, executar investigações ad hoc ou executar consultas personalizadas nos dados de acesso do usuário.
Este artigo ilustra como mostrar a configuração, os usuários e os direitos de acesso exportados do Microsoft Entra, juntamente com os dados exportados de outras fontes, como aplicativos com direitos de acesso nos respectivos bancos de dados SQL. Em seguida, você pode usar o KQL (Linguagem de Consulta Kusto) no Azure Data Explorer para criar relatórios personalizados de acordo com os requisitos da sua organização.
Use as seguintes etapas para criar estes relatórios:
- Configurar o Azure Data Explorer em uma assinatura do Azure ou criar um cluster gratuito.
- Extrair dados do Microsoft Entra ID usando scripts do PowerShell e o Microsoft Graph.
- Criar tabelas e importar esses dados do Microsoft Entra ID para o Azure Data Explorer.
- Extrair dados do Microsoft Entra ID Governance.
- Criar tabelas e importar esses dados do Microsoft Entra ID Governance para o Azure Data Explorer.
- Criar uma consulta personalizada usando a Linguagem de Consulta Kusto.
Ao final deste tutorial, você poderá desenvolver exibições personalizadas dos direitos de acesso e das permissões dos usuários. Essas exibições abrangem diferentes aplicativos usando ferramentas suportadas pela Microsoft. Além disso, você poderá trazer dados de bancos de dados ou de aplicativos de terceiros para gerar relatórios sobre eles também.
Pré-requisitos
Se estiver usando o Azure Data Explorer pela primeira vez e quiser aprender mais sobre os cenários mostrados neste artigo, obtenha um cluster gratuito do Azure Data Explorer. Para uso com suporte para produção com um Contrato de Nível de Serviço para o Azure Data Explorer, você precisa de uma assinatura do Azure para hospedar um cluster completo do Azure Data Explorer.
Determine quais dados você deseja incluir em seus relatórios. Os scripts deste artigo trazem exemplos com os dados específicos de usuários, grupos e aplicativos do Microsoft Entra. Esses exemplos servem para ilustrar os tipos de relatórios que você pode gerar com essa abordagem, mas suas necessidades específicas de relatório podem variar e exigir dados diferentes ou adicionais. Você pode começar com esses objetos e trazer mais tipos de objetos do Microsoft Entra com o tempo.
- Este artigo ilustra a recuperação de dados do Microsoft Entra ao se conectar como usuário. Para fazer isso, verifique se você tem as atribuições de função necessárias para recuperar dados do Microsoft Entra. Você precisa das funções com as permissões certas para exportar o tipo de dados do Microsoft Entra com os quais deseja trabalhar.
- Dados do usuário: Administrador de Segurança, Administrador de Função com Privilégios, Administrador Global
- Dados de grupos: Administrador Global, Administrador de Funções Com Privilégios, Administrador de Grupo
- Aplicativos/Atribuição de Função de Aplicativo: Administrador Global, Administrador de Função com Privilégios, Administrador de Aplicativos, Administrador de Aplicativos de Nuvem
- É necessário conceder o consentimento ao PowerShell do Microsoft Graph para permitir a recuperação de objetos do Microsoft Entra por meio do Microsoft Graph. Os exemplos deste tutorial exigem as permissões User.Read.All, Group.Read.All, Application.Read.All e Directory.Read.All delegadas. Se você estiver planejando recuperar dados usando a automação sem um usuário autenticado, então dê consentimento para as permissões de aplicativo correspondentes. Confira Referência de permissões do Microsoft Graph para saber informações adicionais. Caso você ainda não tenha consentido o Microsoft Graph PowerShell para essas permissões, é necessário ser um Administrador Global para realizar essa operação de consentimento.
- Este tutorial não ilustra atributos de segurança personalizados. Por padrão, o administrador global e outras funções de administrador não incluem permissões para ler atributos de segurança personalizados de usuários do Microsoft Entra. Se você pretende recuperar atributos de segurança personalizados, talvez mais funções e permissões sejam necessárias.
- No computador em que o PowerShell do Microsoft Graph está instalado, verifique se você tem acesso de gravação no diretório do sistema de arquivos. É aqui que você instala os módulos necessários do PowerShell do Microsoft Graph e que os dados exportados do Microsoft Entra são salvos.
- Verifique se você tem permissões para recuperar dados de outras fontes de dados além do Microsoft Entra, caso deseje incorporar esses dados ao Azure Data Explorer também.
1: Configurar o Azure Data Explorer
Se você ainda não usou o Azure Data Explorer anteriormente, precisará configurá-lo primeiro. Você pode criar um cluster gratuito sem uma assinatura do Azure ou um cartão de crédito ou um cluster completo que exige uma assinatura do Azure. Início Rápido: criar um cluster e um banco de dados no Azure Data Explorer para começar.
2: Extrair dados do Microsoft Entra ID com o PowerShell
Nesta seção, você vai instalar módulos do PowerShell do Microsoft Graph e, no PowerShell, se conectar ao Microsoft Graph para extrair dados do Microsoft Entra ID.
Na primeira vez que a sua organização usar esses módulos para esse cenário, você precisará estar em uma função de administrador global para permitir que o PowerShell do Microsoft Graph conceda o consentimento para uso no seu locatário. As interações seguintes podem usar uma função com privilégios inferiores.
- Abra o PowerShell.
- Caso você não tenha todos os módulos do PowerShell do Microsoft Graph já instalados, instale os módulos necessários do Microsoft Graph. Os seguintes módulos são necessários para esta seção do tutorial:
Microsoft.Graph.Authentication
,Microsoft.Graph.Users
,Microsoft.Graph.Groups
,Microsoft.Graph.Applications
eMicrosoft.Graph.DirectoryObjects
. Se você já tiver esses módulos instalados, continue para a próxima etapa.
$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
}
- Importe os módulos para a sessão atual do PowerShell.
$modules = @('Microsoft.Graph.Users', 'Microsoft.Graph.Groups', 'Microsoft.Graph.Applications', 'Microsoft.Graph.DirectoryObjects')
foreach ($module in $modules) {
Import-Module -Name $module
}
- Conecte-se ao Microsoft Graph. Esta seção do tutorial ilustra a leitura de usuários, grupos e aplicativos e, portanto, exige os escopos de permissão
User.Read.All
,Group.Read.All
,Application.Read.All
eDirectory.Read.All
. Para obter mais informações sobre permissões, confira Referência de permissões do Microsoft Graph.
Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All", "Application.Read.All", "Directory.Read.All" -ContextScope Process -NoWelcome
Esse comando solicita que você entre com suas credenciais do Microsoft Entra. Depois que você se conectar, talvez seja necessário consentir com as permissões necessárias se for a primeira vez que se conectar ou se novas permissões forem necessárias.
Consultas do PowerShell para extrair dados do Microsoft Entra ID necessários para criar relatórios personalizados no Azure Data Explorer
As consultas a seguir extraem dados do Microsoft Entra ID por meio do Microsoft Graph usando o PowerShell e exportam os dados para arquivos JSON importados para o Azure Data Explorer na seção 3 seguinte. Pode haver vários cenários para gerar relatórios com esse tipo de dados, incluindo:
- Um auditor gostaria de ver um relatório que lista os membros do grupo para 10 grupos, organizados pelo departamento dos membros.
- Um auditor gostaria de ver um relatório de todos os usuários que tiveram acesso a um aplicativo entre duas datas.
Você também pode trazer dados para o Azure Data Explorer de outras fontes além do Microsoft Entra. Com isso, é possível ter cenários como:
- Um administrador deseja visualizar todos os usuários adicionados a um aplicativo do Microsoft Entra ID e os respectivos direitos de acesso no repositório do próprio aplicativo, como bancos de dados SQL.
Esses tipos de relatórios não são integrados ao Microsoft Entra ID. No entanto, você pode criar esses relatórios por conta própria extraindo dados do Entra e combinando-os com consultas personalizadas no Azure Data Explorer. Isso será abordado posteriormente no tutorial, na seção trazer dados de outras fontes.
Para este tutorial, extraímos dados do Microsoft Entra ID de várias áreas:
- Informações do usuário, como nome de exibição, UPN e detalhes do trabalho
- Informações de grupo, incluindo as respectivas associações
- Atribuições de aplicativos e de funções de aplicativo
Esse conjunto de dados nos permite executar um amplo conjunto de consultas em relação a quem recebeu acesso a um aplicativo, com as respectivas informações de função de aplicativo e o período associado. Observe que essas são consultas de exemplo, e seus dados e requisitos específicos podem variar do que é mostrado aqui.
Observação
Locatários maiores podem enfrentar limitações/erros 429 que são tratados pelo módulo do Microsoft Graph. O Azure Data Explorer também pode limitar os tamanhos de upload de arquivo.
Nesses scripts do PowerShell, exportamos propriedades selecionadas dos objetos do Microsoft Entra para arquivos JSON. Os dados dessas propriedades exportadas são usados para gerar relatórios personalizados no Azure Data Explorer. As propriedades específicas a seguir foram incluídas nesses exemplos, pois estamos usando esses dados para ilustrar os tipos de relatórios que você pode criar no Azure Data Explorer. Como suas necessidades de relatório específicas provavelmente variam do que é mostrado, você deve incluir as propriedades específicas nesses scripts que deseja visualizar nos seus relatórios. No entanto, você pode seguir o mesmo padrão mostrado para ajudar a criar seus scripts.
Selecionar uma data de captura
Incluímos uma data do instantâneo embutida no código, que identifica os dados no arquivo JSON com uma data específica e nos permite acompanhar conjuntos de dados semelhantes ao longo do tempo no Azure Data Explorer. A data do instantâneo também é útil para comparar alterações nos dados entre duas datas de instantâneo.
$SnapshotDate = Get-Date -AsUTC -Format "yyyy-MM-dd"
Obter dados do usuário do Entra
Esse script exporta as propriedades selecionadas do objeto de usuário do Entra para um arquivo JSON. Importaremos esses e dados adicionais de outros arquivos JSON para o Azure Data Explorer em uma seção posterior deste tutorial.
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
Obter dados de grupos
Gere um arquivo JSON com nomes de grupos e IDs que são usados para criar exibições personalizadas no Azure Data Explorer. A amostra inclui todos os grupos, mas uma filtragem adicional pode ser incluída, se necessário. Se você estiver filtrando para incluir apenas determinados grupos, talvez queira incluir lógica em seu script para verificar se há grupos aninhados.
# 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"
Obter dados de associações de grupo
Gere um arquivo JSON com a associação a um grupo que é usada para criar exibições personalizadas no Azure Data Explorer. A amostra inclui todos os grupos, mas uma filtragem adicional pode ser incluída, se necessário.
# 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"
Obter dados de aplicativos e entidades de serviço
Gera o arquivo JSON com todos os aplicativos e entidades de serviço correspondentes no locatário. Importaremos esses dados para o Azure Data Explorer em uma seção posterior deste tutorial que nos permite gerar relatórios personalizados relacionados a aplicativos com base nesses dados.
# 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"
Obter dados do AppRole
Gere um arquivo JSON de todas as appRoles para aplicativos empresariais no Microsoft Entra. Depois que os dados forem importados para o Azure Data Explorer, utilizamos esses dados para gerar relatórios envolvendo atribuições de função de aplicativo para usuários.
# 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'
Obter dados de Atribuição do AppRole
Gere um arquivo JSON de todas as atribuições de função de aplicativo dos usuários no locatário.
$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: Criar tabelas e importar arquivos JSON com os dados do Microsoft Entra ID para o Azure Data Explorer
Nesta seção, importaremos os arquivos JSON recém-criados para os serviços do Microsoft Entra ID como tabelas no Azure Data Explorer para análise posterior. Na primeira importação usando a interface do usuário da Web do Azure Data Explorer, você criará as tabelas com base no esquema que a interface do usuário da Web sugere de cada arquivo JSON.
Depois de configurar um banco de dados no cluster do Azure Data Explorer ou no cluster gratuito, conforme descrito na primeira seção deste artigo, acesse esse banco de dados.
- Entre na interface do usuário da Web do Azure Data Explorer.
- No menu esquerdo, selecione Consulta.
Em seguida, siga estas etapas para cada arquivo JSON exportado, para exportar seus dados para esse banco de dados do Azure Data Explorer como uma nova tabela.
Selecione com o botão direito do mouse o nome do banco de dados em que deseja ingerir os dados. Selecione Obter dados.
Selecione a fonte de dados na lista disponível. Neste tutorial, você está ingerindo dados de um Arquivo local.
Selecione + Nova tabela e insira um nome de tabela, com base no nome do arquivo JSON que você está importando. Por exemplo, se estiver importando EntraUsers.json, dê à tabela o nome de EntraUsers. Após a primeira importação, a tabela já existe e você pode selecioná-la como a tabela de destino para uma importação seguinte.
Selecione Procurar arquivos, selecione o arquivo JSON e selecione Avançar.
O Azure Data Explorer detecta automaticamente o esquema e fornece uma visualização na guia Inspecionar. Selecione Concluir para criar a tabela e importar os dados desse arquivo. Depois que os dados forem ingeridos, clique em Fechar.
Repita cada uma das etapas anteriores para cada um dos arquivos JSON gerados na seção anterior.
Ao final dessas etapas, você terá as tabelas EntraUsers
, EntraGroups
, EntraGroupMembership
, Applications
, AppRoles
e AppRoleAssignments
no banco de dados.
4: Extrair dados do Microsoft Entra ID Governance com o PowerShell
Nesta seção, você usará o PowerShell para extrair dados dos serviços do Microsoft Entra ID Governance. Se você não tiver a Governança de ID do Microsoft Entra, o Microsoft Entra ID P2 ou o Microsoft Entra Suite, continue na seção para usar o Azure Data Explorer para criar relatórios personalizados.
Para isso, talvez seja necessário instalar módulos do PowerShell do Microsoft Graph para extrair dados do Microsoft Entra ID Governance. Na primeira vez que a sua organização usar esses módulos para esse cenário, você precisará estar em uma função de administrador global para permitir que o PowerShell do Microsoft Graph conceda o consentimento para uso no seu locatário. As interações seguintes podem usar uma função com privilégios inferiores.
- Abra o PowerShell.
- Caso você não tenha todos os módulos do PowerShell do Microsoft Graph já instalados, instale os módulos necessários do Microsoft Graph. Os seguintes módulos são necessários para esta seção do tutorial:
Microsoft.Graph.Identity.Governance
. Se você já tiver esses módulos instalados, continue para a próxima etapa.
$modules = @('Microsoft.Graph.Identity.Governance')
foreach ($module in $modules) {
Install-Module -Name $module -Scope CurrentUser -AllowClobber -Force
}
- Importe os módulos para a sessão atual do PowerShell.
$modules = @('Microsoft.Graph.Identity.Governance')
foreach ($module in $modules) {
Import-Module -Name $module
}
- Conecte-se ao Microsoft Graph. Esta seção do tutorial ilustra a recuperação de dados de revisões de acesso e gerenciamento de direitos e, portanto, exige os escopos de permissão
AccessReview.Read.All
eEntitlementManagement.Read.All
. Para outros casos de uso de relatórios, como para o PIM ou os fluxos de trabalho do ciclo de vida, atualize o parâmetroScopes
com as permissões necessárias. Para obter mais informações sobre permissões, confira Referência de permissões do Microsoft Graph.
Connect-MgGraph -Scopes "AccessReview.Read.All, EntitlementManagement.Read.All" -ContextScope Process -NoWelcome
Esse comando solicita que você entre com suas credenciais do Microsoft Entra. Depois que você se conectar, talvez seja necessário consentir com as permissões necessárias se for a primeira vez que se conectar ou se novas permissões forem necessárias.
Consultas do PowerShell para extrair dados do Microsoft Entra ID Governance necessários para criar relatórios personalizados no Azure Data Explorer
Você pode usar consultas para extrair dados do Microsoft Entra ID Governance do Microsoft Graph usando o PowerShell e exportar os dados para arquivos JSON, que serão importados para o Azure Data Explorer na seção seguinte. Pode haver vários cenários para gerar relatórios com esse tipo de dados, incluindo:
- Relatórios de revisões históricas de acesso
- relatórios de atribuições por meio do gerenciamento de direitos
Obter dados de definição de agenda da revisão de acesso
Gere um arquivo JSON com nomes de definições de revisão de acesso e IDs que são usados para criar exibições personalizadas no Azure Data Explorer. A amostra inclui todas as revisões de acesso, mas uma filtragem adicional pode ser incluída, se necessário. Para saber mais, confira usar o parâmetro de consulta de filtro.
$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"
Obter dados da instância de revisão do Access
Para exportar todas as definições, instâncias e decisões da Revisão de Acesso em um formato de pasta estruturado usando o PowerShell, você pode utilizar a API do Microsoft Graph. Essa abordagem garante que seus dados sejam organizados hierarquicamente, alinhando-se com a estrutura de pastas especificada.
Antes de começar, esteja ciente do seguinte:
- Verifique se você tem as permissões necessárias para acessar os dados de Revisões de Acesso no Microsoft Graph.
- Dependendo do volume de dados, o tempo de execução do script pode variar. Monitore o processo e ajuste os parâmetros conforme necessário.
- Baixe o script Export_Access_Reviews.ps1 e salve-o localmente.
- No explorador de arquivos, desbloqueie o script para que ele possa ser executado no PowerShell.
- Execute o comando a seguir, que produzirá todos os dados em três subpastas
ReviewInstances
,ReviewInstanceDecisionItems
eReviewInstanceContactedReviewers
.
.\ExportAccessReviews.ps1 -InstanceStartDate "11/15/2024" -InstanceEndDate "12/15/2024" -ExportFolder "C:\AccessReviewsExport\11_15_to_12_15"
Obter dados do pacote de acesso do gerenciamento de direitos
Gere um arquivo JSON com nomes de pacotes de acesso que são usados para criar exibições personalizadas no Azure Data Explorer. A amostra inclui todos os pacotes de acesso, mas uma filtragem adicional pode ser incluída, se necessário.
$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"
Obter dados de atribuição do pacote de acesso do gerenciamento de direitos
Gere um arquivo JSON com atribuições para acessar pacotes que são usados para criar exibições personalizadas no Azure Data Explorer. A amostra inclui todas as atribuições entregues, mas uma filtragem adicional pode ser incluída, se necessário.
$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: Criar tabelas e importar arquivos JSON com os dados do Microsoft Entra ID Governance para o Azure Data Explorer
Nesta seção, importaremos os arquivos JSON recém-criados para os serviços do Microsoft Entra ID Governance para o Azure Data Explorer, juntamente com os dados já importados para os serviços do Microsoft Entra ID, para análise posterior. Na primeira importação usando a interface do usuário da Web do Azure Data Explorer, você criará tabelas com base no esquema que a interface do usuário da Web sugere de cada arquivo JSON.
No cluster do Azure Data Explorer ou no cluster gratuito, acesse o banco de dados que contém os dados do Microsoft Entra ID.
- Entre na interface do usuário da Web do Azure Data Explorer.
- No menu esquerdo, selecione Consulta.
Em seguida, siga estas etapas para cada arquivo JSON exportado da seção anterior, para exportar seus dados para esse banco de dados do Azure Data Explorer como uma nova tabela.
Selecione com o botão direito do mouse o nome do banco de dados em que deseja ingerir os dados. Selecione Obter dados.
Selecione a fonte de dados na lista disponível. Neste tutorial, você está ingerindo dados de um Arquivo local.
Selecione + Nova tabela e insira um nome de tabela, com base no nome do arquivo JSON que você está importando. Após a primeira importação, a tabela já existirá e você poderá selecioná-la como a tabela de destino para uma importação seguinte.
Selecione Procurar arquivos, selecione o arquivo JSON e selecione Avançar.
O Azure Data Explorer detecta automaticamente o esquema e fornece uma visualização na guia Inspecionar. Selecione Concluir para criar a tabela e importar os dados desse arquivo. Depois que os dados forem ingeridos, clique em Fechar.
Repita cada uma das etapas anteriores para cada um dos arquivos JSON gerados na seção anterior, para cada uma das pastas.
Se houver muitos arquivos em uma pasta, você poderá usar
lightingest
para importar o restante depois que a tabela for criada.
Ao final dessas etapas, você terá as tabelas EntraAccessReviewDefinitions
, EntraAccessPackages
e EntraAccessPackageAssignments
, ReviewInstances
, ReviewInstanceDecisionItems
, ReviewInstanceContactedReviewers
no banco de dados, além das tabelas criadas na seção 3.
6: Usar o Azure Data Explorer para criar relatórios personalizados
Com os dados agora disponíveis no Azure Data Explorer, está tudo pronto para você começar a criar relatórios personalizados de acordo com suas necessidades comerciais.
O Azure Data Explorer é uma poderosa ferramenta de análise de dados altamente escalonável e flexível, fornecendo um ambiente ideal para gerar relatórios personalizados de acesso do usuário. O Azure Data Explorer usa o KQL (Linguagem de Consulta Kusto).
- Entre na interface do usuário da Web do Azure Data Explorer.
- No menu esquerdo, selecione Consulta.
As consultas a seguir fornecem exemplos de relatórios comuns, mas você pode personalizar esses relatórios para atender às suas necessidades e criar relatórios adicionais.
Você também pode exibir seus relatórios no Excel, selecionando a guia Exportar e selecionando Abrir no Excel.
Exemplo 1: gerar atribuições de função de aplicativo para atribuições diretas e de grupo para uma data de instantâneo específica
Este relatório fornece uma visão de quem teve acesso ao aplicativo de destino e em que data, e pode ser usado para auditorias de segurança, verificação de conformidade e compreensão de padrões de acesso dentro da organização.
Essa consulta é direcionada a um aplicativo específico no Microsoft Entra AD e analisa as atribuições de função a partir de determinada data. A consulta recupera atribuições de função diretas e baseadas em grupo, mesclando esses dados com detalhes do usuário da tabela EntraUsers
e informações de função da tabela AppRoles
. Na consulta abaixo, defina a targetSnapshotDate
como o valor snapshotDate
usado ao carregar os dados.
/// 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
Exemplo 2: criar Relatório de Auditor Básico com dados do Entra mostrando quem teve acesso a um aplicativo entre essas duas datas
Este relatório fornece uma visão de quem teve acesso ao aplicativo de destino entre duas datas e pode ser usado para auditorias de segurança, verificação de conformidade e compreensão de padrões de acesso dentro da organização.
Essa consulta tem como alvo um aplicativo específico no Microsoft Entra ID e analisa as atribuições de função entre duas datas. A consulta recupera as atribuições de função diretas da tabela AppRoleAssignments
e mescla esses dados com detalhes do usuário da tabela EntraUsers
e informações de função da tabela 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()
Exemplo 3: obter usuários adicionados a um aplicativo entre duas datas de instantâneo de dados
Esses relatórios fornecem uma exibição de quais usuários receberam uma atribuição de função de aplicativo para o aplicativo de destino entre duas datas. Esses relatórios podem ser usados para acompanhar as alterações no acesso ao aplicativo ao longo do tempo.
Essa consulta tem como alvo um aplicativo específico dentro da Microsoft Entra ID e altera as atribuições de função entre uma data de início e de término.
// 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"
Exemplo 4: Revisões de acesso
Informações sobre linha do tempo e conclusão da revisão
Depois que os dados forem carregados, use as consultas Kusto a seguir para revisá-los.
- Quando o último ciclo de revisão de acesso foi concluído? Quanto tempo demorou?
ReviewInstances
| summarize LastCompletedDate = max(ReviewInstanceEndDateTime),
ReviewDuration = datetime_diff('minute', max(ReviewInstanceEndDateTime), min(ReviewInstanceStartDateTime))
- O processo de revisão de acesso é realizado a tempo (por exemplo, trimestralmente, anualmente)?
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
Analisar a participação e o envolvimento
- Quem foram os revisores atribuídos?
ReviewInstanceContactedReviewers
| project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerName = DisplayName, ReviewerUserPrincipalName = UserPrincipalName, CreatedDateTime
- Quais revisores participaram ativamente e forneceram respostas?
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
- Percentual de revisores que responderam à solicitação de revisão de acesso.
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
- Quando cada revisor concluiu suas tarefas?
ReviewInstanceDecisionItems
| where Decision in ("Approve", "Deny")
| project AccessReviewDefinitionId, AccessReviewInstanceId, ReviewerName = ReviewedBy_DisplayName, ReviewerUserPrincipalName = ReviewedBy_UserPrincipalName, ReviewedDateTime
- Quais revisores não tomaram nenhuma decisão?
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
- Percentual de revisores que não interagiram.
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
- Foram enviados lembretes para os revisores que não deram uma resposta? Decisões pendentes?
// 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
Alterações de usuários e acesso
- Quem perdeu o acesso a recursos específicos durante a revisão de acesso?
ReviewInstanceDecisionItems
| where Decision == "Deny"
| project User = Principal_DisplayName, Resource = Resource_DisplayName, Decision, Justification
- Os usuários foram sinalizados devido à inatividade?
ReviewInstanceDecisionItems
| where Insights contains "inactive"
| project User = Principal_DisplayName, Resource = Resource_DisplayName, Insights, Decision
- Data de remoção de acesso e raciocínio para perda de acesso.
ReviewInstanceDecisionItems
| where Decision == "Deny"
| project User = Principal_DisplayName, Resource=Resource_DisplayName, AccessRemovalDate = AppliedDateTime, Reason = Justification
- Usuários sem decisões tomadas.
ReviewInstanceDecisionItems
| where Decision == "NotReviewed"
| project User = Principal_DisplayName, Resource=Resource_DisplayName
- Revisões sem revisores.
ReviewInstances
| join kind=leftanti (
ReviewInstanceContactedReviewers
| summarize by AccessReviewInstanceId
) on $left.ReviewInstanceId == $right.AccessReviewInstanceId
- Revisões sem usuários.
ReviewInstances
| join kind=leftanti (
ReviewInstanceDecisionItems
| summarize by AccessReviewInstanceId
) on $left.ReviewInstanceId == $right.AccessReviewInstanceId
Examinar dados de decisão
- Decisões tomadas: aprovadas, negadas ou inalteradas.
ReviewInstanceDecisionItems
| summarize count() by Decision
- Número de usuários aprovados ou negados.
ReviewInstanceDecisionItems
| summarize ApprovedCount = countif(Decision == "Approve"), DeniedCount = countif(Decision == "Deny")
- Os motivos de aprovação foram documentados?
ReviewInstanceDecisionItems
| where Decision == "Approve" and isnotempty(Justification)
| summarize count() by ReviewedBy_DisplayName
Verificações de qualidade e conformidade da revisão de acesso
- As revogações de acesso foram consideradas para usuários inativos?
ReviewInstanceDecisionItems
| where Insights contains "inactive" and Decision == "Deny"
| project User = Principal_DisplayName, Decision
- Houve algum acesso não removido corretamente?
ReviewInstanceDecisionItems
| where ApplyResult != "New" and ApplyResult != "AppliedSuccessfully"
- Os revisores documentaram suas decisões?
ReviewInstanceDecisionItems
| where isnotempty(Justification)
| summarize count() by ReviewedBy_DisplayName
- Os comentários foram capturados para cada usuário?
ReviewInstanceDecisionItems
| where isnotempty(Justification)
| project User = Principal_DisplayName, Resource = Resource_DisplayName, Comments = Justification
Configurar importações contínuas
Este tutorial ilustra um processo único de ETL (extração, transformação e carregamento) de dados para popular o Azure Data Explorer com uma só captura para fins de relatório. Para relatórios contínuos ou para comparar alterações ao longo do tempo, você pode automatizar o processo de preenchimento do Azure Data Explorer por meio do Microsoft Entra, para que o seu banco de dados continue tendo dados atuais.
Você pode usar a Automação do Azure, um serviço de nuvem do Azure, para hospedar os scripts do PowerShell necessários para extrair dados do Microsoft Entra ID e do Microsoft Entra ID Governance. Para obter mais informações, confira Automatizar tarefas de governança do Microsoft Entra ID Governance com a Automação do Azure.
Você também pode usar recursos do Azure ou ferramentas de linha de comando, como o lightingest
, para trazer dados e preencher uma tabela já existente. Para obter mais informações, consulte como usar o LightIngest para realizar a ingestão de dados no Azure Data Explorer.
Por exemplo, para carregar um arquivo EntraAccessPackages.json
no diretório atual na tabela EntraAccessPackages
como o usuário conectado no momento:
az login
LightIngest.exe "https://ingest-CLUSTERHOSTNAME;Fed=True" -database:"DATABASE" -table:EntraAccessPackages -sourcepath:"." -pattern:"EntraAccessPackages.json" -format:multijson -azcli:true
Consultar dados no Azure Monitor
Se você estiver enviando logs de auditoria, entrada ou outros do Microsoft Entra para o Azure Monitor, incorpore esses logs no workspace do Log Analytics do Azure Monitor nas suas consultas. Para obter mais informações sobre a relação do Azure Monitor e do Azure Data Explorer, consulte Consultar dados no Azure Monitor usando o Azure Data Explorer.
Entre no Centro de administração do Microsoft Entra.
Selecione Configurações de diagnóstico.
Selecione o local de trabalho do Log Analytics onde você está enviando seus logs.
Na visão geral do workspace do Log Analytics, registre a ID da assinatura, o nome do grupo de recursos e o nome do workspace.
Entre no portal do Azure.
Navegue até a interface do usuário da Web do Azure Data Explorer.
Verifique se o cluster do Azure Data Explorer está listado.
Selecione + Adicionar e depois Conexão.
Na janela Adicionar Conexão, digite a URL para o workspace do Log Analytics, formada pelo nome do host específico da nuvem, pela ID da assinatura, pelo nome do grupo de recursos e pelo nome do workspace do Log Analytics do Azure Monitor, conforme descrito em Adicionar um workspace do Log Analytics.
Depois que a conexão for estabelecida, o workspace do Log Analytics será exibido no painel esquerdo com seu cluster nativo do Azure Data Explorer.
No menu esquerdo, selecione Consulta e depois o cluster do Azure Data Explorer.
No painel de consulta, você pode consultar as tabelas do Azure Monitor que contêm os logs do Microsoft Entra em suas consultas do Azure Data Explorer. Por exemplo:
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
Trazer dados de outras fontes
Você também pode criar tabelas adicionais no Azure Data Explorer para ingerir dados de outras fontes. Se os dados estiverem em um arquivo JSON, semelhante aos exemplos acima, ou em um arquivo CSV, você poderá criar a tabela no momento em que obtiver dados do arquivo pela primeira vez. Quando a tabela for criada, você também poderá usar LightIngest para ingerir dados no Azure Data Explorer de um arquivo JSON ou CSV.
Para obter mais informações sobre a ingestão de dados, confira Visão geral da ingestão de dados do Azure Data Explorer.
Exemplo 5: combinar atribuições de aplicativo de um Entra e uma segunda fonte para criar um relatório de todos os usuários que tiveram acesso a um aplicativo entre duas datas
Este relatório ilustra como você pode combinar dados de dois sistemas separados para criar relatórios personalizados no Azure Data Explorer. Ele agrega dados sobre usuários, suas funções e outros atributos de dois sistemas em um formato unificado para análise ou relatório.
Este exemplo pressupõe que haja uma tabela chamada salesforceAssignments
com colunas UserName
, Name
, EmployeeId
, Department
, JobTitle
, AppName
, Role
e CreatedDateTime
que foi preenchida trazendo dados de outro aplicativo.
// 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()
)