---
title: "Configure serverless Azure metrics with Terraform | Grafana Cloud documentation"
description: "How to configure serverless Azure metrics with Terraform"
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# Configure serverless Azure Metrics with Terraform

Complete the following steps to configure serverless Azure metrics using Terraform.

## Before you begin

Before configuring serverless Azure metrics using Terraform, ensure you have:

- **Terraform:** Version 1.0 or later installed
- **Azure credentials:** Configured for Terraform (with Azure CLI, environment variables, or Service Principal) For more information on authentication options, see the [Azure Active Directory Terraform Provider documentation](https://registry.terraform.io/providers/hashicorp/azuread/latest/docs).

## Configure Azure authorization

To collect metrics from Azure Monitor, create a service principal with the proper authorization to allow Grafana Cloud to pull Azure metrics on your behalf.

### Create a service principal with Azure CLI

1. Log in to your Azure account with the following command:
   
   shell ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```shell
   az login
   ```
2. List your available subscriptions with the following command:
   
   shell ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```shell
   az account list --output table
   ```
3. Create a service principal for each subscription you want to monitor, and give it the appropriate **role**. If a service principal already exists with this name, it updates with the **role** and **scopes** you provide. Replace `AZURE_SUBSCRIPTION_ID` with the appropriate value and use the following command:
   
   shell ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```shell
   az ad sp create-for-rbac --name grafana-cloud-azure-metrics --role "Monitoring Reader" --scopes "/subscriptions/@@@AZURE_SUBSCRIPTION_ID@@@"
   ```
4. When the service principal is created, save the output of the command to use as the credential information that you need for the Terraform configuration steps.
   
   shell ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy
   
   ```shell
   {
     "appId": "54321a67-8fd9-123d-45d6-7891234567fd",
     "displayName": "grafana-cloud-azure-metrics",
     "password": "asdf1234~4321fdsa",
     "tenant": "12345a67-8fd9-123d-45d6-7891234567fd"
   }
   ```

For more information on creating service principals using Azure CLI, refer to the [Azure CLI documentation](https://learn.microsoft.com/en-us/cli/azure/azure-cli-sp-tutorial-1?view=azure-cli-latest&tabs=bash#create-a-service-principal).

### Create a service principal with Terraform

The following snippet shows how to configure the Azure service principal using Terraform. You do not need to apply the Terraform to create the service principal before moving forward.

hcl ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```hcl
data "azurerm_client_config" "current" {}

resource "azuread_application" "grafana_cloud_azure_metrics" {
  display_name = var.azure_application_display_name
}

resource "azuread_application_password" "grafana_cloud_azure_metrics" {
  display_name      = "${var.azure_application_display_name}-secret"
  application_id    = azuread_application.grafana_cloud_azure_metrics.id
  end_date_relative = "8760h" # 1 year

  rotate_when_changed = {
    rotation = time_rotating.azure_monitor_exporter_time_rotation.id
  }
}

resource "time_rotating" "azure_monitor_exporter_time_rotation" {
  // Rotate every 180 days
  // This is to ensure the password is rotated before it expires
  rotation_days = 180
}

# Service Principal for the application — required so we have a client id to grant role assignments
resource "azuread_service_principal" "grafana_cloud_azure_metrics" {
  client_id = azuread_application.grafana_cloud_azure_metrics.client_id
}

# Role assignment for Monitoring Reader - use the Service Principal's client id for principal_id
resource "azurerm_role_assignment" "grafana_cloud_azure_metrics" {
  scope                = "/subscriptions/${var.azure_subscription_id}"
  role_definition_name = "Monitoring Reader"
  principal_id         = azuread_service_principal.grafana_cloud_azure_metrics.id
}
```

## Configure Grafana Cloud

After deciding how you want to configure the Azure service principal, you can configure Grafana Cloud to use it.

### Create an Access Policy for the Grafana Terraform provider

If you are already using the Grafana Terraform provider, ensure the access policy you are using has the following scopes:

- `orgs: Read`
- `stacks: Read`
- `accesspolicies: Read, Write, Delete`

If you haven’t used the Grafana Terraform provider yet, you must create an access policy. Since this access policy is necessary to use the Terraform provider, you must create it through Grafana Cloud.

Follow the steps to [Create access policies and tokens](/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-policies/create-access-policies/).

To create an access policy token:

1. Follow the [Create an access policy for a stack](/docs/grafana-cloud/security-and-account-management/authentication-and-permissions/access-policies/create-access-policies/#create-an-access-policy-for-a-stack) instructions.
2. In step 6, add the following scopes:
   
   - `integration-management:read`
   - `integration-management:write`
   - `stacks:read`
3. After creating the policy, click **Add token** and generate a token.
4. Give your token an appropriate name and select an Expiration date. We recommend you select a specific expiration date and **do not** set the **Expiration date** to **No expiry**, as this can create a security vulnerability.
5. Store this token securely—you’ll use it to configure the Grafana Terraform provider.

### Configure the Grafana Terraform provider with your Access Policy

Include the Grafana Terraform provider as a dependency in your Terraform configuration file. The version of the provider must be `3.24.1` or later, as in the following example:

hcl ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```hcl
terraform {
    required_providers {
        grafana = {
        source = "grafana/grafana"
        version = ">= 3.24.1"
        }
    }
}
```

Choose one of the following methods to configure the Grafana Terraform provider to use the provisioned Access Policy token:

Embed the token in Terraform configuration, as in the following example:

````
```hcl
provider "grafana" {
  cloud_access_policy_token = "@@@GRAFANA_CLOUD_ACCESS_POLICY_TOKEN@@@"
}
```
````

Use the environment variable `GRAFANA_CLOUD_ACCESS_POLICY_TOKEN` set to the created token when running Terraform commands with the following provider block:

````
```hcl
provider "grafana" {}
```
````

### Configure the Terraform provider to use the Cloud Provider API

Replacing values with your own, use the following snippet to configure the provider block with the Cloud Provider API:

hcl ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```hcl
provider "grafana" {
  cloud_access_policy_token   = var.grafana_cloud_access_policy_token
  cloud_provider_url          = format("https://cloud-provider-api-%s.grafana.net", data.grafana_cloud_stack.current.cluster_slug)
  cloud_provider_access_token = var.grafana_cloud_access_policy_token
}
```

> Note
> 
> If this endpoint does not work, your Grafana Cloud Provider API endpoint may be using the new URL format. For more information on Grafana Cloud URLs, refer to [Determine Grafana Cloud URLs based on region](/docs/grafana-cloud/security-and-account-management/region-url-formats/).

### The Azure Credential Terraform model

The Cloud Provider portion of the Grafana Terraform provider enables configuring Azure metric collection through the following resources and data sources:

Expand table

| Name                                      | Description                                                                                                                                                                                                                                                                                                                                                      |
|-------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `grafana_cloud_provider_azure_credential` | A resource representing an Azure Service Principal credential that is used by Grafana Cloud to pull Azure Monitor metrics from one or more subscriptions. For a full reference of this resource, refer to [the Terraform resource documentation](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_provider_azure_credential). |

The following is a minimal Azure Credential resource definition:

hcl ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```hcl
data "grafana_cloud_stack" "current" {
  slug = var.stack_slug
}

resource "grafana_cloud_provider_azure_credential" "azurecred" {
  stack_id = data.grafana_cloud_stack.current.id
  name     = var.credential_name

  client_id     = azuread_application.grafana_cloud_azure_metrics.client_id
  client_secret = azuread_application_password.grafana_cloud_azure_metrics.value
  tenant_id     = data.azurerm_client_config.current.tenant_id

  depends_on = [azurerm_role_assignment.grafana_cloud_azure_metrics] # If the application has no role, this will fail.
}
```

## Full Terraform Example

The following snippet shows a full Terraform example that provisions an Azure service principal and uses it to collect Azure metrics:

hcl ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```hcl
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.1.0"
    }
    azuread = {
      source  = "hashicorp/azuread"
      version = "~> 2.46.0"
    }
    grafana = {
      source  = "grafana/grafana"
      version = ">= 3.24.1"
    }
  }
}

########################
# Variables
########################

variable "azure_application_display_name" {
  description = "Display name for the Azure application"
  type        = string
  default     = "grafana-cloud-azure-metrics"
}
variable "azure_subscription_id" {
  type        = string
  description = "Azure Subscription ID source of the Azure metrics"
}
variable "credential_name" {
  type        = string
  description = "The name of the Azure Credential resource that will be created"
  default     = "test-azure-credential"
}
// Required scopes: integration-management:read, integration-management:write, stacks:read
variable "grafana_cloud_access_policy_token" {
  type        = string
  description = "Access policy token for a token with permissions to manage Cloud Provider credentials (recommend using env var/secret manager)"
}
variable "stack_slug" {
  type        = string
  description = "Grafana Cloud Stack Slug where the Azure metrics will be collected"
}

########################
# Providers
########################

# no config required here for most setups (auth via Azure CLI or environment)
# provider "azurerm" {}
# provider "azuread" {}

provider "grafana" {
  cloud_access_policy_token   = var.grafana_cloud_access_policy_token
  cloud_provider_url          = format("https://cloud-provider-api-%s.grafana.net", data.grafana_cloud_stack.current.cluster_slug)
  cloud_provider_access_token = var.grafana_cloud_access_policy_token
}

########################
# Azure: create app / sp / secret / role assignment
########################

data "azurerm_client_config" "current" {}

resource "azuread_application" "grafana_cloud_azure_metrics" {
  display_name = var.azure_application_display_name
}

resource "azuread_application_password" "grafana_cloud_azure_metrics" {
  display_name      = "${var.azure_application_display_name}-secret"
  application_id    = azuread_application.grafana_cloud_azure_metrics.id
  end_date_relative = "8760h" # 1 year

  rotate_when_changed = {
    rotation = time_rotating.azure_monitor_exporter_time_rotation.id
  }
}

resource "time_rotating" "azure_monitor_exporter_time_rotation" {
  // Rotate every 180 days
  // This is to ensure the password is rotated before it expires
  rotation_days = 180
}

# Service Principal for the application — required so we have a client id to grant role assignments
resource "azuread_service_principal" "grafana_cloud_azure_metrics" {
  client_id = azuread_application.grafana_cloud_azure_metrics.client_id
}

# Role assignment for Monitoring Reader - use the Service Principal's client id for principal_id
resource "azurerm_role_assignment" "grafana_cloud_azure_metrics" {
  scope                = "/subscriptions/${var.azure_subscription_id}"
  role_definition_name = "Monitoring Reader"
  principal_id         = azuread_service_principal.grafana_cloud_azure_metrics.id
}


########################
# Grafana Cloud Provider Azure credential
########################

data "grafana_cloud_stack" "current" {
  slug = var.stack_slug
}

resource "grafana_cloud_provider_azure_credential" "azurecred" {
  stack_id = data.grafana_cloud_stack.current.id
  name     = var.credential_name

  client_id     = azuread_application.grafana_cloud_azure_metrics.client_id
  client_secret = azuread_application_password.grafana_cloud_azure_metrics.value
  tenant_id     = data.azurerm_client_config.current.tenant_id

  depends_on = [azurerm_role_assignment.grafana_cloud_azure_metrics] # If the application has no role, this will fail.
}
```
