Mastering the Azure AzAPI Terraform Provider: Architecture, Migration, and Advanced Resource Management

The evolution of infrastructure as code demands tools that adapt as rapidly as cloud service catalogs expand. Terraform has established itself as the industry standard for defining, previewing, and deploying cloud infrastructure through its Human Configuration Language (HCL) syntax. This syntax allows engineers to specify cloud providers, such as Microsoft Azure, and the specific elements that constitute the target environment. A critical workflow involves creating an execution plan, which provides a preview of infrastructure changes prior to deployment. Once these changes are verified, the execution plan is applied to deploy the infrastructure. However, a significant bottleneck in traditional Azure resource management is the lag between the release of new Azure features, preview services, or API versions and their subsequent support in the standard Azure Resource Manager (AzureRM) provider. The AzAPI Terraform provider resolves this latency by managing Azure resources directly through the Azure Resource Manager API. This approach is particularly useful for resources, properties, or API versions not yet supported by the standard AzureRM provider. By acting as a thin layer on top of the Azure ARM REST APIs, the AzAPI provider enables the management of any Azure resource type using any API version, ensuring that engineering teams can leverage the latest functionality within the Azure ecosystem immediately.

Architecture and Core Capabilities

The AzAPI provider is designed as a first-class component within the Terraform ecosystem, intended to be used either on its own or in tandem with the AzureRM provider. Unlike the AzureRM provider, which relies on generated SDKs that require updates for every new resource or property, the AzAPI provider removes the dependency on Swagger definitions and generated code. This architectural choice provides several distinct benefits that enhance both the flexibility and fidelity of infrastructure management. The provider supports all Azure control plane services, including preview services and features, and allows access to all available API versions. This comprehensive support ensures that infrastructure definitions remain in full sync with the Azure service catalog without waiting for provider updates.

A critical advantage of the AzAPI provider is its full Terraform state file fidelity. In traditional providers, certain properties or values might not be persisted to the state file if they are not explicitly defined in the provider schema. With AzAPI, properties and values are saved to state, ensuring that the state file accurately reflects the actual infrastructure. This fidelity is essential for debugging, drift detection, and accurate planning. Additionally, the provider includes built-in preflight validation, which helps identify configuration errors before they reach the execution phase. The authentication model is consistent with common Azure authentication patterns, allowing it to integrate seamlessly with existing CI/CD pipelines that utilize service principals or managed identities.

The provider’s core functionality is driven by two generic resources that offer granular control over infrastructure development. These resources abstract the complexity of the REST API into manageable Terraform resources. The following table details the primary resources available within the AzAPI provider:

Resource Name Description Example Use Cases
azapi_resource Used to fully manage any Azure (control plane) resource (API) with full Create, Read, Update, and Delete (CRUD) capabilities. New preview service; new feature added to an existing service; any Azure resource accessible through the ARM API.
azapi_update_resource Used to manage resources or parts of resources that do not have full CRUD support. Update new properties on an existing service; update precreated child resources, such as a DNS SOA record.

The azapi_resource is the workhorse for most scenarios, capable of handling the entire lifecycle of a resource. The azapi_update_resource is designed for scenarios where the Azure API only supports partial updates or where the resource is managed externally but specific properties need to be modified via Terraform. This granular control allows engineers to match their configuration to specific design patterns, avoiding the need for complex workarounds that are often required when using rigid, fully-generated providers.

Developer Experience and Tooling

The efficiency of an infrastructure as code solution is heavily dependent on the authoring experience it provides. For the AzAPI provider, the Microsoft Terraform VS Code extension plays a pivotal role in reducing cognitive load and accelerating development. This extension provides a rich authoring experience for both the AzureRM and AzAPI providers, integrating deep knowledge of the Azure API surface directly into the editor. Key features of this extension include the ability to list all available resource types and API versions, allowing developers to quickly identify the correct type string for their needs. Furthermore, the extension provides autocompletion for allowed properties and values for any resource, significantly reducing the likelihood of syntax or schema errors. When hovering over a property, the extension displays hints that provide context and documentation, aiding in the understanding of complex data structures.

Beyond basic autocomplete, the VS Code extension offers syntax validation to catch errors in real-time. It also supports autocompletion with code samples, providing ready-made templates that can be adapted to specific use cases. A particularly powerful feature is the "paste-as-AzAPI" capability, which converts ARM JSON templates into azapi_resource blocks. This feature bridges the gap between traditional ARM template users and Terraform adopters, allowing teams to leverage existing infrastructure-as-code artifacts in a new format. The extension also supports Azure resource export via aztfexport and AzureRM-to-AzAPI migration, streamlining the transition for teams moving from other tools or providers.

Migration Strategies and State Alignment

As the AzureRM provider matures, some resources that were initially managed via AzAPI due to lack of support may become supported in AzureRM. In such cases, teams may wish to migrate resources to the AzureRM provider for consistency. The aztfmigrate tool is specifically designed to facilitate the migration of existing resources between the AzAPI and AzureRM providers. This tool operates in two distinct modes to ensure a safe and controlled migration process.

The first mode, plan, displays the AzAPI resources that are eligible for migration. This step allows engineers to review the scope of the migration and identify any potential conflicts or unsupported properties. The second mode, migrate, performs the actual migration of the AzAPI resources to AzureRM resources in both the HCL configuration files and the Terraform state. A crucial aspect of the aztfmigrate tool is its ability to ensure that, after migration, the Terraform configuration and state are aligned with the actual infrastructure state. This alignment prevents state drift and ensures that subsequent plans and applies operate correctly. After completing a migration, it is best practice to run terraform plan to validate the update to state and confirm that no changes occurred, verifying that the state file is now fully synchronized with the migrated resources.

