Skip to content

Add table Azure Cost and Usage report #911

@ParthaI

Description

@ParthaI

For Azure, We do have the API available to get the usage details.

Here is the sample API
https://learn.microsoft.com/en-us/rest/api/cost-management/query/usage?view=rest-cost-management-2025-03-01&tabs=HTTP#code-try-0

Sample Go code for future reference:

package main

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)

type QueryDataset struct {
	Granularity string                 `json:"granularity"`
	Aggregation map[string]Aggregation `json:"aggregation"`
	Grouping    []Grouping             `json:"grouping"`
}

type Aggregation struct {
	Name     string `json:"name"`
	Function string `json:"function"`
}

type Grouping struct {
	Type string `json:"type"`
	Name string `json:"name"`
}

type QueryRequest struct {
	Type      string       `json:"type"`
	Timeframe string       `json:"timeframe"`
	Dataset   QueryDataset `json:"dataset"`
}

func main() {
	subscriptionId := os.Getenv("AZURE_SUBSCRIPTION_ID")
	if subscriptionId == "" {
		fmt.Println("Please set AZURE_SUBSCRIPTION_ID environment variable.")
		return
	}

	// Authenticate using Azure CLI credential
	cred, err := azidentity.NewAzureCLICredential(nil)
	if err != nil {
		fmt.Printf("Failed to get Azure CLI credentials: %v\n", err)
		return
	}

	// Acquire token
	ctx := context.Background()
	token, err := cred.GetToken(ctx, policy.TokenRequestOptions{
		Scopes: []string{"https://management.azure.com/.default"},
	})
	if err != nil {
		fmt.Printf("Failed to acquire token: %v\n", err)
		return
	}

	// Build payload
	payload := QueryRequest{
		Type:      "Usage",
		Timeframe: "MonthToDate",
		Dataset: QueryDataset{
			Granularity: "Daily",
			Aggregation: map[string]Aggregation{
				"totalCost": {
					Name:     "PreTaxCost",
					Function: "Sum",
				},
			},
			Grouping: []Grouping{
				{Type: "Dimension", Name: "ResourceGroupName"},
				{Type: "Dimension", Name: "ServiceName"},
			},
		},
	}

	jsonPayload, _ := json.Marshal(payload)

	// Make request
	url := fmt.Sprintf("https://management.azure.com/subscriptions/%s/providers/Microsoft.CostManagement/query?api-version=2023-03-01", subscriptionId)
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonPayload))
	req.Header.Set("Authorization", "Bearer "+token.Token)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("HTTP request failed: %v\n", err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println("Response:\n", string(body))
}

Note: We need to plan what our steampipe table design looks like.

Metadata

Metadata

Assignees

Labels

azureAzure plugin issuesenhancementNew feature or requestnew tableNew table requeststeampipeSteampipe plugin issues

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions