skip to Main Content

I have a PowerShell script that calls the Microsoft Azure API for cost management.

I first call:

https://management.azure.com/providers/Microsoft.Billing/enrollmentAccounts/*****5/providers/Microsoft.CostManagement/generateCostDetailsReport?api-version=2023-08-01"

This returns a 202 as expected:

StatusCode : 202
StatusDescription : Accepted
Content : {}
RawContent : HTTP/1.1 202 Accepted
Pragma: no-cache

I then extract the header location and poll until I get a 200

StatusCode        : 200
StatusDescription : OK
Content           :           {"id":"/providers/Microsoft.Billing/enrollmentAccounts/7****5/providers/Microsoft.CostManagement/costDetail   sOperationResults/ca4f*******-d8bff1dbf7c2","name":"ca4f85f****-d8bff1...
RawContent        : HTTP/1.1 200 OK
                Pragma: no-cache
                Vary: Accept-Encoding
                session-id: ae0a1b9b-2d21********6136a55bcb
                x-ms-request-id: d2f**********85-8d7f54a02fb7
                x-ms-correlation-request-id: 23b94e5d...
Forms             : {}
Headers           : {[Pragma, no-cache], [Vary, Accept-Encoding], [session-id, ae0a1b9b-2d21-4088-82f4-      106136a55bcb], [x-ms-request-id, d2f0ab18-e34c-*****4a02fb7]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 935

The problem is that I'm expecting a blob location to be returned but it isn't. 
Any guidance would be greatly appreciated. 

The blob location should be in the Manifest section 
i.e ......Manifest.blobs.blobLink


I 


I've tried different versions of the API be all return the same. 
I'm sure it's something I'm doing wrong.

2

Answers


  1. Chosen as BEST ANSWER

    Many thanks for your response. Looking at your code I realised I had a difference. I was using Invoke-Webrequest when I was looking for the blob location when it should have been Invoke-RestMethod. Making this single change returns the required Blob Location details. id : /providers/Microsoft.Billing/enrollmentAccounts/75/providers/Microsoft.CostManagement/costDetailsOperationResults/9bb4efc1-e5f-0afdaec988b8 name : 9bb4efc1-4b4e-49****daec988b8 status : Completed manifest : @{manifestVersion=2022-05-01; dataFormat=Csv; byteCount=46517627; blobCount=1; compressData=False; requestContext=; blobs=System.Object[]} validTill : 2023-12-06T23:39:58.9165023

    Many thanks


  2. According to this Official MS Document the Azure Cost management API with scope set to enrollmentAccounts does not contain any blob location in the request. If you want to retrieve the cost of the blob resource, You need to use:-

    '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}'
    

    where resourceGroupName is the name of your resource group containing your blob.

    My sample Powershell script that calls the Cost management API:-

    $AppId = "xxxxxx-6d26a31435cb"
    $AppSecret = "xxxxhhZ~bY."
    $TokenURI = "https://login.microsoftonline.com/xxxxxx95/oauth2/token"
    $Resource = "https://management.core.windows.net/"
    
    $BodyRequest = "grant_type=client_credentials&client_id=$AppId&client_secret=$AppSecret&resource=$Resource"
    
    $AccessToken = Invoke-RestMethod -Method Post -Uri $TokenURI -Body $BodyRequest -ContentType 'application/x-www-form-urlencoded'
    
    $RequestURI = "https://management.azure.com/subscriptions/0151c365-f598-44d6-b4fd-e2b6e97cb2a7/resourceGroups/siliconstrg909-rg/providers/Microsoft.CostManagement/query?api-version=2023-03-01"
    
    $Headers = @{
        "Authorization" = "Bearer " + $AccessToken.access_token
        "Content-Type" = "application/json"
    }
    
    # Updated request body structure
    $UsageRequestBody = @{
        type = "Usage"
        timeframe = "MonthToDate"
        dataset = @{
            granularity = "Daily"
            aggregation = @{
                totalCost = @{
                    name = "PreTaxCost"
                    function = "Sum"
                }
            }
            grouping = @(
                @{
                    type = "Dimension"
                    name = "ResourceGroup"
                }
            )
        }
    }
    
    # Convert the updated payload to JSON
    $UsageRequestBodyJson = $UsageRequestBody | ConvertTo-Json
    
    # Make the request using Invoke-RestMethod
    $UsageRequest = Invoke-RestMethod -Method Post -Uri $RequestURI -Headers $Headers -Body $UsageRequestBodyJson -ContentType 'application/json'
    
    # Output the response
    $UsageRequest.properties.rows
    # Check for pagination
    while ($UsageRequest.properties.nextLink) {
        $NextLink = $UsageRequest.properties.nextLink
        $UsageRequest = Invoke-RestMethod -Uri $NextLink -Headers $Headers -Method Get
        $UsageRequest.properties.rows
    }
    

    Output:-

    enter image description here

    In your enrollmentAccounts Rest API, Try to add ResourceGroup name in value that contains your blob:-

    $AppId = "xxxxxx26a31435cb"
    $AppSecret = "xxxxxxxZ~bY."
    $TokenURI = "https://login.microsoftonline.com/83xxxxxx92395/oauth2/token"
    $Resource = "https://management.core.windows.net/"
    
    $BodyRequest = "grant_type=client_credentials&client_id=$AppId&client_secret=$AppSecret&resource=$Resource"
    
    $AccessToken = Invoke-RestMethod -Method Post -Uri $TokenURI -Body $BodyRequest -ContentType 'application/x-www-form-urlencoded'
    
    $RequestURI = "https://management.azure.com/providers/Microsoft.Billing/enrollmentAccounts/*****5/providers/Microsoft.CostManagement/generateCostDetailsReport?api-version=2023-08-01"
    
    $Headers = @{
        "Authorization" = "Bearer " + $AccessToken.access_token
        "Content-Type" = "application/json"
    }
    
    # Updated request body structure
    $UsageRequestBody = @{
        type = "Usage"
        timeframe = "MonthToDate"
        dataset = @{
            granularity = "Daily"
            filter = @{
                and = @(
                    @{
                        or = @(
                            @{
                                dimensions = @{
                                    name = "ResourceLocation"
                                    operator = "In"
                                    values = @("East US", "West Europe")
                                }
                            },
                            @{
                                tags = @{
                                    name = "Environment"
                                    operator = "In"
                                    values = @("UAT", "Prod")
                                }
                            }
                        )
                    },
                    @{
                        dimensions = @{
                            name = "ResourceGroup"
                            operator = "In"
                            values = @("YourSampleResourceGroupName")  # Replace this with your actual resource group name
                        }
                    }
                )
            }
        }
    }
    
    # Convert the updated payload to JSON
    $UsageRequestBodyJson = $UsageRequestBody | ConvertTo-Json
    
    # Make the request using Invoke-RestMethod
    $UsageRequest = Invoke-RestMethod -Method Post -Uri $RequestURI -Headers $Headers -Body $UsageRequestBodyJson -ContentType 'application/json'
    
    # Output the response
    $UsageRequest
    # Check for pagination
    while ($UsageRequest.properties.nextLink) {
        $NextLink = $UsageRequest.properties.nextLink
        $UsageRequest = Invoke-RestMethod -Uri $NextLink -Headers $Headers -Method Get
        $UsageRequest
    }
    

    Also, There’s a separate Rest API dedicated to Azure Blob Storage, You can try calling the Azure blob Powershell command to retrieve the blob properties like below:-

    # Connect to Azure account and set the desired subscription
    Connect-AzAccount -TenantId xxxxxxxab9
    Set-AzContext -SubscriptionId 'xxxxxxcb2a7'
    
    # Get the storage account context
    $ctx = Get-AzStorageAccount -ResourceGroupName "valleyrg87" -Name "siliconstorage678"
    
    # Check if the context is retrieved properly
    $ctx
    
    
    # Get the storage account context
    $ctx = Get-AzStorageAccount -ResourceGroupName "valleyrg87" -Name "siliconstorage678"
    
    # Check if the context is retrieved properly
    $ctx
    
    # If context is retrieved successfully, proceed to get blob properties
    if ($ctx) {
        # Get the blob reference
        $blob = Get-AzStorageBlob -Blob "hello_world.py" -Container "data" -Context $ctx.Context
    
        # Check if the blob is retrieved successfully
        $blob
    
        # If the blob is retrieved successfully, get blob properties
        if ($blob) {
            $properties = $blob.ICloudBlob.Properties
            $properties
        } else {
            Write-Host "Blob not found or there was an issue retrieving the blob."
        }
    } else {
        Write-Host "Storage account not found"
    }
    

    Output:-

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search