-
-
Save JustinGrote/656a01c1e047df940d577698ba62e3f2 to your computer and use it in GitHub Desktop.
#requires -version 7 -module Microsoft.Graph.Applications | |
using namespace Microsoft.Graph.PowerShell.Models | |
using namespace System.Collections.Generic | |
enum MicrosoftGraphServicePrincipalType { | |
Application | |
Delegated | |
} | |
class MgServicePrincipalPermission { | |
[MicrosoftGraphServicePrincipal]$ServicePrincipal | |
[string]$Id | |
[MicrosoftGraphServicePrincipalType]$Type | |
[string]$User | |
[string]$ResourceName | |
[string]$Permission | |
[string]$PermissionDisplayName | |
[string]$Description | |
[Nullable[DateTime]]$CreatedDateTime | |
} | |
Update-TypeData -TypeName 'MgServicePrincipalPermission' -DefaultDisplayPropertySet 'ServicePrincipal', 'ResourceName', 'User', 'Permission' -Force | Out-Null | |
function Get-MgServicePrincipalPermission { | |
<# | |
.SYNOPSIS | |
Retrieves the permissions assigned to a service principal, providing a similar output to what is on the Azure Portal Screen. | |
.EXAMPLE | |
Get-MgServicePrincipal -Search 'displayname:MyServicePrincipal' -Con eventual -Cou count | Get-MgServicePrincipalPermission | |
#> | |
[CmdletBinding(DefaultParameterSetName = 'Object')] | |
param( | |
[Parameter(ParameterSetName = 'Id', Position = 0, Mandatory, ValueFromPipelineByPropertyName)] | |
[Alias('Id')] | |
[string]$ServicePrincipalId, | |
[Parameter(ParameterSetName = 'Object', Position = 0, Mandatory, 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 | |
#Add a ToString to the serviceprincipal so it summarizes correctly in the formatting | |
$ServicePrincipal | Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.DisplayName } -Force | |
#When using Mandatory above, it becomes an empty string instead of null, so null conditional cannot be used. | |
if ([string]::IsNullOrEmpty($ServicePrincipalId)) { | |
$ServicePrincipalId = $ServicePrincipal.Id | |
} | |
$appPermissions = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $ServicePrincipalId | |
| Where-Object DeletedDateTime -EQ $null | |
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" } | |
[MgServicePrincipalPermission]@{ | |
ServicePrincipal = $ServicePrincipal | |
Id = $app.Id | |
Type = 'Application' | |
User = '[Application]' | |
ResourceName = $app.ResourceDisplayName | |
Permission = $role.Value | |
PermissionDisplayName = $role.DisplayName | |
Description = $role.Description | |
CreatedDateTime = $app.CreatedDateTime | |
} | |
} | |
$delegatedPermissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipalId $ServicePrincipalId | |
foreach ($permission in $delegatedPermissions) { | |
if (-not $spCache[$permission.ResourceId]) { | |
$spCache[$permission.ResourceId] = Get-MgServicePrincipal -ServicePrincipalId $permission.ResourceId | |
| Add-Member -MemberType ScriptMethod -Name ToString -Value { $this.DisplayName } -Force -PassThru | |
} | |
$resource = $spCache[$permission.ResourceId] | |
foreach ($scope in $permission.Scope.split(' ')) { | |
$role = $resource.AppRoles | Where-Object Value -EQ $scope | |
[MgServicePrincipalPermission]@{ | |
ServicePrincipal = $ServicePrincipal | |
Id = $scope.Id | |
Type = 'Delegated' | |
User = $permission.ConsentType -eq 'AllPrincipals' ? 'All' : $permission.PrincipalId | |
ResourceName = $resource.DisplayName | |
Permission = $scope | |
PermissionDisplayName = $role.DisplayName | |
Description = $role.Description | |
CreatedDateTime = $null | |
} | |
} | |
} | |
} | |
} |
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.
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.
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.
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.
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.
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.
@rdantas9 works fine for me, not sure how you're invoking it that is causing the namespace errors.
@rdantas9 works fine for me, not sure how you're invoking it that is causing the namespace errors.
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!
Hi, is 'Id = $app.Id' meant to be there in line 52 under $delegatedPermissions? If so, could you explain why?
Probably a cut/paste oopsie from the foreach loop above it, probably should be $scope.id
Thanks. Appreciate all your work.
Thanks @JustinGrote :)) Saved me reinventing the wheel here. Modified it a bit to list all the permissions in a gridview so I can select and delete Application permissions.
InvalidOperation:
Line |
4 | … ='Object',ValueFromPipeline)][MicrosoftGraphServicePrincipal]$Service …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Unable to find type [MicrosoftGraphServicePrincipal].