Collaboration/Get-TeamsAccessReport.ps1
|
<#
.SYNOPSIS Reports Microsoft Teams tenant-wide access and app settings. .DESCRIPTION Queries Microsoft Graph for Teams application settings and group-level configuration that governs guest access, third-party app policies, and sideloading. Uses the beta endpoint for Teams app settings and the v1.0 endpoint for group settings (guest access). Gracefully degrades if the beta endpoint is unavailable. Essential for M365 security assessments and Teams governance reviews. Requires Microsoft Graph connection with TeamSettings.Read.All permission. .PARAMETER OutputPath Optional path to export results as CSV. If not specified, results are returned to the pipeline. .EXAMPLE PS> . .\Common\Connect-Service.ps1 PS> Connect-Service -Service Graph -Scopes 'TeamSettings.Read.All' PS> .\Collaboration\Get-TeamsAccessReport.ps1 Displays Teams access and app settings in the console. .EXAMPLE PS> .\Collaboration\Get-TeamsAccessReport.ps1 -OutputPath '.\teams-access-settings.csv' Exports Teams access settings to CSV for documentation. #> [CmdletBinding()] param( [Parameter()] [ValidateNotNullOrEmpty()] [string]$OutputPath ) $ErrorActionPreference = 'Stop' # Verify Graph connection if (-not (Assert-GraphConnection)) { return } # Initialize result properties with defaults $allowGuestAccess = $null $allowGuestCreateUpdateChannels = $null $allowThirdPartyApps = $null $allowSideLoading = $null $isUserPersonalScopeResourceSpecificConsentEnabled = $null # Retrieve Teams app settings from beta endpoint try { Write-Verbose "Retrieving Teams app settings from beta endpoint..." $teamsAppSettings = Invoke-MgGraphRequest -Uri '/beta/teamwork/teamsAppSettings' -Method GET $allowSideLoading = $teamsAppSettings.isChatResourceSpecificConsentEnabled $isUserPersonalScopeResourceSpecificConsentEnabled = $teamsAppSettings.isUserPersonalScopeResourceSpecificConsentEnabled } catch { Write-Warning "Teams app settings (beta) endpoint unavailable. Some settings will be reported as N/A. Error: $_" } # Retrieve group settings for guest access configuration try { Write-Verbose "Retrieving group settings for guest access policies..." $groupSettingsResponse = Invoke-MgGraphRequest -Uri '/v1.0/groupSettings' -Method GET $groupSettingsList = $groupSettingsResponse.value $guestSettings = $null foreach ($setting in $groupSettingsList) { if ($setting.displayName -eq 'Group.Unified.Guest') { $guestSettings = $setting break } } # If no dedicated guest setting, check Group.Unified for guest values if (-not $guestSettings) { foreach ($setting in $groupSettingsList) { if ($setting.displayName -eq 'Group.Unified') { $guestSettings = $setting break } } } if ($guestSettings -and $guestSettings.values) { foreach ($valuePair in $guestSettings.values) { switch ($valuePair.name) { 'AllowGuestsToAccessGroups' { $allowGuestAccess = [System.Convert]::ToBoolean($valuePair.value) } 'AllowGuestsToBeGroupOwner' { # Captured but not primary output; useful context } 'AllowToAddGuests' { if ($null -eq $allowGuestAccess) { $allowGuestAccess = [System.Convert]::ToBoolean($valuePair.value) } } } } } } catch { Write-Warning "Failed to retrieve group settings for guest access. Guest access values may be incomplete. Error: $_" } # Try to get tenant-wide Teams settings via service-specific beta endpoint try { Write-Verbose "Retrieving tenant-wide Teams configuration..." $tenantConfig = Invoke-MgGraphRequest -Uri '/beta/teamwork' -Method GET if ($null -ne $tenantConfig) { if ($tenantConfig.PSObject.Properties.Name -contains 'isGuestAccessEnabled' -or $tenantConfig.ContainsKey('isGuestAccessEnabled')) { $allowGuestAccess = $tenantConfig.isGuestAccessEnabled } if ($tenantConfig.PSObject.Properties.Name -contains 'allowGuestCreateUpdateChannels' -or $tenantConfig.ContainsKey('allowGuestCreateUpdateChannels')) { $allowGuestCreateUpdateChannels = $tenantConfig.allowGuestCreateUpdateChannels } if ($tenantConfig.PSObject.Properties.Name -contains 'allowThirdPartyApps' -or $tenantConfig.ContainsKey('allowThirdPartyApps')) { $allowThirdPartyApps = $tenantConfig.allowThirdPartyApps } } } catch { Write-Verbose "Tenant-wide teamwork endpoint did not return extended properties (non-critical)." } # Build the report $report = @([PSCustomObject]@{ AllowGuestAccess = if ($null -ne $allowGuestAccess) { $allowGuestAccess } else { 'N/A' } AllowGuestCreateUpdateChannels = if ($null -ne $allowGuestCreateUpdateChannels) { $allowGuestCreateUpdateChannels } else { 'N/A' } AllowThirdPartyApps = if ($null -ne $allowThirdPartyApps) { $allowThirdPartyApps } else { 'N/A' } AllowSideLoading = if ($null -ne $allowSideLoading) { $allowSideLoading } else { 'N/A' } IsUserPersonalScopeResourceSpecificConsentEnabled = if ($null -ne $isUserPersonalScopeResourceSpecificConsentEnabled) { $isUserPersonalScopeResourceSpecificConsentEnabled } else { 'N/A' } }) Write-Verbose "Successfully compiled Teams access settings" if ($OutputPath) { $report | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 Write-Output "Exported Teams access settings to $OutputPath" } else { Write-Output $report } |