All scripts
Governance 795
Get-TeamsGuestAccessReport
Audits every guest account in the tenant, which Teams they can reach, and how long ago they last signed in. Built for the periodic external-access review.
Get-TeamsGuestAccessReport.ps1
<#
.SYNOPSIS
Get-TeamsGuestAccessReport.ps1 - Audits guest access across Microsoft Teams.
.DESCRIPTION
Lists every guest account in the tenant, which Teams they belong to, and how
long ago they last signed in. Built for the periodic external-access review
most compliance frameworks ask for. Requires Graph scope: User.Read.All,
Team.ReadBasic.All, TeamMember.Read.All
.AUTHOR
Shehryar Hassan
.EXAMPLE
.\Get-TeamsGuestAccessReport.ps1 -OutputPath ".\GuestAccessReport.csv"
#>
param(
[Parameter(Mandatory=$false)]
[string]$OutputPath = ".\GuestAccessReport.csv"
)
Write-Host "=============================================" -ForegroundColor Cyan
Write-Host " Teams Guest Access Report" -ForegroundColor Cyan
Write-Host "=============================================" -ForegroundColor Cyan
if (-not (Get-MgContext)) {
Write-Host "[INFO] Connecting to Microsoft Graph..." -ForegroundColor Yellow
Connect-MgGraph -Scopes "User.Read.All", "Team.ReadBasic.All", "TeamMember.Read.All"
}
Write-Host "[INFO] Pulling guest users..." -ForegroundColor Gray
$guests = Get-MgUser -Filter "userType eq 'Guest'" -All -Property Id, DisplayName, Mail, CreatedDateTime, SignInActivity
Write-Host "[INFO] Pulling teams and matching guest membership (this takes a while on large tenants)..." -ForegroundColor Gray
$teams = Get-MgTeam -All
$report = foreach ($guest in $guests) {
$memberOf = foreach ($team in $teams) {
$isMember = Get-MgTeamMember -TeamId $team.Id -Filter "microsoft.graph.aadUserConversationMember/userId eq '$($guest.Id)'" -ErrorAction SilentlyContinue
if ($isMember) { $team.DisplayName }
}
[PSCustomObject]@{
DisplayName = $guest.DisplayName
Email = $guest.Mail
CreatedOn = $guest.CreatedDateTime
LastSignIn = $guest.SignInActivity.LastSignInDateTime
TeamsAccess = ($memberOf -join "; ")
}
}
$report | Export-Csv -Path $OutputPath -NoTypeInformation
Write-Host "[SUCCESS] $($guests.Count) guest account(s) written to: $OutputPath" -ForegroundColor Green
$stale = $report | Where-Object { -not $_.LastSignIn -or ([datetime]$_.LastSignIn -lt (Get-Date).AddDays(-90)) }
if ($stale) {
Write-Host "[WARNING] $($stale.Count) guest(s) with no sign-in in 90+ days, candidates for removal:" -ForegroundColor Red
}Read it before you run it, and test in a safe tenant first.