Importing Existing Infrastructure

One of the significant challenges in adopting infrastructure as code is bringing existing resources under management without recreating them. The AzAPI provider provides robust mechanisms for importing existing Azure resources. For Terraform version 1.5 and later, the import block can be used to bring a resource under AzAPI management. The resource ID in the import block must include the API version as a query parameter to ensure the correct schema is applied.

The following code block demonstrates how to import an existing virtual network into an azapi_resource definition:

```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"
parent
id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg"
location = "westus"

body = {
properties = {
addressSpace = {
addressPrefixes = ["10.0.0.0/16"]
}
}
}
}
```

For environments where multiple resources need to be imported simultaneously from existing Azure infrastructure, the aztfexport tool is highly effective. This tool generates both the HCL configuration and the import blocks automatically, reducing the manual effort required to define the body and parent_id attributes for each resource. This automation is particularly useful for large-scale migrations where hundreds of resources need to be brought under Terraform management.

Advanced Use Case: Partner Admin Link Automation

Beyond standard resource management, the AzAPI provider enables complex operational workflows that are difficult or impossible with the AzureRM provider. A notable example is the creation and management of Partner Admin Links (PAL) using the azapi_resource_action resource. This scenario is useful in CI/CD pipelines and subscription vending machine situations where automated linking of security principals to partners is required. It is important to note that each security principal can be linked to only one partner ID, making idempotency and precise control critical.

The following configuration demonstrates how to create a Partner Admin Link using azapi_resource_action. This example assumes authentication via a service principal, with the ARM_TENANT_ID, ARM_CLIENT_ID, and ARM_CLIENT_SECRET environment variables exported.

```hcl
terraform {
required_providers {
azapi = {
source = "azure/azapi"
version = ">= 2.8.0"
}
}
}

provider "azapi" {}

variable "partner_id" {
type = string
default = "314159"
}

resource "azapiresourceaction" "pal" {
type = "Microsoft.ManagementPartner/partners@2018-02-01"
resourceid = "/providers/Microsoft.ManagementPartner/partners/${var.partnerid}"
method = "PUT"
when = "apply"

body = {
partnerId = var.partner_id
}

responseexportvalues = {
id = "id"
objectId = "properties.objectId"
partnerName = "properties.partnerName"
partnerId = "properties.partnerId"
}
}

resource "azapiresourceaction" "paldestroy" {
type = "Microsoft.ManagementPartner/partners@2018-02-01"
resource
id = "/providers/Microsoft.ManagementPartner/partners/${var.partner_id}"
method = "DELETE"
when = "destroy"
}
```

In this configuration, the azapi_resource_action.pal resource executes a PUT request when the Terraform configuration is applied. The response_export_values attribute allows specific fields from the API response, such as objectId and partnerName, to be captured and used in other parts of the configuration or output. The azapi_resource_action.pal_destroy resource ensures that the link is removed when the configuration is destroyed, maintaining cleanup hygiene. When executing terraform plan, Terraform indicates that these resources will be created, with values such as id and output marked as "known after apply" since they depend on the execution of the API action. Upon terraform apply, the actions are executed, and the state is updated with the returned values.

Authentication and Prerequisites

To effectively use the AzAPI provider, proper authentication to the Azure subscription is required. Prerequisites include an active Azure subscription. If a user does not have a subscription, a free account must be created before beginning. When logging in to the Azure portal with a Microsoft account, the default Azure subscription for that account is used. Terraform automatically authenticates using information from this default subscription. To verify the current Microsoft account and Azure subscription, the az account show command can be executed. This command displays the current context, ensuring that any changes made via Terraform are applied to the intended subscription.

Terraform supports multiple authentication methods, including service principals and managed identities. For service principal authentication using a client secret, the environment variables ARM_TENANT_ID, ARM_CLIENT_ID, and ARM_CLIENT_SECRET must be set. These credentials are then used by the AzAPI provider to authenticate API requests. The consistency of Azure authentication across providers ensures that teams can use the same authentication infrastructure for both AzureRM and AzAPI, simplifying CI/CD pipeline configuration.

Conclusion

The AzAPI Terraform provider represents a significant advancement in Azure infrastructure management by decoupling resource definition from the lag of provider SDK updates. Its direct integration with the Azure Resource Manager API allows for immediate access to new features, preview services, and the latest API versions. The provider’s generic resources, azapi_resource and azapi_update_resource, offer granular control and full state fidelity, ensuring that infrastructure definitions are both accurate and flexible. The accompanying tooling, including the Microsoft Terraform VS Code extension, aztfmigrate, and aztfexport, further enhances the developer experience by providing robust authoring support, seamless migration capabilities, and automated import processes. Whether managing standard resources, performing complex API actions such as Partner Admin Link creation, or migrating existing infrastructure, the AzAPI provider delivers the performance and precision required for modern cloud engineering. By leveraging its benefits of no Swagger dependency, built-in validation, and consistent authentication, organizations can accelerate their cloud delivery cycles and maintain alignment with the ever-evolving Azure service landscape.

Sources

  1. Azure Terraform Get Started with AzAPI
  2. Overview of the AzAPI Provider
  3. Azure Citadel PAL AzAPI

Related Posts