Deploying to Multiple Azure Subscriptions with Terraform

A quick tip this week if your working with Terraform and Azure. Generally, when you run a deployment against Azure with Terraform, you provide the subscription ID used by your deployment either through environment variables, as part of the Azure Provider or based on the subscription you selected in the Azure CLI. This configuration is fine if everything you are deploying in your template is in the same subscription, but if you find you need to create some resources in another subscription, then this can cause a problem. Thankfully Terraform provides a simple solution.

To give an example of where you might do this, I've recently been deploying some AKS clusters in one subscription. Along with the subscription I am creating ea DNS records in an Azure DNS zone, to point to the cluster. This DNS zone is one shared between many projects and so is stored in a separate subscription used for shared resources. Let's look at how we can do that.

Pre-Requisites

The critical thing you need to have in place is that the account you are using to do the deployment (be this user, service principal or managed identity) needs to have rights to both subscriptions to create whatever resources are required.

Providers

To allow us to create resources in multiple subscriptions, we are going to be creating multiple AzureRM providers.

In a standard deployment using only a single subscription, you would have a single AzureRM provider setup.

provider "azurerm" {
  version = "=1.34.0"
}

You might be including the subscription and authentication details inside this provider, or separately as environment variables.

To allow us to use another subscription, we are going to define a second AzureRM provider. However, we can't just have multiple providers on their own; you will get an error about duplicate entries. We need to provide an alias for our second provider so we can refer to it later.

provider "azurerm" {
  alias           = "core"
  subscription_id = "xxxx-xxxx-xxxx"
}

Here we are creating a provider with an alias of "core". We are then setting the subscription ID in this provider to be the ID of our other subscription. We're now set to use this in our deployment.

Create Resources

Now that we have the provider setup for our second sub, we need to use it in our DNS record creation. This is as simple as adding a provider entry to our record referencing the alias of our second provider.

All our other resources will not have a provider defined and so will use the default azurerm (no alias) provider and use the primary subscription.

As our DNS Zone already exists in our core subscription, the first thing we need to do is create a data item referencing that zone. We'll use the alias for our new provider here. We reference it with the syntax of "azurerm."

data "azurerm_dns_zone" "samcogan" {
  provider            = "azurerm.core"
  name                = "samcogan.com"
  resource_group_name = "samcogan-core"
}

Now we've got our DNS zone data item we can create our record, again using the alias to our provider.

resource "azurerm_dns_a_record" "test" {
  provider            = "azurerm.core"
  name                = "test"
  zone_name           = "${azurerm_dns_zone.test.samcogan}"
  resource_group_name = "samcogan-core"
  ttl                 = 300
  records             = ["200.200.200.200"]
}

When we run this deployment, our DNS record will now be successfully created in the right subscription.

You can add as many providers as you want, so long as they each have their alias.