Created
August 2, 2021 18:56
-
-
Save joerodgers/279dce21d0d205fea408cfda18946374 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -Modules MicrosoftTeams, Microsoft.Graph.Groups, Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore | |
function Split-Array | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true)] | |
[object[]]$Array, | |
[Parameter(Mandatory=$true)] | |
[int]$Size | |
) | |
begin | |
{ | |
$maxChunks = [Math]::Ceiling( ($Array.Count/$Size) ) | |
$chunks = New-Object object[] $maxChunks | |
} | |
process | |
{ | |
Write-Verbose "$(Get-Date) - Total Chunks: $maxChunks" | |
for($i = 0; $i -lt $maxChunks; $i++ ) | |
{ | |
$sourceIndex = $i * $Size | |
$length = [Math]::Min( ($Array.Length - $sourceIndex), $Size) | |
$chunk = New-Object object[] $length | |
[Array]::Copy($Array, $sourceIndex, $chunk, 0 <# destinationIndex #>, $length) | |
$chunks[$i] = $chunk | |
} | |
} | |
end | |
{ | |
return ,$chunks | |
} | |
} | |
function Get-TeamsAppPermissionPolicyMember | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true)] | |
[string]$TeamsAppPermissionPolicyName | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
Write-Verbose "$(Get-Date) - Querying memembers of TeamsAppPermissionPolicy '$TeamsAppPermissionPolicy'" | |
Get-CsOnlineUser | Where-Object -Property TeamsAppPermissionPolicy -eq $TeamsAppPermissionPolicyName | |
Write-Verbose "$(Get-Date) - Querying memembers of TeamsAppPermissionPolicy '$TeamsAppPermissionPolicy' completed" | |
} | |
end | |
{ | |
} | |
} | |
function Get-GroupMember | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true)] | |
[string[]]$GroupId | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
$totalMembers = 0 | |
$GroupId | Foreach-Object { | |
Write-Verbose "$(Get-Date) - Querying memembers of group '$GroupId'" | |
$members = @(Get-MgGroupMember -GroupId $_ -All) | |
$members | |
$totalMembers += $members.Count | |
Write-Verbose "$(Get-Date) - Querying memembers of group '$GroupId' completed. Member count: $($members.Count)" | |
} | |
Write-Verbose "$(Get-Date) - Total group members: $totalMembers" | |
} | |
end | |
{ | |
} | |
} | |
function Get-TeamsAppPermissionPolicyMembersToAdd | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true)] | |
[string[]]$PolicyMemberObjectIds, | |
[Parameter(Mandatory=$true)] | |
[string[]]$GroupMemberObjectIds | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
$objectsIds = @(Compare-Object -ReferenceObject $PolicyMemberObjectIds -DifferenceObject $GroupMemberObjectIds | Where-Object -Property SideIndicator -eq "=>" | Select-Object -ExpandProperty InputObject) | |
$objectsIds | |
Write-Verbose "$(Get-Date) - Teams App Permission Policy Members To Add: $($objectsIds.Count)" | |
} | |
end | |
{ | |
} | |
} | |
function Get-TeamsAppPermissionPolicyMembersToRemove | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true)] | |
[string[]]$PolicyMemberObjectIds, | |
[Parameter(Mandatory=$true)] | |
[string[]]$GroupMemberObjectIds | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
$objectsIds = @(Compare-Object -ReferenceObject $PolicyMemberObjectIds -DifferenceObject $GroupMemberObjectIds | Where-Object -Property SideIndicator -eq "<=" | Select-Object -ExpandProperty InputObject) | |
$objectsIds | |
Write-Verbose "$(Get-Date) - Teams App Permission Policy Members To Remove: $($objectsIds.Count)" | |
} | |
end | |
{ | |
} | |
} | |
function Wait-BatchPolicyAssignmentOperationComplete | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true)] | |
[ValidateRange(1,50)] | |
[int]$MaxConcurrentBatches | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
Write-Verbose "$(Get-Date) - Teams App Permission Policy Members To Remove: $($objectsIds.Count)" | |
$batches = @(Get-CsBatchPolicyAssignmentOperation | Where-Object -Property OverallStatus -ne "Completed") | |
while( $null -ne $batches -and $batches.Count -ge $MaxConcurrentBatches ) | |
{ | |
Write-Warning "$(Get-Date) - $($batches.Count) batches executing, waiting for $($batches.Count - $($MaxConcurrentBatches-1)) batch operations to complete before scheduling next batch operation." | |
Start-Sleep -Seconds 5 | |
$batches = @(Get-CsBatchPolicyAssignmentOperation | Where-Object -Property OverallStatus -ne "Completed") | |
} | |
} | |
end | |
{ | |
} | |
} | |
function Sync-TeamsAppPermissionPolicyMembers | |
{ | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Mandatory=$true)] | |
[string]$TeamsAppPermissionPolicy, | |
[Parameter(Mandatory=$false)] | |
[AllowEmptyCollection()] | |
[string[]]$ObjectIdsToAdd, | |
[Parameter(Mandatory=$false)] | |
[AllowEmptyCollection()] | |
[string[]]$ObjectIdsToRemove, | |
[Parameter(Mandatory=$false)] | |
[ValidateRange(1,5000)] | |
[int]$BatchSize = 5000, | |
[Parameter(Mandatory=$false)] | |
[ValidateRange(1,50)] | |
[int]$MaxConcurrentBatches = 50 | |
) | |
begin | |
{ | |
} | |
process | |
{ | |
if( $PSBoundParameters.ContainsKey("ObjectIdsToRemove") -and $ObjectIdsToRemove.Count -gt 0 ) | |
{ | |
Write-Verbose "$(Get-Date) - Processing $($ObjectIdsToRemove.Count) removal objects" | |
$counter = 1 | |
$chunks = Split-Array -Array $ObjectIdsToRemove -Size $BatchSize | |
foreach( $chunk in $chunks ) | |
{ | |
Wait-BatchPolicyAssignmentOperationComplete -MaxConcurrentBatches $MaxConcurrentBatches | |
$operationName = "Teams App Permission Policy Removal - Chunk $counter of $($chunks.Count)" | |
Write-Verbose "$(Get-Date) - Creating New CsBatchPolicyAssignmentOperation: $operationName" | |
$null = New-CsBatchPolicyAssignmentOperation -PolicyType TeamsAppPermissionPolicy -PolicyName $null -Identity $chunk -OperationName $operationName | |
$counter++ | |
} | |
} | |
if( $PSBoundParameters.ContainsKey("ObjectIdsToAdd") -and $ObjectIdsToAdd.Count -gt 0 ) | |
{ | |
Write-Verbose "$(Get-Date) - Processing $($ObjectIdsToAdd.Count) addition objects" | |
$counter = 1 | |
$chunks = Split-Array -Array $ObjectIdsToAdd -Size $BatchSize | |
foreach( $chunk in $chunks ) | |
{ | |
Wait-BatchPolicyAssignmentOperationComplete -MaxConcurrentBatches $MaxConcurrentBatches | |
$operationName = "Teams App Permission Policy Addition - Chunk $counter of $($chunks.Count)" | |
Write-Verbose "$(Get-Date) - Creating New CsBatchPolicyAssignmentOperation: $operationName" | |
$null = New-CsBatchPolicyAssignmentOperation -PolicyType TeamsAppPermissionPolicy -PolicyName $teamsAppPermissionPolicyName -Identity $chunk -OperationName $operationName | |
$counter++ | |
} | |
} | |
} | |
end | |
{ | |
} | |
} | |
<# Secret store config | |
Register-SecretVault -Name "TeamsAutomation" -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault | |
Set-SecretStoreConfiguration -Authentication None -Scope CurrentUser | |
Set-Secret -Name "TeamsAutomationAccountPassword" -SecureStringSecret (ConvertTo-SecureString -Force -AsPlainText -String "xxxxxxxxxxxxxxxxxxx" ) -Vault "TeamsAutomation" -NoClobber | |
#> | |
$clientId = $env:O365_CLIENTID | |
$thumbprint = $env:O365_THUMBPRINT | |
$tenantId = $env:O365_TENANTID | |
$groupIds = 'fd1ae607-2c48-48b3-a715-7a9f83c53ff5', # Group 1 | |
'fd401dc3-d1eb-489d-ac9e-dd8fac8204cf' # Group 2 | |
$teamsAppPermissionPolicyName = "Connections Policy" | |
$automationAccountUserName = "john.doe@contoso.onmicrosoft.com" | |
$automationAccountPassword = Get-Secret -Name "TeamsAutomationAccountPassword" | |
Connect-MgGraph ` | |
-ClientId $clientId ` | |
-CertificateThumbprint $thumbprint ` | |
-TenantId $tenantId | Out-Null | |
Connect-MicrosoftTeams ` | |
-Credential ([PSCredential]::new( $automationAccountUserName, $automationAccountPassword)) | Out-Null | |
# get all group members | |
$groupMemberObjectIds = @(Get-GroupMember -GroupId $groupIds | Select-Object -ExpandProperty Id -Unique) | |
# get all users in the Teams App Permission Policy | |
$policyMemberObjectIds = @(Get-TeamsAppPermissionPolicyMember -TeamsAppPermissionPolicyName $teamsAppPermissionPolicyName | Select-Object -ExpandProperty ObjectId | Select-Object -ExpandProperty Guid) | |
# get all users to remove | |
$memberObjectIdsToRemove = Get-TeamsAppPermissionPolicyMembersToRemove -GroupMemberObjectIds $groupMemberObjectIds -PolicyMemberObjectIds $policyMemberObjectIds -Verbose | |
# get all users to add | |
$memberObjectIdsToAdd = Get-TeamsAppPermissionPolicyMembersToAdd -GroupMemberObjectIds $groupMemberObjectIds -PolicyMemberObjectIds $policyMemberObjectIds -Verbose | |
# execute sequential sync | |
Sync-TeamsAppPermissionPolicyMembers -TeamsAppPermissionPolicy $teamsAppPermissionPolicyName -ObjectIdsToAdd $memberObjectIdsToAdd -ObjectIdsToRemove $memberObjectIdsToRemove -BatchSize 2000 -MaxConcurrentBatches 50 -Verbose | |
# disconnect from cloud services | |
Disconnect-MgGraph -ErrorAction Ignore | |
Disconnect-MicrosoftTeams -ErrorAction Ignore |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment