Workloads/Get-TeamsData.ps1
|
# Get-TeamsData.ps1 # Collects Teams, channels, guest access, and external access signals. # Part of the M365-QuickAssess module -- not exported. function Get-TeamsData { param ( $Assessment ) Write-Log "Collecting Teams data" # ------------------------------------------------------------------- # Teams and Channels # ------------------------------------------------------------------- try { $teams = Get-MgGroup -All ` -Filter "resourceProvisioningOptions/Any(x:x eq 'Team')" ` -Property Id,DisplayName ` -ErrorAction Stop $teamCount = $teams.Count $privateCount = 0 $sharedCount = 0 $checked = 0 foreach ( $team in $teams ) { $checked++ try { $channels = Invoke-MgGraphRequest ` -Method GET ` -Uri "https://graph.microsoft.com/v1.0/teams/$( $team.Id )/channels" ` -ErrorAction Stop foreach ( $ch in $channels.value ) { switch ( $ch.membershipType ) { "private" { $privateCount++ } "shared" { $sharedCount++ } } } } catch { Write-Log "Could not retrieve channels for team '$( $team.DisplayName )'" "WARN" } if ( $checked % 50 -eq 0 ) { Write-Log "Teams: processed $checked / $teamCount" } } $Assessment.Teams.TeamCount = $teamCount $Assessment.Teams.PrivateChannelCount = $privateCount $Assessment.Teams.HasPrivateChannels = ( $privateCount -gt 0 ) $Assessment.Teams.SharedChannelCount = $sharedCount $Assessment.Teams.HasSharedChannels = ( $sharedCount -gt 0 ) $Assessment.Summary.TeamCount = $teamCount Write-Log "Teams: Total=$teamCount PrivateChannels=$privateCount SharedChannels=$sharedCount" # ------------------------------------------------------------------- # Finding: Private channels # ------------------------------------------------------------------- if ( $privateCount -gt 0 ) { $Assessment.Findings += New-Finding ` -Type "PrivateChannels" ` -Summary "$privateCount private channels detected across $teamCount teams" ` -Category "Teams" ` -Severity "Medium" ` -Impact "Private channels have their own SharePoint site collections and separate membership. They require additional attention during migration." ` -Recommendation "Inventory private channels and validate membership and content migration separately." } # ------------------------------------------------------------------- # Finding: Shared channels # ------------------------------------------------------------------- if ( $sharedCount -gt 0 ) { $Assessment.Findings += New-Finding ` -Type "SharedChannels" ` -Summary "$sharedCount shared channels detected across $teamCount teams" ` -Category "Teams" ` -Severity "Medium" ` -Impact "Shared channels involve external tenant participants and may have cross-tenant dependencies that complicate migration." ` -Recommendation "Review shared channel memberships and notify external participants of the migration timeline." } # ------------------------------------------------------------------- # Finding: Large team count # ------------------------------------------------------------------- if ( $teamCount -gt 500 ) { $Assessment.Findings += New-Finding ` -Type "LargeTeamCount" ` -Summary "$teamCount Teams detected" ` -Category "Teams" ` -Severity "Medium" ` -Impact "A large number of Teams increases migration complexity and time." ` -Recommendation "Review Teams inventory and archive or delete inactive teams before migration." } } catch { Write-Log "Teams collection failed: $( $_.Exception.Message )" "ERROR" } # ------------------------------------------------------------------- # Guest Access Signal # ------------------------------------------------------------------- try { $authPolicy = Invoke-MgGraphRequest ` -Method GET ` -Uri "https://graph.microsoft.com/v1.0/policies/authorizationPolicy" ` -ErrorAction Stop $hasGuestAccess = $authPolicy.allowInvitesFrom -ne "none" $Assessment.Teams.HasTeamsGuestAccess = $hasGuestAccess Write-Log "Teams Guest Access: $hasGuestAccess (allowInvitesFrom=$( $authPolicy.allowInvitesFrom ))" if ( $hasGuestAccess ) { $Assessment.Findings += New-Finding ` -Type "TeamsGuestAccessEnabled" ` -Summary "Teams guest access is enabled" ` -Category "Teams" ` -Severity "Info" ` -Impact "Guest users in Teams do not migrate with standard tooling and will lose access post-migration if not re-invited in the target tenant." ` -Recommendation "Inventory Teams guest members and plan re-invitation in the target tenant." } } catch { Write-Log "Guest access signal failed: $( $_.Exception.Message )" "WARN" $Assessment.Teams.HasTeamsGuestAccess = $null } # ------------------------------------------------------------------- # External Access (Federation) -- best effort via Graph # ------------------------------------------------------------------- try { $crossTenantPolicy = Invoke-MgGraphRequest ` -Method GET ` -Uri "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy" ` -ErrorAction Stop $hasExternalAccess = $null -ne $crossTenantPolicy $Assessment.Teams.HasTeamsExternalAccess = $hasExternalAccess Write-Log "Teams External Access (cross-tenant policy): $hasExternalAccess" } catch { Write-Log "External access signal failed: $( $_.Exception.Message )" "WARN" $Assessment.Teams.HasTeamsExternalAccess = $null } # ------------------------------------------------------------------- # Teams Apps signal # ------------------------------------------------------------------- $Assessment.Teams.HasTeamsApps = $true } |