Mantra Reborn
Mantra Reborn

Reputation: 56

Using MS Azure API cost report with PowerShell

I've been trying to extract usage cost using Azure Cost Management API, i ran the API through Postman to test the URI's before injecting them into the powershell script. this is the POST method I used:

POST https://management.azure.com/subscriptions/0000000-0000-0000-0000-00000000/providers/Microsoft.CostManagement/generateCostDetailsReport?api-version=2022-10-01

{
  "metric": "ActualCost",
  "timePeriod": {
    "start": "2020-03-01",
    "end": "2020-03-15"
  }
}

I used this Microsoft API link as a reference : Generate Cost Details Report - Create Operation

POST response

according to Microsoft the result (cost management report) should be in an another URI that comes in this POST response within the Headers (Location), see first screenshot:

GET response

the link highlighted should be the one that I will be using to get the results for a signle subscriptions and it worked perfectly fine using Postman. However, now I want to use both methods (POST and GET) and rund them in a PS script that goes through subscriptions and generate/download the file automatically. this is the script that I was able to come up with :

# Step 1: Get mandatory parameters from the user
$startDate = Read-Host "Enter the start date (YYYY-MM-DD):"
$endDate = Read-Host "Enter the end date (YYYY-MM-DD):"

# Step 2: Connect to Azure and get subscriptions
Connect-AzAccount

$subscriptions = Get-AzSubscription | Select-Object -ExpandProperty SubscriptionId

# Step 3: Process each subscription
foreach ($subscriptionId in $subscriptions) {
    # Generate cost details report
    $generateReportUri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.CostManagement/generateCostDetailsReport?api-version=2022-10-01"

    $reportRequest = @{
        metric = "ActualCost"
        timePeriod = @{
            start = $startDate
            end = $endDate
        }
    }

    $reportResponse = Invoke-RestMethod -Uri $generateReportUri -Method Post -Body ($reportRequest | ConvertTo-Json) -Headers @{ "Authorization" = "Bearer $((Get-AzAccessToken).Token)" }

    # Get usage report URI
    $usageGet1Uri = $reportResponse.Headers.Location

    # Download and rename the usage report file
    $usageReport = Invoke-RestMethod -Uri $usageGet1Uri -Method Get -Headers @{ "Authorization" = "Bearer $((Get-AzAccessToken).Token)" }
    $blobLink = $usageReport.Manifest.blobs.blobLink
    $subscriptionName = (Get-AzSubscription -SubscriptionId $subscriptionId).Name
    $fileName = "$subscriptionName.csv"

    Invoke-WebRequest -Uri $blobLink -OutFile $fileName

    Write-Host "Downloaded and renamed usage report for subscription '$subscriptionName' to '$fileName'."
}

I want to make sure that I am getting both Headers.Location from POST method and the BlobLink from the reponse body from GET method, and I don't know whether I called them right in the script or not. This is the error that I got when I tried to run it on my environment:

Invoke-RestMethod : Cannot validate argument on parameter 'Uri'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At C:\Users\XXXXXX\VScode\POST_method_try.ps1:29 char:43

  • $usageReport = Invoke-RestMethod -Uri $usageGet1Uri -Method Get - ...
    
  •                                       ~~~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (:) [Invoke-RestMethod], ParameterBindingValidationException
    • FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeRestMethodCommand Invoke-WebRequest : Cannot validate argument on parameter 'Uri'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At C:\Users\XXXXXX\VScode\POST_method_try.ps1:34 char:28
  • Invoke-WebRequest -Uri $blobLink -OutFile $fileName
    
  •                        ~~~~~~~~~
    
    • CategoryInfo : InvalidData: (:) [Invoke-WebRequest], ParameterBindingValidationException
    • FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Upvotes: 1

Views: 1098

Answers (1)

Use Invoke-WebRequest instead for your first call,

$reportResponse = Invoke-WebRequest -Uri $generateReportUri -Method Post -Body ($reportRequest | ConvertTo-Json) -Headers @{ "Authorization" = "Bearer $((Get-AzAccessToken).Token)" }

Upvotes: 0

Related Questions