Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joerodgers/279dce21d0d205fea408cfda18946374 to your computer and use it in GitHub Desktop.
Save joerodgers/279dce21d0d205fea408cfda18946374 to your computer and use it in GitHub Desktop.
#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