AzAPI Provider for Terraform

repository·main·Indexed 42 days ago

https://github.com/azure/terraform-provider-azapi

A thin wrapper around Azure ARM REST APIs that enables Terraform management of Azure resources not yet supported by the standard AzureRM provider, including preview features. It provides the azapi_resource and azapi_resource_action resources for managing and performing stateless actions on resources, as well as data sources like azapi_client_config, azapi_resource_list, and azapi_resource for retrieving Azure configuration and resource information.

Tokens
579.1K
Snippets
916
Records
1.3K
Agent score
50%

What's inside AzAPI

  1. What is a managed identity and how does it work?

    main

    Managed identities for Azure resources allow Azure resources to authenticate to services that support Azure Active Directory (Azure AD) without storing credentials on the resource.

    There are two types:

    1. System-assigned: The identity's lifecycle is tied to the resource. It is created when the resource is created and removed when the resource is deleted.
    2. User-assigned: A standalone Azure resource that can be assigned to one or more Azure resources.

    To use a managed identity, you must perform two steps:

    1. Assign a role: Associate the identity with the subscription used to run Terraform to grant permission to access Azure Resource Manager (ARM) resources.
    2. Configure access control: Set up permissions for specific Azure resources (e.g., Key Vault or Storage Account) that the identity needs to access.

    Permissions required: To configure a resource with a managed identity and assign RBAC roles, your account must be an Owner or have both Contributor and User Access Administrator roles.

  2. How the Acquire Policy Token feature works

    main

    The AzAPI provider supports Azure Policy invoke policies (external evaluation policies). When a write request (PUT, POST, PATCH, or DELETE) is blocked because it lacks a required policy token, the provider can automatically handle the acquisition and retry process.

    Reactive Acquisition (Default)

    By default, the provider uses a reactive approach:

    1. It sends the original write request.
    2. If it receives a 403 Forbidden with the error code RequestDisallowedByPolicy and a PolicyViolation entry containing missingPolicyTokenDetails where shouldDeny is true, it triggers the acquisition flow.
    3. The provider calls the Microsoft.Authorization/acquirePolicyToken API (api-version=2025-03-01) for the subscription.
    4. If a token is returned, the provider attaches it via the x-ms-policy-external-evaluations header and retries the original request.

    Note: GET requests are never affected by this feature.

    Limitations

    • Change references are not supported: If the policy denial indicates that a change reference is required (isChangeReferenceRequired is true), the provider will return an error instead of attempting to acquire a token.
  3. Export API response values using response_export_values

    main

    When using azapi_resource, you can use the response_export_values argument to specify which fields from the Azure REST API response should be mapped to the resource's output attribute. This is useful for retrieving read-only properties generated by Azure (like a login server URL or a generated ID).

    Values specified in response_export_values are accessed in Terraform via azapi_resource.<NAME>.output.<PATH_TO_VALUE>.

    resource "azapi_resource" "example" {
      type      = "Microsoft.ContainerRegistry/registries@2020-11-01-preview"
      name      = "registry1"
      parent_id = azurerm_resource_group.example.id
      # ... other config ...
    
      response_export_values = ["properties.loginServer", "properties.policies.quarantinePolicy.status"]
    }
    
    output "login_server" {
      value = azapi_resource.example.output.properties.loginServer
    }
  4. Configure response_export_values in azapi_resource_action

    main

    The response_export_values attribute determines how data from the Azure API response is mapped to the output attribute of the ephemeral resource. It supports two modes:

    1. List Mode

    Provide a list of JMESPath paths to export. Setting it to ["*"] exports the full response body.

    Example: If you set ["properties.loginServer", "properties.policies.quarantinePolicy.status"], the output will be:

    {
      properties = {
        loginServer = "registry1.azurecr.io"
        policies = {
          quarantinePolicy = {
            status = "disabled"
          }
        }
      }
    }

    2. Map Mode

    Provide a map where the key is your desired result name and the value is a JMESPath query string.

    Example: If you set {"login_server": "properties.loginServer", "quarantine_status": "properties.policies.quarantinePolicy.status"}, the output will be:

    {
      "login_server" = "registry1.azurecr.io"
      "quarantine_status" = "disabled"
    }
    # Example of using the output from an ephemeral resource
    output "login_server" {
      value = ephemeral.azapi_resource_action.example.output.properties.loginServer
    }
  5. Use the azapi_resource_action data source to perform Azure actions

    main

    The azapi_resource_action data source allows you to perform an action on an existing Azure resource, such as retrieving access keys from a Storage Account.

    Warning: This data source should only be used for actions that read information. Do not use it to perform actions that modify the state of an Azure resource, as it may be called multiple times during a Terraform run.

    To use it, you must provide the resource type in the format <resource-type>@<api-version> and the resource_id of the target resource.

    data "azapi_resource_action" "example" {
      type                   = "Microsoft.Automation/automationAccounts@2021-06-22"
      resource_id            = azurerm_automation_account.example.id
      action                 = "listKeys"
      response_export_values = ["*"]
    }
  6. Use azapi_data_plane_resource for data plane operations

    main

    The azapi_data_plane_resource is used to manage resources that reside on the data plane of an Azure service rather than the control plane. Unlike standard azapi_resource calls which typically target the Azure Resource Manager (ARM) endpoint, data plane resources often target service-specific endpoints (e.g., service-name.azureiotcentral.com or service-name.search.windows.net).

    Key characteristics:

    • parent_id: Often requires the service's data plane endpoint (e.g., a URL) rather than an ARM resource ID.
    • retry block: Allows configuring custom retry logic for specific error patterns common in data plane operations (like PermissionDenied or Unauthorized).
    • depends_on: Frequently requires an explicit dependency on a control plane azapi_resource (like a Role Assignment) to ensure permissions are in place before the data plane call is made.
    resource "azapi_data_plane_resource" "example" {
      type      = "Microsoft.AppConfiguration/configurationStores/keyValues@1.0"
      parent_id = replace(azapi_resource.appconf.output.endpoint, "https://", "")
      name      = "mykey"
      body = {
        content_type = ""
        value        = "myvalue"
      }
    
      retry = {
        error_message_regex  = ["PermissionDenied", "Unauthorized"]
        interval_seconds     = 30
        max_interval_seconds = 180
      }
    
      depends_on = [
        azapi_resource.roleAssignment,
      ]
    }
  7. Export values from the API response using response_export_values

    main

    The response_export_values attribute allows you to extract data from the Azure API response into Terraform's state. You can use two formats:

    1. List: A list of paths. Using ["*"] exports the entire body.
    2. Map: A map where the key is the output name and the value is a JMESPath query string.

    Once exported, these values are accessible via the output attribute of the resource.

    # Example using a Map with JMESPath
    resource "azapi_update_resource" "example" {
      resource_id = "..."
      type        = "..."
      response_export_values = {
        "login_server"      = "properties.loginServer"
        "quarantine_status" = "properties.policies.quarantinePolicy.status"
      }
    }
    
    # Accessing the exported values
    output "login_server" {
      value = azapi_update_resource.example.output.login_server
    }
  8. Use azapi_resource to manage Azure resources

    main

    The azapi_resource resource allows you to manage Azure resources directly via their REST API type and properties. You specify the type (including the API version), the name, and a parent_id. The resource configuration is defined within the body argument using a JSON-like structure that maps to the Azure ARM API properties.

    terraform {
      required_providers {
        azapi = {
          source  = "Azure/azapi"
        }
      }
    }
    
    provider "azapi" {}
    
    resource "azapi_resource" "example" {
      type      = "Microsoft.Automation/automationAccounts@2021-06-22"
      name      = "myAccount"
      parent_id = azurerm_resource_group.example.id
      location  = "West Europe"
    
      body = {
        properties = {
          disableLocalAuth    = true
          publicNetworkAccess = false
          sku = {
            name = "Basic"
          }
        }
      }
    }
  9. Optimize AzAPI performance with Policy Tokens

    main

    By default, the provider waits for a 403 response indicating a policy token is required before retrying a write request. To improve performance when performing large-scale changes, you can proactively acquire a policy token for every write request.

    Set always_acquire_policy_token = true to avoid the extra round-trip per request. This can also be configured via the ARM_ALWAYS_ACQUIRE_POLICY_TOKEN environment variable.

  10. Export response values from azapi_resource_action

    main

    You can capture data from the Azure API response using response_export_values (for standard data) or sensitive_response_export_values (for sensitive data). This allows you to use values returned by the action in other parts of your Terraform configuration.

    Both attributes accept two formats:

    1. List: A list of paths to export. Using ["*"] exports the entire response body.

      • Example: ["properties.loginServer"] creates an output object containing that specific path.
    2. Map: A map where the key is your desired output name and the value is a JMESPath query string used to extract the data.

      • Example: {"login_server": "properties.loginServer"}

    Accessing Outputs

    Once exported, you can access the values via the .output or .sensitive_output attributes of the resource.

    // Accessing standard output
    output "login_server" {
      value = azapi_resource_action.example.output.properties.loginServer
    }
    
    // Accessing sensitive output
    output "quarantine_policy" {
      value     = azapi_resource_action.example.sensitive_output.properties.policies.quarantinePolicy.status
      sensitive = true
    }
    resource "azapi_resource_action" "example" {
      type        = "Microsoft.ContainerRegistry/registries@2023-01-01"
      resource_id = azapi_container_registry.example.id
      action      = "regeneratePassword"
      
      response_export_values = {
        "login_server" = "properties.loginServer"
      }
    }
    
    output "login_server" {
      value = azapi_resource_action.example.output.login_server
    }