Have created a custom PowerShell script to export all of my azure registered apps API application permissions
and delegated permissions
. Some of my apps have either API permissions
of Type
equal to delegated
or application
. I followed the step by step guide answered in this question
I'm expecting similar output for all apps with delegated permissions
What i'm i doing wrong or missing?
CodePudding user response:
Here is how I would get all the application permissions / delegated permissions for all apps while tracking ownership context.
This will produce something like your sample CSV output.
Code
Connect-azureAD
$Apps = Get-AzureADApplication -All $true
$ServicePrincipals = Get-AzureADServicePrincipal -All $true
$export_application_permission = ""
$export_delegated_permission = "C:\temp\delegated_perms.csv"
$PermissionsList = $ServicePrincipals.Oauth2Permissions | Select-Object Id, Value
$RolesList = $ServicePrincipals.AppRoles | Select-Object Id, Value
$app.RequiredResourceAccess
$Data = Foreach ($App in $Apps) {
foreach ($Access in $App.RequiredResourceAccess) {
foreach ($Permission in $Access.ResourceAccess) {
switch ($Permission.Type) {
'Scope' {
$PermissionName = ($PermissionsList | Where Id -eq $Permission.Id).Value
break
}
'Role' {
$PermissionName = ($RolesList | Where Id -eq $Permission.Id).Value
break
}
}
if (!$PermissionName) { $PermissionName = $Permission.Id }
[PSCustomObject]@{
'Application Display Name' = $App.DisplayName
'Permission Type' = $Permission.Type
'Permission Value' = $PermissionName
}
}
}
}
$Data | Where-Object 'Permission Type' -eq Role | Export-Csv -Path $export_application_permission -NoTypeInformation
$Data | Where-Object 'Permission Type' -eq Scope | Export-Csv -Path $export_delegated_permission -NoTypeInformation
Caveat
Checking just for the permission value (eg: User.Read.All
) can be misleading as a custom app that also expose a permission with the same name would result in a situation where you get the permissions name, but you don't know which API is behind that permission (eg: Is it graph, a custom app, another Microsoft API that share some of the permissions name, etc...)
A couple of notes regarding your original code
There is a couple of inefficiencies in your original sample.
Connect-AzureAd
. you only need to connect once before entering the loop and not at multiple points like you do.Get-AzureADServicePrincipal
can be called once before the loop at the same time you get all your azure AD apps. In the loops, you just select what you need from the initial results instead of calling the cmdlet again and again.Export-CSV -Append
. I would discourage the use of this and rather use it after the loop so instead of accessing the file dozen, hundred or thgousands times, you access it once.- Perfomance wise, it is faster (and cleaner IMO) to use the hashtable cast to PSCustomObject rather than creating a PSObject and using
Add-member
# This
$record = [PSCustomObject]@{
"Application Display Name" = $app.displayName
"Permission Type" = $res_access.Type
"Permission Value" = $rol
}
#Instead of this
$record = New-Object PSObject
$record | Add-Member NoteProperty -Name "Application Display Name" -Value $app.displayName
$record | Add-Member NoteProperty -Name "Permission Type" -Value $res_access.Type
$record | Add-Member NoteProperty -Name "Permission Value" -Value $rol
CodePudding user response:
Line 65 needs to say $sp.Oauth2Permissions:
$delegated_perms = $sp.Oauth2Permissions | Where-Object {$_.Id -eq $res_ac}
You have:
$delegated_perms = $sp.oauth2PermissionScopes | Where-Object {$_.Id -eq $res_ac}