Using AzAPI in Terraform
Here is an example Terraform config to create the Partner Admin Link using azapi_resource_action, useful in CI/CD and subscription vending machine situations.
Table of Contents
Introduction
You can also create a Partner Admin Link easily if you have a Terraform config that runs as a service principal or managed identity.
Remember that each security principal can be linked to only one partner ID.
The examples use 314159 as a placeholder as I won’t be sharing the partner ID that I use for testing!
Example Terraform config
There are multiple ways for azapi to authenticate as a service principal or managed identity.
This example is based on Authentication: Authenticating via a Service Principal and a Client Secret, and assumes that you have exported ARM_TENANT_ID, ARM_CLIENT_ID, and ARM_CLIENT_SECRET.
terraform {
required_providers {
azapi = {
source = "azure/azapi"
version = ">= 2.8.0"
}
}
}
provider "azapi" {}
variable "partner_id" {
type = string
default = "314159"
}
resource "azapi_resource_action" "pal" {
type = "Microsoft.ManagementPartner/partners@2018-02-01"
resource_id = "/providers/Microsoft.ManagementPartner/partners/${var.partner_id}"
method = "PUT"
when = "apply"
body = {
partnerId = var.partner_id
}
response_export_values = {
id = "id"
objectId = "properties.objectId"
partnerName = "properties.partnerName"
partnerId = "properties.partnerId"
}
}
resource "azapi_resource_action" "pal_destroy" {
type = "Microsoft.ManagementPartner/partners@2018-02-01"
resource_id = "/providers/Microsoft.ManagementPartner/partners/${var.partner_id}"
method = "DELETE"
when = "destroy"
depends_on = [azapi_resource_action.pal]
}
output "pal" {
value = azapi_resource_action.pal.output
}
Example Terraform run
-
Initialise
terraform initExpected output:Initializing the backend... Initializing provider plugins... - Reusing previous version of azure/azapi from the dependency lock file - Installing azure/azapi v2.8.0... - Installed azure/azapi v2.8.0 (signed by a HashiCorp partner, key ID 6F0B91BDE98478CF) Partner and community providers are signed by their developers. If you'd like to know more about provider signing, you can read about it here: https://developer.hashicorp.com/terraform/cli/plugins/signing Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
-
Validate
terraform validateExpected output:Success! The configuration is valid. -
Plan
terraform planExpected output:Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azapi_resource_action.pal will be created + resource "azapi_resource_action" "pal" { + body = { + partnerId = "314159" } + id = (known after apply) + method = "PUT" + output = (known after apply) + resource_id = "/providers/Microsoft.ManagementPartner/partners/314159" + response_export_values = { + id = "id" + objectId = "properties.objectId" + partnerId = "properties.partnerId" + partnerName = "properties.partnerName" } + sensitive_output = (sensitive value) + type = "Microsoft.ManagementPartner/partners@2018-02-01" + when = "apply" } # azapi_resource_action.pal_destroy will be created + resource "azapi_resource_action" "pal_destroy" { + id = (known after apply) + method = "DELETE" + output = (known after apply) + resource_id = "/providers/Microsoft.ManagementPartner/partners/314159" + sensitive_output = (sensitive value) + type = "Microsoft.ManagementPartner/partners@2018-02-01" + when = "destroy" } Plan: 2 to add, 0 to change, 0 to destroy. Changes to Outputs: + pal = (known after apply) ───────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
-
Apply
terraform applyExpected output:- snip - Plan: 2 to add, 0 to change, 0 to destroy. Changes to Outputs: + pal = (known after apply) Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. yes Enter a value: azapi_resource_action.pal: Creating... azapi_resource_action.pal: Still creating... [00m10s elapsed] azapi_resource_action.pal: Creation complete after 15s [id=/providers/Microsoft.ManagementPartner/partners/314159] azapi_resource_action.pal_destroy: Creating... azapi_resource_action.pal_destroy: Creation complete after 0s [id=/providers/Microsoft.ManagementPartner/partners/314159] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: pal = { "id" = "/providers/microsoft.managementpartner/partners/314159" "objectId" = "84964f8f-22ce-4a1e-ba9d-1e45a53ca1c4" "partnerId" = "314159" "partnerName" = "Azure Citadel" }
-
Destroy
⚠️ Only use the destroy switch if you are intending to remove the applied config. This is included here to demonstrate the azapi_resource_action.pal_destroy block.terraform destroyExpected output:azapi_resource_action.pal: Refreshing state... [id=/providers/Microsoft.ManagementPartner/partners/314159] azapi_resource_action.pal_destroy: Refreshing state... [id=/providers/Microsoft.ManagementPartner/partners/314159] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: - destroy Terraform will perform the following actions: # azapi_resource_action.pal will be destroyed - resource "azapi_resource_action" "pal" { - body = { - partnerId = "314159" } -> null - id = "/providers/Microsoft.ManagementPartner/partners/314159" -> null - method = "PUT" -> null - output = { - id = "/providers/microsoft.managementpartner/partners/314159" - objectId = "84964f8f-22ce-4a1e-ba9d-1e45a53ca1c4" - partnerId = "314159" - partnerName = "Azure Citadel" } -> null - resource_id = "/providers/Microsoft.ManagementPartner/partners/314159" -> null - response_export_values = { - id = "id" - objectId = "properties.objectId" - partnerId = "properties.partnerId" - partnerName = "properties.partnerName" } -> null - sensitive_output = (sensitive value) -> null - type = "Microsoft.ManagementPartner/partners@2018-02-01" -> null - when = "apply" -> null } # azapi_resource_action.pal_destroy will be destroyed - resource "azapi_resource_action" "pal_destroy" { - id = "/providers/Microsoft.ManagementPartner/partners/314159" -> null - method = "DELETE" -> null - resource_id = "/providers/Microsoft.ManagementPartner/partners/314159" -> null - type = "Microsoft.ManagementPartner/partners@2018-02-01" -> null - when = "destroy" -> null } Plan: 0 to add, 0 to change, 2 to destroy. Changes to Outputs: - pal = { - id = "/providers/microsoft.managementpartner/partners/314159" - objectId = "84964f8f-22ce-4a1e-ba9d-1e45a53ca1c4" - partnerId = "314159" - partnerName = "Azure Citadel" } -> null Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. yes Enter a value: azapi_resource_action.pal_destroy: Destroying... [id=/providers/Microsoft.ManagementPartner/partners/314159] azapi_resource_action.pal_destroy: Still destroying... [id=/providers/Microsoft.ManagementPartner/partners/314159, 00m10s elapsed] azapi_resource_action.pal_destroy: Destruction complete after 15s azapi_resource_action.pal: Destroying... [id=/providers/Microsoft.ManagementPartner/partners/314159] azapi_resource_action.pal: Destruction complete after 0s Destroy complete! Resources: 2 destroyed.
Equivalent Azure CLI commands
These are included for reference only.
-
Set the partner ID
partnerId=314159 -
Authenticate
az login --service-principal --username "${ARM_CLIENT_ID}" --password "${ARM_CLIENT_SECRET}" --tenant "${ARM_TENANT_ID}" --allow-no-subscriptions -
Set the URI
uri="https://management.azure.com/providers/microsoft.managementpartner/partners/${partnerId}?api-version=2018-02-01" -
Create the Partner Admin Link
az rest --method PUT --url $uri --body '{"partnerId": "'${partnerId}'"}' -
Delete the Partner Admin Link
az rest --method DELETE --url $uri