All scripts
Microsoft 365 733
Get-PowerBIWorkspaceAccessReport
Exports every Power BI workspace along with its members and their access level, so you can spot workspaces with too many admins or external accounts still sitting in them.
Get-PowerBIWorkspaceAccessReport.ps1
<#
.SYNOPSIS
Reports on Power BI workspace membership and access levels across the tenant.
.DESCRIPTION
Connects to the Power BI service and pulls every workspace along with its members,
then exports a CSV showing who has Admin, Member, Contributor, or Viewer access to
each one. Useful for spotting workspaces with too many admins, or external accounts
that were added once for a project and never removed.
.AUTHOR
Shehryar Hassan
.EXAMPLE
.\Get-PowerBIWorkspaceAccessReport.ps1 -OutputPath "C:\Reports\PowerBIAccess.csv"
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[string]$OutputPath = ".\PowerBIWorkspaceAccessReport.csv",
[Parameter(Mandatory = $false)]
[switch]$IncludePersonalWorkspaces
)
if (-not (Get-Module -ListAvailable -Name MicrosoftPowerBIMgmt)) {
Write-Host "The MicrosoftPowerBIMgmt module is not installed. Run: Install-Module -Name MicrosoftPowerBIMgmt -Scope CurrentUser" -ForegroundColor Yellow
return
}
Import-Module MicrosoftPowerBIMgmt -ErrorAction Stop
try {
Connect-PowerBIServiceAccount -ErrorAction Stop | Out-Null
}
catch {
Write-Host "Could not connect to the Power BI service. $_" -ForegroundColor Red
return
}
Write-Host "Pulling workspace list, this can take a minute on larger tenants..."
$workspaces = Get-PowerBIWorkspace -Scope Organization -All
if (-not $IncludePersonalWorkspaces) {
$workspaces = $workspaces | Where-Object { $_.Type -eq "Workspace" }
}
$results = New-Object System.Collections.Generic.List[Object]
foreach ($workspace in $workspaces) {
Write-Host "Checking $($workspace.Name)..."
try {
$users = Get-PowerBIWorkspaceUser -Scope Organization -Id $workspace.Id -ErrorAction Stop
}
catch {
Write-Host " Skipped $($workspace.Name), could not read membership. $_" -ForegroundColor Yellow
continue
}
if (-not $users -or $users.Count -eq 0) {
$results.Add([PSCustomObject]@{
WorkspaceName = $workspace.Name
WorkspaceId = $workspace.Id
WorkspaceState = $workspace.State
UserPrincipalName = "(no members returned)"
AccessRight = ""
UserType = ""
})
continue
}
foreach ($user in $users) {
$results.Add([PSCustomObject]@{
WorkspaceName = $workspace.Name
WorkspaceId = $workspace.Id
WorkspaceState = $workspace.State
UserPrincipalName = $user.Identifier
AccessRight = $user.AccessRight
UserType = $user.PrincipalType
})
}
}
$results | Sort-Object WorkspaceName, AccessRight | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
$adminCount = ($results | Where-Object { $_.AccessRight -eq "Admin" }).Count
Write-Host ""
Write-Host "Done. $($workspaces.Count) workspaces checked, $($results.Count) membership rows exported to $OutputPath"
Write-Host "$adminCount rows have Admin access, worth a look if that number seems high for your tenant size."
Disconnect-PowerBIServiceAccount | Out-Null
Read it before you run it, and test in a safe tenant first.