### FILE: scripts/Audit-CopilotChatEnablement.ps1 <# .SYNOPSIS Cross-cloud audit of Microsoft Teams Copilot Chat enablement signals across GCC, GCC High, and DoD tenants. .DESCRIPTION This script connects to a specified US Government Community Cloud instance (GCC, GCC High, or DoD) using the MicrosoftTeams PowerShell module and enumerates all Teams Messaging Policies and Meeting Policies to determine the current enablement state of Copilot Chat surfaces (1:1/Group Chat, Channels, Calls, Meetings). Because Teams PowerShell sessions are cloud-instance-specific and credentials do not roam across sovereign cloud boundaries, this script must be run once per cloud instance connection by an admin holding the appropriate role in that tenant. The report flags policies where transcription-dependent Copilot features (Calls/Meetings recap) may be blocked due to 'AllowTranscription' being disabled at the tenant or policy level -- a common inherited default in DoD-adjacent CMMC/NIST 800-171 hardening baselines. IMPORTANT: Property names such as AllowCopilotChat and AllowChannelSummary reflect the schema at time of writing (Sep 2026) and are subject to change post-GA. Always validate against: Get-CsTeamsMessagingPolicy | Get-Member -MemberType Property before relying on this script's output in a compliance report. .EXAMPLE .\Audit-CopilotChatEnablement.ps1 -CloudInstance GCCHigh -TenantAdminUPN admin@contoso.us Connects to the GCC High cloud instance as admin@contoso.us and exports a CSV audit report to the default C:\Reports path. .EXAMPLE .\Audit-CopilotChatEnablement.ps1 -CloudInstance DoD -TenantAdminUPN admin@contoso.mil -ReportPath 'D:\Audits\dod_copilot_audit.csv' Connects to the DoD cloud instance and writes the report to a custom path. .NOTES Author: Souhaiel Morhag Company: MSEndpoint.com Blog: https://msendpoint.com Academy: https://app.msendpoint.com/academy LinkedIn: https://linkedin.com/in/souhaiel-morhag GitHub: https://github.com/Msendpoint License: MIT #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet('GCC','GCCHigh','DoD')] [string]$CloudInstance, [Parameter(Mandatory = $true)] [string]$TenantAdminUPN, [Parameter(Mandatory = $false)] [string]$ReportPath = "C:\Reports\CopilotChat_Audit_$(Get-Date -Format 'yyyyMMdd_HHmm').csv" ) $ErrorActionPreference = 'Stop' $results = [System.Collections.Generic.List[Object]]::new() # Map cloud instance to the correct Teams PowerShell admin endpoint (reference only — # actual connection is handled via TeamsEnvironmentName below) $cloudEndpointMap = @{ 'GCC' = 'https://admin.teams.microsoft.com' 'GCCHigh' = 'https://admin.teams.microsoft.us' 'DoD' = 'https://admin.teams.microsoft.us' } try { # Ensure the report directory exists before we attempt to write to it $reportDir = Split-Path -Path $ReportPath -Parent if ($reportDir -and -not (Test-Path -Path $reportDir)) { New-Item -Path $reportDir -ItemType Directory -Force | Out-Null } Write-Host "[+] Connecting to Teams PowerShell — Cloud Instance: $CloudInstance ($($cloudEndpointMap[$CloudInstance]))" -ForegroundColor Cyan $connectParams = @{ AccountId = $TenantAdminUPN } # GCC uses the standard commercial cloud endpoint implicitly; GCC High and DoD require # explicit environment targeting so the module authenticates against the correct boundary switch ($CloudInstance) { 'GCCHigh' { $connectParams['TeamsEnvironmentName'] = 'TeamsGCCH' } 'DoD' { $connectParams['TeamsEnvironmentName'] = 'TeamsDOD' } } Connect-MicrosoftTeams @connectParams Write-Host "[+] Connected. Enumerating messaging and meeting policies..." -ForegroundColor Cyan # Pull ALL messaging policies — Copilot Chat surface toggle lives here in current builds $messagingPolicies = Get-CsTeamsMessagingPolicy foreach ($policy in $messagingPolicies) { # Property names below reflect current (Sep 2026) schema; validate against # Get-CsTeamsMessagingPolicy | Get-Member if Microsoft renames properties post-GA $copilotChatEnabled = $policy.AllowCopilotChat -as [bool] $channelSummaryEnabled = $policy.AllowChannelSummary -as [bool] $results.Add([PSCustomObject]@{ CloudInstance = $CloudInstance RecordType = 'MessagingPolicy' PolicyName = $policy.Identity AllowCopilotChat = $copilotChatEnabled AllowChannelSummary = $channelSummaryEnabled IsGlobalPolicy = ($policy.Identity -eq 'Global') AllowTranscription = $null AllowCloudRecording = $null CopilotDependencyMet = $null AuditTimestamp = (Get-Date).ToString('o') }) } # Cross-reference meeting policies for the transcription dependency gate — Calls and # Meetings Copilot recap features require AllowTranscription to be $true $meetingPolicies = Get-CsTeamsMeetingPolicy foreach ($mp in $meetingPolicies) { $results.Add([PSCustomObject]@{ CloudInstance = $CloudInstance RecordType = 'MeetingPolicy' PolicyName = $mp.Identity AllowCopilotChat = $null AllowChannelSummary = $null IsGlobalPolicy = ($mp.Identity -eq 'Global') AllowTranscription = $mp.AllowTranscription -as [bool] AllowCloudRecording = $mp.AllowCloudRecording -as [bool] CopilotDependencyMet = ($mp.AllowTranscription -eq $true) AuditTimestamp = (Get-Date).ToString('o') }) }