Created
September 8, 2026 20:03
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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