Skip to content

Instantly share code, notes, and snippets.

@JustinGrote
Last active January 19, 2024 15:05
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save JustinGrote/656a01c1e047df940d577698ba62e3f2 to your computer and use it in GitHub Desktop.
Get a list of application and delegated permissions for a service principal, similar to what the Azure Portal shows
#requires -version 7
using namespace Microsoft.Graph.PowerShell.Models
using namespace System.Collections.Generic
function Get-MgServicePrincipalPermission {
param(
[Parameter(ParameterSetName='Id',ValueFromPipelineByPropertyName)][Alias('Id')][string]$ServicePrincipalId,
[Parameter(ParameterSetName='Object',ValueFromPipeline)][Microsoft.Graph.PowerShell.Models.MicrosoftGraphServicePrincipal]$ServicePrincipal
)
begin {
#We use this to cache app info for permission lookups
[Dictionary[string,MicrosoftGraphServicePrincipal]]$spCache = @{}
}
process {
$ErrorActionPreference = 'Stop'
$ServicePrincipal ??= Get-MgServicePrincipal -ServicePrincipalId $ServicePrincipalId
$ServicePrincipalId ??= $ServicePrincipal.Id
$appPermissions = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ServicePrincipalId
| Where-Object DeletedDateTime -eq $null
$delegatedPermissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipalId $ServicePrincipalId
foreach ($app in $appPermissions) {
$spCache[$app.ResourceId] ??= Get-MgServicePrincipal -ServicePrincipalId $app.ResourceId
[MicrosoftGraphAppRole]$role = $spCache[$app.ResourceId].AppRoles
| Where-Object Id -eq $app.AppRoleId
if (-not $Role) {throw "No matching permission found for AppRoleID $($app.AppRoleId). This is a bug"}
[PSCustomObject]@{
ServicePrincipalName = $ServicePrincipal.DisplayName
Id = $app.Id
Type = 'Application'
User = $null
ResourceName = $app.ResourceDisplayName
Permission = $role.Value
PermissionDisplayName = $role.DisplayName
Description = $role.Description
CreatedDateTime = $app.CreatedDateTime
}
}
foreach ($permission in $delegatedPermissions) {
$spCache[$permission.ResourceId] ??= Get-MgServicePrincipal -ServicePrincipalId $permission.ResourceId
$resource = $spCache[$permission.ResourceId]
foreach ($scope in $permission.Scope.split(' ')) {
$role = $resource.AppRoles | Where-Object Value -eq $scope
[PSCustomObject]@{
ServicePrincipalName = $ServicePrincipal.DisplayName
Id = $app.Id
Type = 'Delegated'
User = $permission.ConsentType -eq 'AllPrincipals' ? 'All' : $permission.PrincipalId
ResourceName = $resource.DisplayName
Permission = $scope
PermissionDisplayName = $role.DisplayName
Description = $role.Description
CreatedDateTime = $null
}
}
}
}
}
@JustinGrote
Copy link
Author

image

@rdantas9
Copy link

InvalidOperation:
Line |
4 | … ='Object',ValueFromPipeline)][MicrosoftGraphServicePrincipal]$Service …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Unable to find type [MicrosoftGraphServicePrincipal].

@JustinGrote
Copy link
Author

InvalidOperation: Line | 4 | … ='Object',ValueFromPipeline)][MicrosoftGraphServicePrincipal]$Service … | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | Unable to find type [MicrosoftGraphServicePrincipal].

You probably need to import the graph module first before running so that the type is loaded.

@rdantas9
Copy link

InvalidOperation: Line | 4 | … ='Object',ValueFromPipeline)][MicrosoftGraphServicePrincipal]$Service … | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | Unable to find type [MicrosoftGraphServicePrincipal].

You probably need to import the graph module first before running so that the type is loaded.

I've updated Microsoft.Graph module and imported it, but the same error is displayed after run your Powershell script.

@JustinGrote
Copy link
Author

Try running using namespace Microsoft.Graph.PowerShell.Models before running the function. I also updated the function so it shouldn't error if this is missing now.

@rdantas9
Copy link

Try running using namespace Microsoft.Graph.PowerShell.Models before running the function. I also updated the function so it shouldn't error if this is missing now.

InvalidOperation:
Line |
8 | [Dictionary[string,MicrosoftGraphServicePrincipal]]$spCache = @{}
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Unable to find type [Dictionary].
Get-MgServicePrincipalPermission: Cannot index into a null array.

@JustinGrote
Copy link
Author

Are you running this in PowerShell 5.1? Try PowerShell 7, also try dot sourcing the script rather than cut-paste. For whatever reason you are not getting the namespace things at the top of the script to register correctly.

@rdantas9
Copy link

Are you running this in PowerShell 5.1? Try PowerShell 7, also try dot sourcing the script rather than cut-paste. For whatever reason you are not getting the namespace things at the top of the script to register correctly.

I'm running PowerShell 7.3.5. I'm trying to run Powershell script in another VM.

@JustinGrote
Copy link
Author

@rdantas9 works fine for me, not sure how you're invoking it that is causing the namespace errors.
image

@rdantas9
Copy link

@rdantas9 works fine for me, not sure how you're invoking it that is causing the namespace errors. image

I was able to run your PowerShell script properly, but I've replaced line 12 from MicrosoftGraphServicePrincipal to Microsoft.Graph.PowerShell.Models.MicrosoftGraphServicePrincipal.

Thanks for your patience and support!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment