There are a couple of ways off running Terraform code with Azure depending on how your workflow is designed. If you are running Terraform on your local machine, you can connect to Azure through PowerShell or Azure CLI and run the Terraform commands locally. This works fine for demo and development scenarios but when moving into production it is recommended to use a CI/CD pipeline.

When you run Terraform, you generate a state file that stores the current state of your managed infrastructure, configuration and metadata. You can read up on why Terraform uses a state file here but the short answer is: It enables Terraform to work with several cloud vendors and makes Terraform perform much better. The file usually resides on the machine you run your code on, but for teams working together it would be preferable to store it remotely.

FYI; Everything that I’m going to mention is readily available in the official Terraform docs so if you prefer to learn everything the hard way, or you just don’t like me rambling, feel free to dive straight into the nitty-gritty. I’m also currently reading Terraform: Up and Running, so if you’re into book-learning then that’s the one I recommend on this subject.

Running the Terraform in your favorite shell

Now that you’re sold on the idea of using Terraform to manage your infrastructure, you’d want to cut to the chase and run some code towards Azure. But hold on to your claws, Bub! First, we need to authenticate. When you’re starting out, you can get everything up and running by connecting to Azure with Azure CLI in the same terminal window as you are planning to run Terraform in.

You can connect to Azure by running the following Azure CLI command, then follow the instructions:

# Azure CLI
az login

For more information, read up on how to connect to Azure with Azure CLI in the Microsoft Docs.

After you have connected your shell to Azure, you can now run your Terraform config files directly towards Azure.

Working with a Service Principal

So far we have authenticated within a shell to run Terraform but there comes a time where you have to either run Terraform on a shared server or better yet through a CI/CD pipeline. When that time comes, you want Terraform to be able to authenticate so you or the people you work with don’t have to authenticate all the time.

You can define a Service Principal and secret as Environment variables, or directly in the configuration file. The first one is highly recommended as the alternative is to store sensitive information in plain text. You could also use a service principal with a client certificate.

To set up a service principal, you would need a Client ID (Application ID), Client Secret, your subscription ID, and tenant ID.

There is no reason to invent the wheel over again, so for the setup itself, I’ll just refer to the Terraform docs. However, I prefer to use PowerShell for all things, and they tend to use bash and Azure CLI in their examples so here are the steps that they refer to Azure CLI but the PowerShell counterpart.

# Connect to Azure
Connect-AzAccount

# Connect to Azure if using China, Germany or Government Cloud
Connect-AzAccount -Environment <AzureChinaCloud|AzureGermanCloud|AzureUSGovernment>

# Fetch your subscription, which also gives you the tenant ID where it resides
Get-AzSubscription

# Create Service Principal
New-AzADServicePrincipal -DisplayName "Terraform-Auth" -Role Contributor -Scope "/subscriptions/SUBSCRIPTION_ID"

# After following the steps in the Terraform Docs
# storing the credentials as environment variables
New-Item -Path "Env:\" -Name ARM_CLIENT_ID -Value "00000000-0000-0000-0000-000000000000"
New-Item -Path "Env:\" -Name ARM_CLIENT_SECRET -Value "00000000-0000-0000-0000-000000000000"
New-Item -Path "Env:\" -Name ARM_SUBSCRIPTION_ID -Value "00000000-0000-0000-0000-000000000000"
New-Item -Path "Env:\" -Name ARM_TENANT_ID -Value "00000000-0000-0000-0000-000000000000"