pwsh/dev/functions/processAADGroups.ps1 (119 lines of code) (raw):

function processAADGroups { if ($NoPIMEligibility) { Write-Host 'Resolving Microsoft Entra groups (for which a RBAC role assignment exists)' } else { Write-Host 'Resolving Microsoft Entra groups (for which a RBAC role assignment or PIM eligibility exists)' } Write-Host " Users known as Guest count: $($htUserTypesGuest.Keys.Count) (before resolving Microsoft Entra groups)" $startAADGroupsResolveMembers = Get-Date $roleAssignmentsforGroups = ($roleAssignmentsUniqueById.where( { $_.RoleAssignmentIdentityObjectType -eq 'Group' } ) | Select-Object -Property RoleAssignmentIdentityObjectId, RoleAssignmentIdentityDisplayname) | Sort-Object -Property RoleAssignmentIdentityObjectId -Unique $optimizedTableForAADGroupsQuery = [System.Collections.ArrayList]@() if ($roleAssignmentsforGroups.Count -gt 0) { foreach ($roleAssignmentforGroups in $roleAssignmentsforGroups) { $null = $optimizedTableForAADGroupsQuery.Add($roleAssignmentforGroups) } } $aadGroupsCount = ($optimizedTableForAADGroupsQuery).Count Write-Host " $aadGroupsCount Groups from RoleAssignments" if (-not $NoPIMEligibility) { $PIMEligibleGroups = $arrayPIMEligible.where({ $_.IdentityType -eq 'Group' }) | Select-Object IdentityObjectId, IdentityDisplayName | Sort-Object -Property IdentityObjectId -Unique $cntPIMEligibleGroupsTotal = 0 $cntPIMEligibleGroupsNotCoveredFromRoleAssignments = 0 foreach ($PIMEligibleGroup in $PIMEligibleGroups) { $cntPIMEligibleGroupsTotal++ if ($optimizedTableForAADGroupsQuery.RoleAssignmentIdentityObjectId -notcontains $PIMEligibleGroup.IdentityObjectId) { $cntPIMEligibleGroupsNotCoveredFromRoleAssignments++ $null = $optimizedTableForAADGroupsQuery.Add([PSCustomObject]@{ RoleAssignmentIdentityObjectId = $PIMEligibleGroup.IdentityObjectId RoleAssignmentIdentityDisplayname = $PIMEligibleGroup.IdentityDisplayName }) } } Write-Host " $cntPIMEligibleGroupsTotal groups from PIM eligibility; $cntPIMEligibleGroupsNotCoveredFromRoleAssignments groups added ($($cntPIMEligibleGroupsTotal - $cntPIMEligibleGroupsNotCoveredFromRoleAssignments) already covered in role assignments)" $aadGroupsCount = ($optimizedTableForAADGroupsQuery).Count Write-Host " $aadGroupsCount groups from role assignments and PIM eligibility" } if ($aadGroupsCount -gt 0) { switch ($aadGroupsCount) { { $_ -gt 0 } { $indicator = 1 } { $_ -gt 10 } { $indicator = 5 } { $_ -gt 50 } { $indicator = 10 } { $_ -gt 100 } { $indicator = 20 } { $_ -gt 250 } { $indicator = 25 } { $_ -gt 500 } { $indicator = 50 } { $_ -gt 1000 } { $indicator = 100 } { $_ -gt 10000 } { $indicator = 250 } } Write-Host " processing $($aadGroupsCount) Microsoft Entra groups (indicating progress in steps of $indicator)" $ThrottleLimitThis = $ThrottleLimit * 2 $batchSize = [math]::ceiling($optimizedTableForAADGroupsQuery.Count / $ThrottleLimitThis) Write-Host "Optimal batch size: $($batchSize)" $counterBatch = [PSCustomObject] @{ Value = 0 } $optimizedTableForAADGroupsQueryBatch = ($optimizedTableForAADGroupsQuery) | Group-Object -Property { [math]::Floor($counterBatch.Value++ / $batchSize) } Write-Host "Processing data in $($optimizedTableForAADGroupsQueryBatch.Count) batches" $optimizedTableForAADGroupsQueryBatch | ForEach-Object -Parallel { #$aadGroupIdWithRoleAssignment = $_ #region UsingVARs #fromOtherFunctions $AADGroupMembersLimit = $using:AADGroupMembersLimit $azAPICallConf = $using:azAPICallConf $scriptPath = $using:ScriptPath #Array&HTs $htAADGroupsDetails = $using:htAADGroupsDetails $arrayGroupRoleAssignmentsOnServicePrincipals = $using:arrayGroupRoleAssignmentsOnServicePrincipals $arrayGroupRequestResourceNotFound = $using:arrayGroupRequestResourceNotFound $arrayProgressedAADGroups = $using:arrayProgressedAADGroups $htAADGroupsExeedingMemberLimit = $using:htAADGroupsExeedingMemberLimit $indicator = $using:indicator $htUserTypesGuest = $using:htUserTypesGuest $htServicePrincipals = $using:htServicePrincipals #other $function:getGroupmembers = $using:funcGetGroupmembers #endregion UsingVARs foreach ($aadGroupIdWithRoleAssignment in $_.Group) { $uri = "$($azAPICallConf['azAPIEndpointUrls'].MicrosoftGraph)/beta/groups/$($aadGroupIdWithRoleAssignment.RoleAssignmentIdentityObjectId)/transitiveMembers/`$count" $method = 'GET' $aadGroupMembersCount = AzAPICall -AzAPICallConfiguration $azAPICallConf -uri $uri -method $method -currentTask "getGroupMembersCountTransitive $($aadGroupIdWithRoleAssignment.RoleAssignmentIdentityObjectId)" -listenOn 'Content' -consistencyLevel 'eventual' if ($aadGroupMembersCount -eq 'Request_ResourceNotFound') { $null = $script:arrayGroupRequestResourceNotFound.Add([PSCustomObject]@{ groupId = $aadGroupIdWithRoleAssignment.RoleAssignmentIdentityObjectId }) } else { if ($aadGroupMembersCount -gt $AADGroupMembersLimit) { Write-Host " Group exceeding limit ($($AADGroupMembersLimit)); memberCount: $aadGroupMembersCount; Group: $($aadGroupIdWithRoleAssignment.RoleAssignmentIdentityDisplayname) ($($aadGroupIdWithRoleAssignment.RoleAssignmentIdentityObjectId)); Members will not be resolved adjust the limit using parameter -AADGroupMembersLimit" $script:htAADGroupsDetails.($aadGroupIdWithRoleAssignment.RoleAssignmentIdentityObjectId) = @{ MembersAllCount = $aadGroupMembersCount MembersUsersCount = 'n/a' MembersGroupsCount = 'n/a' MembersServicePrincipalsCount = 'n/a' } } else { getGroupmembers -aadGroupId $aadGroupIdWithRoleAssignment.RoleAssignmentIdentityObjectId -aadGroupDisplayName $aadGroupIdWithRoleAssignment.RoleAssignmentIdentityDisplayname } } $null = $script:arrayProgressedAADGroups.Add($aadGroupIdWithRoleAssignment.RoleAssignmentIdentityObjectId) $processedAADGroupsCount = $null $processedAADGroupsCount = ($arrayProgressedAADGroups).Count if ($processedAADGroupsCount) { if ($processedAADGroupsCount % $indicator -eq 0) { Write-Host " $processedAADGroupsCount Microsoft Entra groups processed" } } } } -ThrottleLimit ($ThrottleLimitThis) } else { Write-Host " processing $($aadGroupsCount) Microsoft Entra groups" } $arrayGroupRequestResourceNotFoundCount = ($arrayGroupRequestResourceNotFound).Count if ($arrayGroupRequestResourceNotFoundCount -gt 0) { Write-Host "$arrayGroupRequestResourceNotFoundCount Groups could not be checked for Memberships" } Write-Host " processed $($arrayProgressedAADGroups.Count) Microsoft Entra groups" $endAADGroupsResolveMembers = Get-Date Write-Host "Resolving Microsoft Entra groups duration: $((New-TimeSpan -Start $startAADGroupsResolveMembers -End $endAADGroupsResolveMembers).TotalMinutes) minutes ($((New-TimeSpan -Start $startAADGroupsResolveMembers -End $endAADGroupsResolveMembers).TotalSeconds) seconds)" Write-Host " Users known as Guest count: $($htUserTypesGuest.Keys.Count) (after resolving Microsoft Entra groups)" }