Using terraform 0.13.0 we have a scenario we where we want to create 1 to many keyvaults with 1 to many keyvault access policy objects and some of these object IDs are known up front eg: 1 to many Azure AD groups/users, and some are dynamic eg: MSI from 1 to many app services,
keyvaults = [
“kv1”,“kv2”,“kv3”]
keyvault_accesspolicyobjects = [“12345678-1234-abcd-df12-abc45678901x”,“12345678-5678-efgh-ui67-def45678901y”,“12345678-9101-ijkl-7g3f-hij45678901z”]
dynamic MSI’s
Using a single for_each we can loop through list “keyvaults” and create those no problem,
resource “azurerm_key_vault” “azure” {
for_each = toset(var.keyvaults)
name = each.key
location = azurerm_resource_group.azure.location
resource_group_name = azurerm_resource_group.azure.name
enabled_for_disk_encryption = true
tenant_id = data.azurerm_client_config.current.tenant_id
soft_delete_enabled = false
sku_name = “standard”
tags = var.tags
network_acls {
default_action = “Allow”
bypass = “AzureServices”
}
}
The next bit we want to apply is the keyvault access policy objects.
We loop through the key_vault_id and if the “object_id” is a single string this works without issue. However we cannot pass a list and as we cannot have more than 1 for_each we are not able to loop through either a static or dynamic list of object ids.
We’ve looked at setproduct() and tried using for_each in a locals block but that is also unsupported.
We’ve moved the for_each back to the parent module level but that also introduces other issues for us.
What other options should we consider?
resource “azurerm_key_vault_access_policy” “azure” {
for_each = toset(var.keyvaults)
key_vault_id = azurerm_key_vault.azure[each.key].id
tenant_id = data.azurerm_client_config.current.tenant_id
object_id = SECOND LOOP REQUIRED
key_permissions = [
“backup”, “create”, “decrypt”, “delete”, “encrypt”,
]
secret_permissions = [
“backup”, “delete”, “get”, “list”, “purge”, “recover”, “restore”, “set”
]
certificate_permissions = [
“get”,
]
}