AzurePIMStuff.psm1
function Get-PIMGroup { <# .SYNOPSIS Function returns Azure groups with some PIM eligible assignments a.k.a. PIM enabled groups. .DESCRIPTION Function returns Azure groups with some PIM eligible assignments a.k.a. PIM enabled groups. To get more details about the PIM eligible assignments, use Get-PIMGroupEligibleAssignment. .EXAMPLE Get-PIMGroup Function returns Azure groups with some PIM eligible assignments a.k.a. PIM enabled groups. #> [CmdletBinding()] param() Write-Warning "Searching for groups with PIM eligible assignment. This can take a while." if (!(Get-Command Get-MgContext -ErrorAction silentlycontinue) -or !(Get-MgContext)) { throw "$($MyInvocation.MyCommand): Authentication needed. Please call Connect-MgGraph." } # I don't know how to get PIM enabled groups in better way than just get all PIM capable groups and find whether they have some eligible assignment set $possiblePIMGroup = Invoke-MgGraphRequest -Uri "v1.0/groups?`$select=Id,DisplayName,OnPremisesSyncEnabled,GroupTypes,MailEnabled,SecurityEnabled" | Get-MgGraphAllPages | ? { $_.onPremisesSyncEnabled -eq $null -and $_.GroupTypes -notcontains 'DynamicMembership' -and !($_.MailEnabled -and $_.SecurityEnabled -and $_.GroupTypes -notcontains 'Unified') -and !($_.MailEnabled -and !$_.SecurityEnabled) } if (!$possiblePIMGroup) { return } $groupWithPIMEligibleAssignment = New-GraphBatchRequest -url "identityGovernance/privilegedAccess/group/eligibilitySchedules?`$filter=groupId eq '<placeholder>'" -placeholder $possiblePIMGroup.Id | Invoke-GraphBatchRequest -graphVersion v1.0 -dontAddRequestId $possiblePIMGroup | ? Id -In ($groupWithPIMEligibleAssignment.groupId) | select *, @{Name = 'EligibleAssignment'; Expression = { $id = $_.Id; $groupWithPIMEligibleAssignment | ? groupId -EQ $id } } } function Get-PIMGroupEligibleAssignment { <# .SYNOPSIS Returns eligible assignments for Azure AD groups (PIM). .DESCRIPTION This function finds Azure AD groups that have Privileged Identity Management (PIM) eligible assignments. It can process specific group IDs or search all groups for PIM eligibility. Optionally, it retrieves assignment settings for each group and translates object IDs to display names for easier interpretation. .PARAMETER groupId One or more Azure AD group IDs to process. If not specified, all possible PIM-enabled groups will be searched. .PARAMETER skipAssignmentSettings If specified, the function will not retrieve assignment settings for the roles. This can speed up the function if you don't need the detailed settings. .EXAMPLE Get-PIMGroupEligibleAssignment Returns all Azure AD groups with PIM eligible assignments and their assignment settings. .EXAMPLE Get-PIMGroupEligibleAssignment -groupId "12345678-aaaa-bbbb-cccc-1234567890ab" -skipAssignmentSettings Returns PIM eligible assignments for the specified group, skipping assignment settings for faster results. .NOTES Author: @AndrewZtrhgf #> [CmdletBinding()] param ( [string[]] $groupId, [switch] $skipAssignmentSettings ) if (!(Get-Command Get-MgContext -ErrorAction silentlycontinue) -or !(Get-MgContext)) { throw "$($MyInvocation.MyCommand): Authentication needed. Please call Connect-MgGraph." } if ($groupId) { $possiblePIMGroupId = $groupId } else { # I don't know how to get the list of PIM enabled groups so I have to find them # by searching for eligible role assignments for every PIM-supported-type group Write-Warning "Searching for groups with PIM eligible assignment. This can take a while." $possiblePIMGroupId = (Invoke-MgGraphRequest -Uri "v1.0/groups?`$select=Id,DisplayName,OnPremisesSyncEnabled,GroupTypes,MailEnabled,SecurityEnabled" | Get-MgGraphAllPages | ? { $_.onPremisesSyncEnabled -eq $null -and $_.GroupTypes -notcontains 'DynamicMembership' -and !($_.MailEnabled -and $_.SecurityEnabled -and $_.GroupTypes -notcontains 'Unified') -and !($_.MailEnabled -and !$_.SecurityEnabled) }).id } if (!$possiblePIMGroupId) { return } # search for groups that have some PIM settings defined $groupWithPIMEligibleAssignment = New-GraphBatchRequest -url "identityGovernance/privilegedAccess/group/eligibilitySchedules?`$filter=groupId eq '<placeholder>'" -placeholder $possiblePIMGroupId | Invoke-GraphBatchRequest -graphVersion v1.0 -dontAddRequestId if (!$groupWithPIMEligibleAssignment) { Write-Warning "None of the groups have PIM eligible assignments" return } #region get assignment settings for all PIM groups if (!$skipAssignmentSettings) { $assignmentSettingBatch = [System.Collections.Generic.List[Object]]::new() $groupWithPIMEligibleAssignment | % { $groupId = $_.groupId $type = $_.accessId $assignmentSettingBatch.Add((New-GraphBatchRequest -url "policies/roleManagementPolicyAssignments?`$filter=scopeId eq '$groupId' and scopeType eq 'Group' and roleDefinitionId eq '$type'&`$expand=policy(`$expand=rules)")) } $assignmentSettingList = Invoke-GraphBatchRequest -batchRequest $assignmentSettingBatch -graphVersion beta -dontAddRequestId } #endregion get assignment settings for all PIM groups #region translate all Ids to corresponding DisplayName $idToTranslate = [System.Collections.Generic.List[Object]]::new() $groupWithPIMEligibleAssignment.PrincipalId | % { $idToTranslate.add($_) } $groupWithPIMEligibleAssignment.groupId | % { $idToTranslate.add($_) } $idToTranslate = $idToTranslate | select -Unique $translationList = Get-AzureDirectoryObject -id $idToTranslate #endregion translate all Ids to corresponding DisplayName # output the results $groupWithPIMEligibleAssignment | % { $groupId = $_.groupId $type = $_.accessId $principalId = $_.PrincipalId # get the PIM assignment settings if ($skipAssignmentSettings) { $assignmentSetting = $null } else { $assignmentSetting = $assignmentSettingList | ? { $_.ScopeId -eq $groupId -and $_.roleDefinitionId -eq $type } } $_ | select Id, CreatedDateTime, ModifiedDateTime, Status, GroupId, @{n = 'GroupName'; e = { ($translationList | ? Id -EQ $groupId).DisplayName } }, PrincipalId, @{n = 'PrincipalName'; e = { ($translationList | ? Id -EQ $principalId).DisplayName } }, AccessId, MemberType, ScheduleInfo, @{ n = 'Policy'; e = { $assignmentSetting.policy } } } } Export-ModuleMember -function Get-PIMGroup, Get-PIMGroupEligibleAssignment |