Entra / Microsoft 365 · Groups
Find guests from blocked B2B domains
Report guest members in Microsoft 365 Groups whose email domains are blocked by the Entra ID B2B collaboration policy.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-ExchangeOnlineConnect-MgGraph -Scopes Directory.Read.All, Policy.Read.All
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
If ($Null -eq (Get-ConnectionInformation)) {Connect-ExchangeOnline}Connect-MgGraph -Scopes Directory.Read.All, Policy.Read.All# Define output file for report$OutputFile = "C:\Temp\BadGuestAccounts.csv"# Get Blocked domains from the Azure AD B2B Collaboration settings$Uri = "https://graph.microsoft.com/beta/legacy/policies/"[array]$Policies = Invoke-MgGraphRequest -Uri $Uri -Method Get$B2BPolicy = $Policies.Value | Where-Object {$_.displayName -eq "B2BManagementPolicy"}$Uri = ("https://graph.microsoft.com/beta/legacy/policies/{0}/definition" -f $B2BPolicy.id)$Data = Invoke-MgGraphRequest -Uri $Uri -Method Get$Policy = $Data.Value | ConvertFrom-Json[array]$BlockedDomains = $Policy.B2BManagementPolicy.InvitationsAllowedAndBlockedDomainsPolicy.BlockedDomainsIf ($BlockedDomains -eq $Null) {Write-Host "Looks like you have not configured any blocked domains" ; break}Else {Write-Host ("Checking Microsoft 365 Groups for guests from blocked domains {0}" -f ($BlockedDomains -join ", ")) }[array]$Groups = Get-UnifiedGroup -ResultSize Unlimited -Filter {GroupExternalMemberCount -gt 0}If (!($Groups)) { Write-Host "No Groups with external guests found"; break }$Report = [System.Collections.Generic.List[Object]]::new()CLS; $GroupNumber = 0ForEach ($Group in $Groups) {$GroupNumber++$ProgressBar = "Processing Group " + $Group.DisplayName + " (" + $GroupNumber + " of " + $Groups.Count + ")"Write-Progress -Activity "Checking Microsoft 365 Groups for guest members from blocked domains" -Status $ProgressBar -PercentComplete ($GroupNumber/$Groups.Count*100)$Members = Get-UnifiedGroupLinks -Identity $Group.ExternalDirectoryObjectId -LinkType Member | ? {$_.RecipientTypeDetails -eq "GuestMailUser" } | Select ExternalEmailAddress, DisplayName, ExternalDirectoryObjectIdForEach ($Guest in $Members) {$Domain = $Guest.ExternalEmailAddress.Split("@")[1]$GuestEmail = $Guest.ExternalEmailAddress.Split(":")[1]If ($BlockedDomains -contains $Domain) {Write-Host ("Found guest user {0} ({1}) in group {2}" -f $Guest.DisplayName, $GuestEmail, $Group.DisplayName) -foregroundcolor Red$GuestData = Get-MgUser -UserId $Guest.ExternalDirectoryObjectId$AccountAge = ($GuestData.CreatedDateTime | New-TimeSpan).Days$ReportLine = [PSCustomObject]@{Guest = $Guest.DisplayName"Guest Email" = $GuestEmailGroup = $Group.DisplayNameCreated = $CreationDate"Age in Days" = $AccountAge"ObjectId" = $Guest.ExternalDirectoryObjectId }$Report.Add($ReportLine)} # End if} #End ForEach Guest} #End Foreach Group# Get Unique set of guests and groups$BadGuests = $Report.Guest | Sort -unique$BadGroups = $Report.Group | Sort -unique$Report | Export-Csv -NotypeInformation $OutputFile# Output DetailsCLSWrite-Host "Report of Guest Accounts from Blocked Domains"Write-Host "---------------------------------------------"Write-Host ""Write-Host ("{0} Groups processed. {1} groups have guests from blocked domains, with a total of {2} guest accounts." -f $Groups.Count, $BadGroups.Count, $BadGuests.Count)Write-Host "-----------------------------------------------------------------------------------------------------------"Write-Host " "Write-Host ("Guest accounts from blocked domains: {0}" -f ($BadGuests -join ", "))Write-Host "-----------------------------------------------------------------------------------------------------------"Write-Host " "Write-Host "Problem Groups:"Write-Host "---------------"$BadGroupsWrite-Host " "Write-Host "Report data is available in" $OutputFile
Attribution
Author
Office365itpros