The evolution of Infrastructure-as-Code (IaC) within the Azure ecosystem has reached a critical inflection point with the maturation of the AzAPI Terraform provider. While the Azure Resource Manager (AzureRM) provider has long been the standard for defining, previewing, and deploying cloud infrastructure using HashiCorp Configuration Language (HCL), it often lags behind the rapid release cadence of new Azure services. The AzAPI provider solves this latency by managing Azure resources directly through the Azure Resource Manager (ARM) API. This approach allows engineers to provision resources, properties, or API versions that are not yet supported by the traditional AzureRM provider, effectively granting access to "Day-Zero" features. As the provider enters version 2.0, it introduces robust enhancements that make IaC on Azure more powerful, flexible, and user-friendly, shifting the paradigm from static resource definitions to dynamic API-driven configuration.
Architectural Foundation and Authentication
Terraform operates by allowing users to create configuration files using HCL syntax, which specifies the cloud provider and the specific elements that make up the cloud infrastructure. In a standard workflow, after creating these configuration files, an execution plan is generated. This plan allows users to preview infrastructure changes before they are deployed. Once the changes are verified, the execution plan is applied to deploy the infrastructure. The AzAPI provider fits into this workflow by abstracting the underlying HTTP interactions with the Azure REST API, but it retains the granularity of the raw API calls.
A primary distinction of AzAPI is its utility for resources that the AzureRM provider has not yet wrapped. For instance, if a new property is added to an Azure Container Registry in a recent API version but the AzureRM provider has not been updated to reflect that property, AzAPI allows the user to interact with that specific API version directly. The provider manages resources by targeting specific API versions, ensuring that the infrastructure code matches the exact backend capabilities available at the time of deployment.
Authentication is a prerequisite for any Terraform operation on Azure. Terraform automatically authenticates using information from the default Azure subscription associated with the logged-in Microsoft account. When a user logs into the Azure portal, the default Azure subscription for that account is utilized for any subsequent operations. To verify the current Microsoft account and Azure subscription, administrators can run the az account show command in the Azure CLI. Any changes made via Terraform are applied to the displayed Azure subscription. This automatic authentication streamlines the developer experience, reducing the need for manual configuration of credentials within the Terraform provider blocks, provided the Azure CLI environment is correctly set up.
Provider Setup and HCL Configuration
To begin using the AzAPI provider, developers must configure their Terraform environment to include the necessary dependencies. The provider is sourced from Azure/azapi, and the latest stable release is version 2.0. The configuration requires defining the provider in the terraform block of the HCL files. A typical setup includes the AzAPI provider, the traditional AzureRM provider for baseline resources like resource groups, and often a random provider for generating unique identifiers.
The following code block demonstrates the initial setup in a file named providers.tf. This configuration registers the Microsoft.ContainerRegistry provider implicitly by allowing the AzAPI provider to interact with the necessary service namespaces.
```hcl
terraform {
required_providers {
azapi = {
source = "Azure/azapi"
version = "~>2.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~>4.0"
}
random = {
source = "hashicorp/random"
version = "~>3.0"
}
}
}
provider "azurerm" {
features {}
}
```
In this setup, the azapi provider is pinned to version 2.0, ensuring access to the latest features such as write-only properties and enhanced data sources. The azurerm provider is included to manage foundational resources like resource groups, which are typically better suited for the traditional provider due to their stability and common usage. The random provider is used to generate unique names for resources, preventing collisions in the Azure subscription.
Variables are defined in a separate variables.tf file to allow for flexible deployment across different environments. The variables typically include the location of the resource group, a prefix for the resource group name, and the name of the specific resource, such as a container registry.
```hcl
variable "resourcegrouplocation" {
type = string
default = "eastus"
description = "Location of the resource group."
}
variable "resourcegroupname_prefix" {
type = string
default = "rg"
description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
}
variable "containerregistryname" {
type = string
default = ""
description = "Name of the container registry."
}
```
The main configuration file, main.tf, orchestrates the creation of resources. It utilizes the random_pet resource to generate a unique name for the resource group, combining the prefix variable with a random string. This ensures that the resource group name is unique within the Azure subscription.
```hcl
Create a resource group with a random name.
resource "randompet" "rgname" {
prefix = var.resourcegroupname_prefix
}
resource "azurermresourcegroup" "rg" {
location = var.resourcegrouplocation
name = randompet.rgname.id
}
Create a user assigned identity resource.
resource "azurermuserassignedidentity" "example" {
name = "example"
resourcegroupname = azurermresourcegroup.rg.name
location = azurermresource_group.rg.location
}
```
Advanced Features of AzAPI 2.0
The release of AzAPI 2.0 marked a significant leap in functionality, introducing features that address common pain points in Azure IaC. One of the most critical additions is the support for write-only properties. In Azure, certain properties, such as secrets or admin passwords, are sent to the API during resource creation but are not retrievable in subsequent GET requests. Previously, managing these properties required workarounds or external secret management systems. AzAPI 2.0 introduces the sensitive_body attribute on azapi_resource, which allows these properties to be sent to the ARM API but not stored in the Terraform state file. This is crucial for security, as it prevents sensitive data from being persisted in the state file, which is often committed to version control or stored in state backends.
The following example illustrates the use of sensitive_body to handle a write-only property, such as an admin password. The property is included in the sensitive_body block, ensuring it is not written to the Terraform state.
hcl
resource "azapi_resource" "example" {
type = "Microsoft.SomeService/resources@2024-01-01"
name = "example"
parent_id = azurerm_resource_group.example.id
body = {
properties = {
name = "example"
}
}
# Write-only — not stored in state
sensitive_body = {
properties = {
adminPassword = var.admin_password
}
}
}
To control when these write-only properties are resent to the API, the sensitive_body_version attribute can be used. This is particularly useful when rotating credentials or updating sensitive information without triggering a full resource replacement.
Another enhancement in AzAPI 2.0 is the improved handling of resource replacement triggers. The provider allows users to configure replace_triggers_external_values, which replaces the resource if a specified external value changes. This provides granular control over the lifecycle of the resource, allowing infrastructure teams to define specific conditions under which a resource should be destroyed and recreated. This is essential for maintaining consistency and preventing configuration drift.
Developer Experience and Tooling
The developer experience with AzAPI is significantly enhanced by the Microsoft Terraform VS Code extension. This extension provides a rich authoring experience for both the AzureRM and AzAPI providers. Key features of the extension include:
- Listing all available resource types and API versions.
- Autocompletion of allowed properties and values for any resource.
- Displaying hints when hovering over a property.
- Syntax validation to catch errors early in the development cycle.
- Autocompletion with code samples to accelerate learning and implementation.
The extension also supports "paste-as-AzAPI," a feature that converts Azure Resource Manager (ARM) JSON templates into azapi_resource blocks. This is invaluable for engineers who are more comfortable with ARM JSON or who are porting existing ARM templates to Terraform. Additionally, the extension supports Azure resource export via aztfexport, AzureRM-to-AzAPI migration, and preflight validation.
Preflight validation is a critical feature that surfaces configuration errors during the terraform plan phase rather than at the terraform apply time. This reduces feedback loops and allows developers to fix issues before they impact the production environment. The validation process checks for syntax errors, missing required properties, and incompatible API versions, ensuring that the configuration is valid before deployment.
Migration and Import Strategies
One of the challenges in adopting a new provider is migrating existing infrastructure. The aztfmigrate tool is designed to help migrate existing resources between the AzAPI and AzureRM providers. The tool operates in two modes: plan and migrate.
- Plan: Displays the AzAPI resources that can be migrated. This mode allows administrators to preview the scope of the migration without making any changes.
- Migrate: Migrates the AzAPI resources to AzureRM resources in both the HCL files and the state.
The aztfmigrate tool ensures that after migration, the Terraform configuration and state are aligned with the actual state of the infrastructure. To validate the update to the state, users can run terraform plan after completing the migration to confirm that no changes occurred. If the plan shows no changes, it indicates that the migration was successful and that the configuration and state are in sync.
For importing existing Azure resources into AzAPI without recreating them, the import block (available in Terraform 1.5 and later) or the terraform import command can be used. The resource ID must include the API version as a query parameter. This ensures that the correct API version is used when retrieving the resource details.
```hcl
import {
to = azapi_resource.example
id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Network/virtualNetworks/example-vnet?api-version=2023-11-01"
}
resource "azapiresource" "example" {
type = "Microsoft.Network/virtualNetworks@2023-11-01"
name = "example-vnet"
parentid = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg"
location = "westus"
body = {
properties = {
addressSpace = {
addressPrefixes = ["10.0.0.0/16"]
}
}
}
}
```
For large-scale migrations or when importing multiple resources at once from existing Azure infrastructure, Azure Export for Terraform (aztfexport) is recommended. This tool generates both the HCL configuration and the import blocks automatically, reducing the manual effort required to bring existing infrastructure under Terraform management.
Data Sources and Fine-Grained Controls
The AzAPI provider supports various useful data sources, with the azapi_resource data source being the most versatile. This data source is used to read information from any Azure control plane resource. It allows users to retrieve specific properties of a resource without defining a full resource block, which is useful for referencing existing resources or retrieving dynamic values.
The provider also offers granular controls over infrastructure through its ability to fine-tune configurations to match specific design patterns. This includes the use of timeouts blocks to set upper bounds on total retry duration. For example, setting a create timeout ensures that the deployment process does not hang indefinitely if the API response is delayed.
hcl
timeouts {
create = "10m"
}
Combining retry with the timeouts block allows for robust error handling, ensuring that transient API failures do not cause the deployment to fail. This level of control is essential for enterprise environments where reliability and predictability are paramount.
Comparative Analysis of AzureRM and AzAPI Providers
The choice between the AzureRM and AzAPI providers depends on the specific requirements of the project. The following table compares the key features of both providers to assist in decision-making.
| Feature | AzureRM Provider | AzAPI Provider |
|---|---|---|
| Resource Abstraction | High-level abstraction of Azure resources | Direct access to Azure Resource Manager API |
| Day-Zero Support | Limited; lags behind new Azure features | Full support for Day-Zero features |
| API Versioning | Managed internally by the provider | Explicitly defined in the resource type |
| Write-Only Properties | Limited support | Full support via sensitive_body |
| Resource Replacement | Standard Terraform behavior | Configurable via replace_triggers_external_values |
| Import Mechanism | Standard terraform import |
import block with API version query parameter |
| Tooling | Standard Terraform tools | aztfmigrate, aztfexport, VS Code extension |
| Use Case | Stable, well-established resources | New features, complex configurations, migration |
Conclusion
The Terraform AzAPI provider represents a significant advancement in the ability to manage Azure infrastructure with precision and flexibility. By providing direct access to the Azure Resource Manager API, it enables engineers to leverage Day-Zero features that are not yet available in the traditional AzureRM provider. The introduction of version 2.0 has further solidified its position as a critical tool for enterprise-grade IaC, with features such as write-only properties, preflight validation, and enhanced migration tools.
The integration of the Microsoft Terraform VS Code extension and tools like aztfmigrate and aztfexport lowers the barrier to entry and accelerates the adoption of AzAPI. These tools facilitate the transition from ARM JSON to HCL, simplify the migration of existing resources, and provide real-time feedback during the development process. The ability to use sensitive_body for handling secrets and replace_triggers_external_values for granular lifecycle control addresses common security and operational challenges.
For organizations looking to maintain a competitive edge in cloud infrastructure, adopting the AzAPI provider offers a pathway to faster innovation and greater control. The provider's alignment with the Azure API ensures that infrastructure code remains in sync with the latest Azure capabilities, reducing the risk of configuration drift and enabling more resilient and scalable platforms. As Azure continues to evolve, the AzAPI provider will likely play an increasingly central role in the IaC toolchain, complementing the AzureRM provider to provide a comprehensive solution for Azure infrastructure management.