Public/Write-AdvancedCriteriaBasedGroupMemberOfButNotMemberOf.ps1
<# .DESCRIPTION Helper function to simplify the common task of adding members to a group based on the members of other groups, but only if they are not member of some other groups. .EXAMPLE # Writes members of groups 22222222-2222-2222-2222-222222222222 and 33333333-3333-3333-3333-333333333333 to group 11111111-1111-11111-1111-111111111111, but only if they are not member of group 44444444-4444-4444-4444-444444444444 Write-AdvancedCriteriaBasedGroupMemberOfButNotMemberOfGroup ` -DestinationGroup "11111111-1111-1111-1111-111111111111" ` -MemberOfGroups "22222222-2222-2222-2222-222222222222", "33333333-3333-3333-3333-333333333333" ` -ButNotMemberOfGroups "44444444-4444-4444-4444-444444444444" #> function Write-AdvancedCriteriaBasedGroupMemberOfButNotMemberOfGroup { [CmdletBinding(SupportsShouldProcess = $true)] Param( [Parameter(Mandatory = $true)] $DestinationGroup, [Parameter(Mandatory = $true)] [String[]] $MemberOfGroups, [Parameter(Mandatory = $false)] [String[]] $ButNotMemberOfGroups = @() ) Process { # Get existing members Write-Debug "Getting existing members of group $DestinationGroup" $DestinationGroupMembers = (Get-MgGroupMember -GroupId $DestinationGroup -All | Group-Object -AsHashTable -Property id) ?? @{} Write-Debug "Getting members of 'member of groups'" $MemberOfGroupsMembers = $MemberOfGroups | ForEach-Object { Write-Verbose "Getting members of 'member of group' $($_)" Get-MgGroupMember -GroupId $_ -All } | Select-Object -Unique -Property id $ButNotMemberOfGroupsMembers = $ButNotMemberOfGroups ? (($ButNotMemberOfGroups | ForEach-Object { Write-Debug "Getting members of 'but not member of group' $($_)" Get-MgGroupMember -GroupId $_ -All } | Select-Object -Unique -Property id | Group-Object -AsHashTable -Property id) ?? @{}) : @{} # Calculate expected members $ExpectedMembers = ($MemberOfGroupsMembers | Where-Object { -not $ButNotMemberOfGroupsMembers.ContainsKey($_.id) } | Group-Object -AsHashTable -Property id) ?? @{} Write-Verbose "Expected member count for group $DestinationGroup : $($ExpectedMembers.Count)" # Make sure expected members are in the destination group $ExpectedMembers.GetEnumerator() | Where-Object { !$DestinationGroupMembers.ContainsKey($_.key) } | ForEach-Object { if ($PSCmdlet.ShouldProcess($DestinationGroup, "Add member $($_.key)")) { New-MgGroupMember -GroupId $DestinationGroup -DirectoryObjectId $_.key } else { Write-Verbose "Adding member $($_.key) to group $DestinationGroup" } } # Remove members that are not expected $MembersToRemove = $DestinationGroupMembers.GetEnumerator() | Where-Object { !$ExpectedMembers.ContainsKey($_.key) } if ($MembersToRemove) { $MembersToRemove | ForEach-Object { if ($PSCmdlet.ShouldProcess($DestinationGroup, "Remove member $($_.key)")) { Remove-MgGroupMemberByRef -GroupId $DestinationGroup -DirectoryObjectId $_.key } else { Write-Verbose "Removing member $($_.key) from group $DestinationGroup" } } } } } |