I have a PowerShell script that creates an Azure API Management service with a custom HTTPS domain using an SSL certificate stored in an Azure key vault. I'm converting it to Terraform but running into a problem.
Terraform creates the APIM with a ‘System Assigned’ identity, and the ID needs to be granted permissions in the key vault to access the SSL cert so APIM can be created with the custom domain. However, Terraform can’t grant the ID access to key vault until APIM has been created, but APIM can’t be created until the ID has been granted access to key vault.
Relevant snippet:
resource "azurerm_api_management" "apim" {
name = var.apim_name
resource_group_name = var.rg_name
location = var.location
publisher_name = var.publisher_name
publisher_email = var.publisher_email
sku_name = var.sku_name_capacity
virtual_network_type = var.vnet_type
hostname_configuration {
dynamic "proxy" {
for_each = var.gateway_endpoint_custom_domains
content {
host_name = proxy.value
key_vault_id = var.ssl_cert_secret_id
}
}
}
identity {
# User assigned identities are not supported yet
type = "SystemAssigned"
}
virtual_network_configuration {
subnet_id = var.subnet_id
}
}
resource "azurerm_key_vault_access_policy" "apim_said" {
key_vault_id = var.kv_id
object_id = var.apim_said_principal_id
tenant_id = data.azurerm_client_config.current.tenant_id
secret_permissions = [
"Get",
"List"
]
}
In PowerShell, this can be done with three steps in the one script:
As far as I understand, Terraform doesn’t have the ability to perform these three steps in a single step because Terraform wants to create the resource as a whole rather than create & modify later.
Can Terraform be used similar to the PowerShell script by using modules? I noticed in Azure Portal that User Assigned Identities are in preview but Terraform does not support this as yet.
If multiple Terraform runs is the only option, what’s the ‘proper’ way to structure and trigger subsequent runs using Terraform Cloud? The only way that would work, as far as I can tell, is if I had two Terraform Cloud workspaces with a shared state, but I hope there’s a more elegant solution.
To create APIM, giving access to Keyvault, and setting the domain settings, you can use something like below to resolve the issue:
provider "azurerm"{
features{}
}
data "azurerm_client_config" "current" {}
resource "azurerm_api_management" "apim" {
name = "ansuman-apim"
resource_group_name = "resourcegroup"
location = "West US 2"
publisher_name = "company"
publisher_email = "[email protected]"
sku_name = "Developer_1"
identity {
# User assigned identities are not supported yet
type = "SystemAssigned"
}
}
resource "azurerm_key_vault_access_policy" "apim_said" {
key_vault_id = "/subscriptions/b83c1ed3-xxxx-xxxxx-xxxxx-xxxx/resourceGroups/resourcegroup/providers/Microsoft.KeyVault/vaults/testkeyvautlansuman007"
object_id = azurerm_api_management.apim.identity[0].principal_id
tenant_id = data.azurerm_client_config.current.tenant_id
secret_permissions = [
"Get",
"List"
]
}
resource "null_resource" "previous" {}
resource "time_sleep" "wait_60_seconds" {
depends_on = [azurerm_key_vault_access_policy.apim_said]
create_duration = "60s"
}
resource "azurerm_api_management_custom_domain" "example" {
api_management_id = azurerm_api_management.apim.id
proxy {
host_name = "ansuman.xyz.com"
key_vault_id = "https://testkeyvautlansuman007.vault.azure.net/secrets/test/3a6ebe74364xxxxxxxxxxx"
}
depends_on = [
time_sleep.wait_60_seconds
]
}
Note: Due to this drawback of azurerm_api_management not able to access keyvault while creation from Terraform, azurerm_api_management_custom_domain was added. So, that you can create the APIM with identity and give access to keyvault and then use the custom domain block to add the host_configurations to the APIM that you have created.
Output:


If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With