Skip to main content

Inventory Flows By Creator

Author: Pete Skelly

The Power Automate Admin Center provides a list of the Flows in your tenant, but there is no way to easily export Flows from the Flow admin center for governance activities. This script retrieves Flows from the Default Environment and maps creator information from Microsoft Entra ID to list Flows by owner, state and trigger type.

The bash version of this script uses an external file to process owner mapping. This is provided in the jq tab and should be saved to the same folder as the bash script and named merge.jq.

#!/usr/local/bin/pwsh -File

$DIR = Split-Path $script:MyInvocation.MyCommand.Path
$TMP_DIR = "./tmp"
$TMP_FLOWS = "$TMP_DIR/flows.json"
$FLOWSCSV = "flows.csv"

function CleanDistFolder {
# Remove the dist folder as needed
if (Test-Path -Path "$TMP_DIR" -PathType Container) {
Remove-Item -Path "$TMP_DIR" -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue
}
}

$CURRENT_USER = $(m365 status).Split(':')[1]
Write-Host "Logged in as $CURRENT_USER"

try {
if (-not (Test-Path -Path "$TMP_DIR" -PathType Container)) {
Write-Host " Creating $TMP_DIR folder..."
New-Item -ItemType Directory -Path "$TMP_DIR"
}

#Step 1 - Get the default environment
Write-Host "Querying for default Flow environment..."
$flowEnvironments = m365 flow environment list --output json | ConvertFrom-Json
$defaultEnvironment = $flowEnvironments[0].name
Write-Host "Found default environment $defaultEnvironment, querying Flows..."

# Step 2 - Get all of the flows using the cli and write flows json to a tmp file
# Use a JMESPath query to filter the size of the file. See https://github.com/pnp/cli-microsoft365/issues/1266
m365 flow list --environmentName $defaultEnvironment `
--query '[].{name: name, displayName: properties.displayName,owner: properties.creator.userId, state: properties.state, created: properties.createdTime, lastModified: properties.lastModifiedTime, trigger: properties.definitionSummary.triggers[0].swaggerOperationId, triggerType: properties.definitionSummary.triggers[0].type }' --asAdmin --output json |
Out-File "$TMP_FLOWS" -Encoding ASCII
$flows = Get-Content "$TMP_FLOWS" | ConvertFrom-Json

#Step 3 - Get a unique list of the flow owners from the tmp file
Write-Host "Flows found, searching for owner values..."
$uniqueOwners = $flows.owner | Sort-Object | Get-Unique
Write-Host "There are $($uniqueOwners.Count) unique Flows owners."
Write-Host "Building owner information mappings..."

#Step 4 - map properties.creator.userId's to {name, email} mapping hashtable
Write-Host "Querying graph for userids..."
$userMap = @{}
$uniqueOwners | ForEach-Object {
Write-Host "Querying graph for userid $_..."
m365 entra user get --id $_ --output json | ConvertFrom-Json
} | ForEach-Object {
$userMap.Add($_.id, @{
upn = $_.userPrincipalName
displayName = $_.displayName
mail = $_.mail
}
)
}
# And add the Owner information to each flow entry to get owner name and email
Write-Host "Mapping owner information..."
$flows | ForEach-Object {
$_ | Add-Member -MemberType NoteProperty -Name "upn" -Value $userMap[$_.owner].upn
$_ | Add-Member -MemberType NoteProperty -Name "ownerName" -Value $userMap[$_.owner].displayName
$_ | Add-Member -MemberType NoteProperty -Name "ownerMail" -Value $userMap[$_.owner].mail
}

#Step 5 - Create a CSV file with header row, flow information and owner email
$flows | Export-Csv -Path "$FLOWSCSV" -NoTypeInformation

}
finally {
CleanDistFolder
}

# if we are on macOS try opening the file with Excel
if ($IsMacOS) {
$answer = Read-Host -Prompt "Open CSV file in Excel? (y/n)"
switch ($answer)
{
y {
open -a "/Applications/Microsoft Excel.app" "$DIR/$FLOWSCSV"
}
Default {
Write-Host "Open $DIR/$FLOWSCSV to review report."
}
}
}
CTRL + M