Skip to content

Instantly share code, notes, and snippets.

@joerodgers
Created September 8, 2026 20:03
Show Gist options
  • Select an option

  • Save joerodgers/534381255f4507d45297ec38579af352 to your computer and use it in GitHub Desktop.

Select an option

Save joerodgers/534381255f4507d45297ec38579af352 to your computer and use it in GitHub Desktop.
Example script that pulls Power Platform billing policies and the associated Azure Resource Group "CostCenter" tag value
#requries -modules "Az.Accounts"
function Get-AccessToken
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)]
[string]
$ResourceUrl
)
if (-not (Get-AzContext))
{
Write-Host "No Azure context - launching sign-in..." -ForegroundColor Yellow
Connect-AzAccount -WarningAction SilentlyContinue | Out-Null
}
$azAccessToken = Get-AzAccessToken -ResourceUrl $ResourceUrl -WarningAction SilentlyContinue
if ($azAccessToken.Token -is [System.Security.SecureString])
{
return [System.Net.NetworkCredential]::new('', $azAccessToken.Token).Password
}
return $azAccessToken.Token
}
function Get-ResourceGroup
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)]
[Guid]
$SubscriptionId
)
begin
{
$accessToken = Get-AccessToken -ResourceUrl "https://api.powerplatform.com/"
$headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json"; "Accept" = "application/json" }
$skipToken = ""
$skip = 0
$top = 1000
$resourceQueryTemplate = @'
{{
"Options": {{
"Top": {0},
"Skip": {1},
"SkipToken": "{2}"
}},
"TableName": "resourcecontainers",
"Clauses": [
{{
"$type": "where",
"FieldName": "type",
"Operator": "==",
"Values": [ "'microsoft.resources/subscriptions/resourcegroups'" ]
}},
{{
"$type": "where",
"FieldName": "subscriptionId",
"Operator": "==",
"Values": [ "'{3}'" ]
}},
{{
"$type": "project",
"FieldList": [
"resourceGroup",
"subscriptionId",
"tags",
"name"
]
}}
]
}}
'@
}
process
{
$uri = "https://api.powerplatform.com/resourcequery/resources/query?api-version=2022-03-01-preview"
$page = 0
$resources = do
{
$page++
Write-Verbose "[$(Get-Date)] - Querying Power Platform resources, page $page."
$body = $resourceQueryTemplate -f $top, $skip, $skipToken, $SubscriptionId
$response = Invoke-RestMethod -Method Post -Uri $uri -Body $body -Headers $headers -Verbose:$false
$skipToken = $response.skipToken
$skip += $top
$response.data
}
while( $skipToken )
return $resources
$resources = foreach( $resource in $resources )
{
[PSCustomObject] @{
ResourceType = $resource.resourceType
ResourceName = $resource.resourceName
ResourceId = $resource.resourceId
EnvironmentId = $resource.environmentId
EnvironmentName = $resource.environmentName
EnvironmentRegion = $resource.environmentRegion
EnvironmentType = $resource.environmentType
EnvironmentIsManaged = $resource.isManagedEnvironment
EnvironmentGroupId = $resource.environmentGroupId
EnvironmentGroupName = $resource.environmentGroupName
ResourceCreatedAt = $resource.properties.createdAt
ResourceCreatedBy = $resource.properties.createdBy
ResourceOwnerId = $resource.properties.ownerId
ResourceLastPublishedAt = $resource.properties.lastPublishedAt
}
}
if( $IncludeAgentResources.IsPresent )
{
$rows = @($resources | where-object -Property ResourceType -ne "Agent Workflow")
Write-Verbose "[$(Get-Date)] - Discovered $($rows.Count) Power Platform Agent resources."
}
if( $IncludeWorkflowResources.IsPresent )
{
$rows = @($resources | where-object -Property ResourceType -eq "Agent Workflow")
Write-Verbose "[$(Get-Date)] - Discovered $($rows.Count) Power Platform Workflow resources."
}
$resources
}
end
{
}
}
function Get-BillingPolicyResourceGroupDetail
{
[CmdletBinding()]
param
(
)
begin
{
$accessToken = Get-AccessToken -ResourceUrl "https://api.powerplatform.com/"
$headers = @{ "Authorization" = "Bearer $accessToken"; "Content-Type" = "application/json"; "Accept" = "application/json" }
}
process
{
$uri = 'https://api.powerplatform.com/licensing/billingPolicies?api-version=2024-10-01'
$response = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -ErrorAction Stop -Verbose:$false
$policies = foreach( $billingpolicy in $response.value )
{
foreach( $env in $billingpolicy.environmentIds )
{
[PSCustomObject] @{
Id = $billingpolicy.id
Name = $billingpolicy.name
Type = $billingpolicy.type
Status = $billingpolicy.status
Location = $billingpolicy.location
EnvironmentId = $env
CreatedOn = $billingpolicy.createdOn
CreatedBy = $billingpolicy.createdBy.id
LastModifiedOn = $billingpolicy.lastModifiedOn
LastModifiedBy = $billingpolicy.lastModifiedBy.id
ResourceGroup = $billingpolicy.billingInstrument.resourceGroup
SubscriptionId = $billingpolicy.billingInstrument.subscriptionId
CostCenter = ""
}
}
}
$resourceGroups = foreach( $subscription in $policies.SubscriptionId | Select-Object -Unique )
{
Get-ResourceGroup -SubscriptionId $subscription
}
foreach( $policy in $policies )
{
if( $resourceGroup = $resourceGroups | Where-Object -Property subscriptionId -eq $policy.SubscriptionId | Where-Object -Property resourceGroup -eq $policy.ResourceGroup )
{
$policy.CostCenter = $resourceGroup.tags.CostCenter
}
}
return $policies
}
end
{
}
}
Get-BillingPolicyResourceGroupDetail
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment