The AzAPI
Terraform Provider for deploying and managing Microsoft Azure resources is a lightweight, “thin layer” provider built on top of the Azure ARM (Azure Resource Manager) REST APIs. This enables the management of any Microsoft Azure resource using any Azure ARM API version. The primary benefit of the AzAPI
Terraform Provider is that it can be used to deploy and manage new Azure resources and resource properties that aren’t yet supported by the azurerm
Terraform Provider.
Use AzAPI Terraform Provider to managed Azure Preview Resources and Properties
The AzAPI
Terraform Provider supports only couple different resource
in Terraform. This is not an expansive list of different Microsoft Azure resources, since the intention of this provider is to enable management of resources not yet supported by the azurerm
Terraform Provider, including Preview Properties of the Azure Resources that are supported by the azurerm
provider.
For this simplistic, yet powerful, reason for the AzAPI
Provider, this provider only supported these two Terraform resources:
azapi_resource
– Used for managing Azure Resources that are not yet supported by theazurerm
Terraform Provider.azapi_update_resource
– Used for managing Preview Properties of Azure Resources that are not yet supported by theazurerm
Terraform Provider.
Essentially, you’ll want to generally use the azurerm
Terraform Provider when managing Azure Resources using Terraform Infrastructure as Code projects. However, there are times when that provider does not yet support a specific Azure Resource or property needs to be managed from Terraform. In these special cases, the AzAPI
Terraform Provider provides the capabilities to manage these resources and properties from Terraform.
The way the AzAPI
Terraform Provider works is it is built as a thin layer on top of the Azure ARM (Azure Resource Management) REST APIs. This enables AzAPI
to be able to manage any Azure Resource as long as the Azure Resource Type symbolic name and API Version are specified.
When setting the value of the type
attribute on either of the azapi_resource
or azapi_update_resource
resources, the format for the expected value is as follows:
<azure-resource-type>@<api-version>
The placeholders in the previous Azure Resource symbolic type and API version definition will be replace by the following values to specify a particular Azure Resource:
azure-resource-type
– This is the symbolic name of the Azure ARM Resource Type to be managed.api-version
– This is the Azure ARM REST API Version for the specific Azure Resource Type specified. This will need to be a supported API Version for the specific Azure Resource Type that’s being targeted with theAzAPI
provider.
The following is a full Azure Resource symbolic type with API version to help add clarity on specifying the necessary values on managing resources, like the Custom IP Prefixes resource in Azure:
Microsoft.Network/customIpPrefixes@2021-03-01
On a related note, the symbolic name of the Azure ARM Resource Type and API Version is similar what Azure Bicep uses to support managing any Azure Resource using that set of IaC tooling for Microsoft Azure.
azapi_resource
Resource Definition
The azapi_resource
resources is used for managing Azure Resources that are not yet supported by the azurerm
Terraform Provider. Without a specific Terraform resource defined in the AzAPI
provider, the azapi_resource
resource is used with the type
attribute set to the Azure ARM Resource Type name and API Version to target within the Azure REST API.
The following is an example targeting the Azure Custom IP Prefixes resource type (Microsoft.Network/customIpPrefixes
) using the 2021-03-01
API Version:
resource "azapi_resource" "build5nines_publicip" {
type = "Microsoft.Network/customIpPrefixes@2021-03-01"
name = "build5nines_publicip"
parent_id = azurerm_resource_group.example.id
location = "northcentralus"
body = jsonencode({
properties = {
cidr = "10.0.0.0/24"
signedMessage = "Sample Message for WAN"
}
})
}
In the previous example, there are a few additional attributes configured on the azapi_resource
resource to configure the necessary properties on the Azure Resource being managed. The definition of these additional attributes are as follows:
name
– The name of the Azure Resourceparent_id
– The Azure Resource ID for the Azure Resource that will be the Parent of this Azure Resource. The previous example shows setting this to the Resource ID of an Azure Resource Group to place the resource in.location
– This is the Azure Region / Location to provision the resource within.body
– This is set to a JSON encoding of all the required properties to configure on the Azure Resource being managed.
The body
attribute is set using a Terraform object that contains all the necessary properties and values needed for the resource. Then, the Terraform jsonencode()
function is used to encode that Terraform object into a JSON string that is then passed to the asapi_resource
resources body
property. This JSON string is what gets passed as the body of the Azure ARM REST API request made to manage the Azure Resource.
The following is an additional example of defining the azapi_resource
Terraform resource from the AzAPI
provider. This time to manage a Microsoft.MachineLearningServices/workspaces/compute
Azure Resource.
resource "azapi_resource" "build5nines_machinelearning_compute" {
name = "build5nines_ml_compute"
parent_id = data.azurerm_machine_learning_workspace.existing.id
type = "Microsoft.MachineLearningServices/workspaces/computes@2021-07-01"
location = "eastus"
body = jsonencode({
properties = {
computeType = "ComputeInstance"
disableLocalAuth = true
properties = {
vmSize = "STANDARD_NC6"
}
}
})
}
azapi_update_resource
Resource Definition
The azapi_update_resource
resource is used for managing Preview Properties of Azure Resources that are not yet supported by the azurerm
Terraform Provider. Without a specific Terraform resource defined in the AzAPI
provider, the azapi_update_resource
resource is used with the type
attribute set to the Azure ARM Resource Type name and API Version to target within the Azure REST API.
The following is an example targeting the the Azure Container Registry resource type (Microsoft.ContainerRegistry/registries
) using the 2020-11-01-preview
API Version to set the anonymousPullEnabled
Preview Feature:
resource "azapi_update_resource" "test" {
type = "Microsoft.ContainerRegistry/registries@2020-11-01-preview"
resource_id = azurerm_container_registry.acr.id
body = jsonencode({
properties = {
anonymousPullEnabled = var.bool_anonymous_pull
}
})
}
NOTE: The
anonymousPullEnabled
Preview Property of the Azure Container Registry resource is likely no longer in Preview, but this example still represents the method for how theazapi_update_resource
resource is used to manage Preview Properties within Microsoft Azure.
In the previous example, there are a few additional attributes configured on the azapi_update_resource
resource to configure the necessary properties on the targeted Azure Resource. The definition of these additional attributes are as follows:
resource_id
– This is set to the Azure Resource ID for the Azure Resource targeted to update the properties of.body
– This is set to a JSON encoding of all the required properties to configure on the Azure Resource being managed.
The body
attribute is set in the same fashion on the azapi_update_resource
resource to the azapi_resource
resource. This enables the necessary Azure Resource Preview Properties to be defined and set to the necessary values to manage them using the AzAPI
Terraform Provider.
AzAPI Provider Definition
The AzAPI
Terraform Provider is defined in a Terraform Project using the provider
block just like any other Terraform Provider. This is done similar to defining the azurerm
Terraform Provider
# Using required_providers is recommended best practice
# when defining Terraform Providers on a project.
terraform {
required_providers {
azapi = {
source = "azure/azapi"
}
}
}
provider "azapi" {
# subscription_id = "..."
# client_id = "..."
# client_secret = "..."
# tenant_id = "..."
}
There are several attributes supported for use on the provider
block when using the AzAPI
Terraform Provider to define the Azure Service Principal or Managed Identity to use when authenticating with Microsoft Azure. These are very similar to the attributes supported by the azurerm
Provider too.
client_id
– (Optional) Client ID to use.subscription_id
– (Optional) Subscription ID for the Azure Subscription to use.tenant_id
– (Optional) The Tenant ID of the Azure AD Tenant to authenticate against.client_secret
– (Optional) The Client Secret to use when authenticating with Service Principal.
Also, the AzAPI
and azurerm
Terraform Providers can be used together in the same Terraform Project to enable all the required Azure resources to be deployed and managed.
Authenticate AzAPI Provider with Azure
Authenticating the AzAPI
Terraform Provider against an Azure Subscription is performed the same way as using the azurerm
Terraform Provider. The easiest way to authenticate the AzAPI
provider is to use the Azure CLI to login to an Azure Subscription, then the AzAPI
Terraform Provider will automatically use the account logged in with to authenticate itself against the Azure Subscription when managing resources.
Overall there are three methods that can be used to authenticate the AzAPI
provider against Microsoft Azure. The following list shows the different methods supported:
- Login using Azure CLI (
az login
) and set the Azure Subscription (az account set
) to the necessary Azure Subscription. - Create a Service Principal within Azure AD with permissions on the Azure Subscription necessary for the provider to manage resources.
- Pass Service Principal to Terraform using Environment Variables
- Pass Service Principal to Terraform using
provider
block
Login using Azure CLI
The Azure CLI can be used to authenticate with Microsoft Azure, then the AzAPI
Terraform Provider will be able to use those credentials to manage Azure Resources. Logging in to Azure is done using the az login
command, and then the az account set
command is used to explicitly tell the Azure CLI which Azure Subscription to target subsequent resources commands towards. This is important to specify when the logged in account has access to multiple Azure Subscriptions.e
az login
az account set --subscription "<azure-subscription-id|azure-subscription-name>"
When using the az account set
command, the --subscription
argument is used to specify the Azure Subscription to target. This argument accepts either the GUID that is the Azure Subscription ID, or the text name of the Azure Subscription. Since Azure Subscriptions can be renamed but their GUID will never change, it’s best practice to use the Azure Subscription ID in scripts and workflow pipelines so they don’t break if the subscription name is changed at some point in the future.
Pass Service Principal Credentials using Environment Variables
The credential information for the Service Principal to authenticate against Microsoft Azure can be specified using Environment Variables. This works the same in different environments. The AzAPI
provider will automatically pull in the values from Environment Variables if they are named as follows:
ARM_SUBSCRIPTION_ID
– This needs to be set to the Azure Subscription ID (guid).ARM_TENANT_ID
– This will be the Azure Subscription Tenant ID (guid), or otherwise known as the Azure Active Directory ID.ARM_CLIENT_ID
– This needs to be the “Client ID” or “App ID” for the Service Principal that was created in Azure AD.ARM_CLIENT_SECRET
– This needs to be the “Client Secret” (aka Password) for the Service Principal that was created in Azure AD.
The following are examples of setting the environment variables using both bash and PowerShell:
# Use Bash to set Environment Variables
export ARM_SUBSCRIPTION_ID="<azure-subscription-id>"
export ARM_TENANT_ID="<azure-ad-tenant-id>"
export ARM_CLIENT_ID="<service-principal-app-id>"
export ARM_CLIENT_SECRET="<service-principal-secret>"
# Use PowerShell to set Environment Variables
$env:ARM_SUBSCRIPTION_ID="<<azure-subscription-id>"
$env:ARM_TENANT_ID="<azure-ad-tenant-id>"
$env:ARM_CLIENT_ID="<service-principal-app-id>"
$env:ARM_CLIENT_SECRET="<service-principal-secret>"
Once the Environment Variables are set with the necessary values for the Azure Subscription and Service Principal to target, then the AzAPI
provider will automatically pull those values in without needing to add additional configurations to the provider
block within the Terraform Project.
Pass Service Principal Credentials using provider
block
The AzAPI
provider also supports the ability to configure the provider
block with attributes to set the necessary values to authenticate with the Azure Subscription and Service Principal. This can be done using the Terraform provider
block as follows:
# We strongly recommend using the required_providers block to set the
# Azure Provider source and version being used
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=3.0.0"
}
}
}
# Configure the Microsoft Azure Provider
provider "azurerm" {
features {}
subscription_id = "00000000-0000-0000-0000-000000000000"
tenant_id = "00000000-0000-0000-0000-000000000000"
client_id = "00000000-0000-0000-0000-000000000000"
client_secret = "xxxxxxxxxxxxxxxxxxxx"
}
While it’s not recommended to hard code the “Client Secret” for the Service Principal, you could hard code the other values if desired. If the organization has a different Azure Subscriptions for each environment being deployed within, then it may not make sense to hard code these values at all. In this case, provider
block is able to be configured to pull these values from input variables or event custom environment variables instead.
Input variables can be defined on the Terraform Project, and then those variables can be used to set the provider
attributes to set values like the Azure Subscription ID or Client ID and Secret to use for authenticating with Microsoft Azure. This is defined in the same syntax as using any other input variables in Terraform.
The following is an example showing the Terraform code for adding a input variable to the project and setting one of the attributes on the AzAPI
provider:
variable "azure_subscription_id" {
type = string
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
# other attributes set similarly
}
Custom Environment Variables can be used in a similar fashion to using input variables to set the AzAPI
provider attributes to authenticate with Azure. The Environment Variables must be set before running Terraform commands. In the Terraform code, on the provider
block for the AzAPI
provider, the custom Environment Variables can be accessed using the env.
prefix, in a similar fashion to the var.
prefix for input variables, using the name of the Environment Variable.
The following is are examples of setting a custom Environment Variable using both bash and PowerShell:
# Use Bash to set Environment Variables
export CUSTOM_AZURE_SUBSCRIPTION_ID="<azure-subscription-id>"
# Use PowerShell to set Environment Variables
$env:CUSTOM_AZURE_SUBSCRIPTION_ID="<<azure-subscription-id>"
After the custom Environment Variables are created, the Terraform provider
block for the AzAPI
provider can reference them as follows:
provider "azurerm" {
features {}
subscription_id = env.CUSTOM_AZURE_SUBSCRIPTION_ID
# other attributes set similarly
}