Viele Webdienste bieten die Möglichkeit sich mit einem Microsoft Konto anzumelden. Nutzt ein Anwender die Möglichkeit muss er dem Dienst je nach Anforderung div. Berechtigungen auf seine Daten geben, und es legt für den Dienst in Azure eine App an. Mit PowerShell lassen sich Berechtigungen solcher Apps auswerten.
Das Hinzufügen von Azure (Enterprise) Apps durch Anwender ist standardmässig aktiviert. Administratoren können es deaktivieren, das aber bei bestehenden Apps nachträglich Probleme verursachen kann. Im besten Fall klärt man das Thema bereits zu Beginn ab. Ist es aktiviert und ein Webdienst stellt die Möglichkeit bereit sich via Microsoft Konto anzumelden (anstatt ein neues Konto via Email + Passwort anzulegen) können Anwender ihr Unternehmenskonto für die Anmeldung bei dem Dienst einsetzen. Interne Entwickler können bei Bedarf selbst solche Apps erstellen.
Doodle ist zum Beispiel so ein Dienst. Anstatt ein neues Konto mit Email und Passwort anzulegen kann ein Microsoft Konto für die Anmeldung eingesetzt werden.

Mit einem Klick auf „Mit Microsoft anmelden“ wird Doodle die Anforderung stellen Daten für den Microsoft Account abzufragen.

Wird die Anforderung bestätigt erstellt es in Azure unter Enterprise Apps die „Doodle AG“ App.

In der App listet es unter Permissions die Übersicht welche Berechtigungen eine App hat und wie viele Benutzer die App einsetzen. Die Berechtigungen sind identisch wie es oben bei der Anforderung war.

Für einzelne Apps und Benutzer ist es über Azure möglich diese manuell auszuwerten. Möchte man alle bestehenden Apps auswerten ist es manuell ein langwieriger Task. Mit PowerShell wird die Zusammenfassung in kurzer Zeit erstellt.
Voraussetzungen
- Azure AD PowerShell Modul
- Der ausführende Account hat die Rolle Global Admin oder Application Admin
Ein paar Punkte zur Auswertung:
- Das Property Oauth2Permissions in der App steht für den Berechtigungstyp Delegated. Apps mit Delegated Permissions können Daten begrenzt auf einen Benutzeraccount abfragen, und nicht für den ganzen Tenant. Im Normalfall fordern Webdienste bei ihren Apps Delegated Permissions.
- Das Property AppRoles in der App steht für den Berechtigungstyp Application. Apps mit Application Permissions können im Tenant Daten aller Accounts abfragen. Oft sind die beiden Properties in PowerShell leer. Das macht nichts, es kann trotzdem ausgewertet werden.

- Das Script wertet beide Berechtigungstypen aus.
- Das Script inkludiert wie viele Accounts eine App einsetzen.
- Die Auswertung exportiert es am Ende in den Pfad C:\Users\[Username]\Documents\AzureAppPermissions.csv. Mit Excel kannst du den Export filtern.

