Azure CAF: Enterprise Scale: Subscription association not working correctly

I’ve been attempting to spin up an environment and keep running into issues with CAF and subscriptions that I had not previously encountered during my proof of concept ~9 months ago.

I’m specifically having issues with the templates referenced in the lv200 and above,

Most specifically with the following values in main.tf
subscription_id_connectivity = “xxxxxxxx-xxx-xxx-xxx-xxxxxxxxxxxx”
subscription_id_identity = “xxxxxxxx-xxx-xxx-xxx-xxxxxxxxxxxx”
subscription_id_management = “xxxxxxxx-xxx-xxx-xxx-xxxxxxxxxxxx”

The subscription ID I supply to those values is getting properly associated with the corresponding management group, however only a few of the resource groups and resources created are being associated with the proper subscription.
Aside from networkwatcherRG and one other minor resource that are correctly associated with the connectivity subscription, the management, connectivity, identity and other RG’s are all getting associated with whatever subscription the az context is currently set to.

This is causing the linking of resources, such as log analytics to fail as terraform is trying to create the link supplying the expected subscription ID as part of the resource’s location when terraform had built it using whatever the current context subscription was.

Things will sort of deploy if I leave the values at data.azurerm_client_config.core.subscription_id however some provisioning items have a tendency to fail due to the one subscription getting bounced back and forth between the Management Groups.

I’ve tried both using the latest version of terraform (windows) + Azure CLI and the Azure Portal’s built in terraform with the same result.

Example of what my main.tf looks like

# Get the current client configuration from the AzureRM provider.
# This is used to populate the root_parent_id variable with the
# current Tenant ID used as the ID for the "Tenant Root Group"
# Management Group.

data "azurerm_client_config" "core" {}

# Declare the Azure landing zones Terraform module
# and provide a base configuration.

module "enterprise_scale" {
  source  = "Azure/caf-enterprise-scale/azurerm"
  version = "2.1.2"

  providers = {
    azurerm              = azurerm
    azurerm.connectivity = azurerm
    azurerm.management   = azurerm
  }
  # Global
  root_parent_id = data.azurerm_client_config.core.tenant_id
  root_id        = var.root_id
  root_name      = var.root_name
  library_path   = "${path.root}/lib"
  # Connectivity
  deploy_connectivity_resources    = var.deploy_connectivity_resources
  subscription_id_connectivity     =  "xxxxxxxx-xxx-xxx-xxx-xxxxxxxxxxxx"
  configure_connectivity_resources = local.configure_connectivity_resources
  # Identity
  deploy_identity_resources    = var.deploy_identity_resources
  subscription_id_identity     =  "xxxxxxxx-xxx-xxx-xxx-xxxxxxxxxxxx"
  configure_identity_resources = local.configure_identity_resources
  # Management
  deploy_management_resources    = var.deploy_management_resources
  # subscription_id_management     = data.azurerm_client_config.core.subscription_id
  subscription_id_management     = "xxxxxxxx-xxx-xxx-xxx-xxxxxxxxxxxx"
  configure_management_resources = local.configure_management_resources
  # Misc

}

Hi @gawainXX

In addition to setting the subscription_id_xxxxx values, you also need to configure the provider settings to target the required Subscription for resource creation.

This is documented here in the Wiki:
[User Guide] Provider Configuration · Azure/terraform-azurerm-caf-enterprise-scale Wiki (github.com)

This abstraction was intentional to allow the module to behave correctly in environments where different pipelines (possibly with different credentials/permissions) are used to deploy different subsets of resources (e.g. core, vs connectivity, vs management).

This is also a limitation of how the Terraform provider for Azure is currently designed to only target a single Azure subscription per provider declaration. We are working with the provider team to see whether we can get an optional “parent_id” attribute added to all resources so it’s possible to target multiple Subscriptions without having to declare multiple providers.

Hope this helps?