<#
.DESCRIPTION
The script collects permissions and users for all Azure Enterprise Apps.
For my blog post at https://blog.topedia.com/?p=4270.
.Requirements
- Azure AD PowerShell module
- Account must be a Global Admin or Application Admin
.Link
https://blog.topedia.com/?p=4270
.Link
.Notes
Author: Tobias Asböck
Modified: 01.12.2020
#>
#Requires -Modules @{ ModuleName = "AzureAD" }
Function Get-TAAzureAppResources
{ # Collect all Azure resources to reduce additional Azure requests (required for the summary of Application permissions)
$AllAzureResources = @()
$AllOAuthPermissions = Get-AzureADOAuth2PermissionGrant -All $true
$VariableNr = 1
foreach( $Resource in ($AllOAuthPermissions.Resourceid | select -unique ))
{ $AzureResource = Get-AzureADObjectByObjectId -ObjectIds $Resource
Set-Variable -Name "AzureResource$VariableNr" -Value $AzureResource -Scope "Script"
$AllAzureResources += @{ Variable = ("AzureResource$VariableNr"); ResourceID = $Resource; ResourceDisplayName = $AzureResource.DisplayName }
$VariableNr++
}
$AllAzureResources
}
Import-Module AzureAD
Connect-AzureAD
$AllOAuthPermissions = Get-AzureADOAuth2PermissionGrant -All $true
$AllAzureResources = Get-TAAzureAppResources # Collect all Azure resources to reduce additional Azure requests (required for the summary of Application permissions)
$AllEnterpriseApps = Get-AzureADServicePrincipal -All $true
$MSGraphPermissions = Get-AzureADObjectByObjectId -ObjectIds ($AllEnterpriseApps | ?{$_.Displayname -eq "Microsoft Graph" }).ObjectId # For Delegated permissions, by default the script tries the Graph API first.
$PermissionScopeDetails = @()
$Count = 1
foreach($App in $AllEnterpriseApps )
{ Write-Host ("$Count of " + $AllEnterpriseApps.Count + " - " + $App.DisplayName + "...")
$ConsentDisplayName = $null
$ConsentDescription = $null
$OAuthPermissions = Get-AzureADServicePrincipalOAuth2PermissionGrant -ObjectId $App.ObjectId -All $true # Receiving Delegated permissions
$AppRolePermissions = Get-AzureADServiceAppRoleAssignedTo -ObjectId $App.ObjectId -All $true # Receiving Application permissions
$AppUsers = (Get-AzureADServiceAppRoleAssignment -ObjectId $App.ObjectId -All $true).Count
if( $OAuthPermissions.Count -gt 0 -or $AppRolePermissions.Count -gt 0 ) # In case an app has no permissions included skip it
{
if( $OAuthPermissions.Count -gt 0 )
{ $AllAppPermissions = ($OAuthPermissions.Scope | select -unique).Split(" ") | ?{ $_ }
foreach($AppPermission in $AllAppPermissions )
{
$MSGraphOAuthPermissions = $MSGraphPermissions.Oauth2Permissions | ?{$_.value -eq $AppPermission }
if( $MSGraphOAuthPermissions.UserConsentDisplayName -ne $null)
{ $ConsentDisplayName = $MSGraphOAuthPermissions.UserConsentDisplayName
$ConsentDescription = $MSGraphOAuthPermissions.UserConsentDescription
$API = $MSGraphPermissions.DisplayName
} else
{ # By default the script checks Graph API. In some cases other APIs are included. If Graph returns no results the script requests details for the other API.
$AzureResource = Get-AzureADObjectByObjectId -ObjectIds ($AllOAuthPermissions | ?{$_.scope -like "*$AppPermission*" })[0].ResourceId
$OAuthScope = $AzureResource.Oauth2Permissions | ?{$_.value -eq $AppPermission }
$ConsentDisplayName = $OAuthScope.UserConsentDisplayName
$ConsentDescription = $OAuthScope.UserConsentDescription
$API = $AzureResource.DisplayName
# In some cases the descriptions of user consent is empty, switching to admin consent description (it's mostly a copy)
if( $ConsentDisplayName -eq $null)
{ $ConsentDisplayName = $OAuthScope.AdminConsentDisplayName }
if( $ConsentDescription -eq $null)
{ $ConsentDescription = $OAuthScope.AdminConsentDescription }
}
$PermissionScopeDetails += @{ AppName = $App.DisplayName; AppID = $App.AppId; AppInUseByUsers = $AppUsers; AppEnabled = $App.AccountEnabled; ConsentPermission = $AppPermission ; ResourceAPI = $API; ConsentDisplayName = $ConsentDisplayName ; ConsentDescription = $ConsentDescription; PermissionType = 'Delegated' }
}
}
if( $AppRolePermissions.Count -gt 0 )
{
foreach( $Object in $AppRolePermissions )
{
$AzureResourceVar = ($AllAzureResources | ?{$_.ResourceID -eq $Object.ResourceId }).Variable
if( $AzureResourceVar.Count -eq 0 )
{ # If the resource API was not collected at the start the script adds the missing API information.
$AzureResource = Get-AzureADObjectByObjectId -ObjectIds $Object.ResourceId
$VariableNr = $AllAzureResources.Count + 1
Set-Variable -Name "AzureResource$VariableNr" -Value $AzureResource
$AzureResourceVar = "AzureResource$VariableNr"
$AllAzureResources += @{ Variable = ("AzureResource$VariableNr"); ResourceID = $Object.ResourceId; ResourceDisplayName = $AzureResource.DisplayName }
}
$AzureResource = (Get-Variable $AzureResourceVar).Value
$ResourceScope = $AzureResource.AppRoles | ?{$_.Id -eq $Object.Id}
$PermissionScopeDetails += @{ AppName = $App.DisplayName; AppID = $App.AppId; AppInUseByUsers = $AppUsers; AppEnabled = $App.AccountEnabled; ConsentPermission = $ResourceScope.Value ; ResourceAPI = $AzureResource.DisplayName; ConsentDisplayName = $ResourceScope.DisplayName ; ConsentDescription = $ResourceScope.Description; PermissionType = 'Application' }
}
}
}
$Count++
}
# Exporting the results to C:\Users\[Username]\Documents\AzureAppPermissions.csv
$AppPermissionExport = $PermissionScopeDetails | % { new-object PSObject -Property $_} | Select AppName,AppID,AppInUseByUsers,AppEnabled,ResourceAPI,ConsentPermission,PermissionType,ConsentDisplayname,ConsentDescription
$AppPermissionExport | Export-Csv -Path ([Environment]::GetFolderPath("MyDocuments") + "\AzureAppPermissions.csv") -Delimiter ";" -NoTypeInformation -force


No comments yet