> For the complete documentation index, see [llms.txt](https://cookbook.geuer-pollmann.de/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cookbook.geuer-pollmann.de/azure/terraform.md).

# terraform

![Azure loves Terraform](/files/JILVpqzSVBdIp2Emq65t)

## ARM and terraform - Side by Side

| [ARM Templates](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/)                    | Terraform                                                               |
| ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| JSON w/ comments                                                                                             | HCL                                                                     |
| [Parameters](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-parameters)    | Variables                                                               |
| [Variables](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-variables)      | Local variables                                                         |
| Resources                                                                                                    | Resources                                                               |
| [Functions](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions)      | [Functions](https://www.terraform.io/docs/configuration/functions.html) |
| [Nested templates](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/linked-templates) | Modules                                                                 |
| Explicit                                                                                                     | Automatic                                                               |
| Refer by reference or resourceId                                                                             | Refer by resource or data source                                        |

## Providers

* Azure (i.e. Azure *Resource* Manager)
* ~~the 'old' Azure *Service* Management (ASM) provider~~
* Azure Active Directory (AAD)
* Azure Stack (on-premises)

## Authentication

<https://www.terraform.io/docs/providers/azurerm/index.html#authenticating-to-azure>

* AZ CLI - if environment has `az` CLI installed, re-use existing session
* Azure Managed Identity (on Azure compute resource)
* Azure Service Principals (with client secrets or X.509 certs)

## The [`"azurerm"`](https://www.terraform.io/docs/providers/azurerm/index.html) Provider (Azure Resource Manager)

* <https://www.terraform.io/docs/providers/azurerm/>
* <http://aka.ms/terraform>

```
provider "azurerm" {
  version         = "~> 1.40"
  alias           = "networking"
  subscription_id = var.subscription_id
  client_id = var.client_id
  client_secret = var.client_secret
}
```

## The [`"azure_ad"`](https://www.terraform.io/docs/providers/azurerm/index.html) Provider (Azure Resource Manager)

<https://www.terraform.io/docs/providers/azuread/index.html>

```
provider "azure_rm" {
  version         = "~> 0.7"
  subscription_id = var.subscription_id
  client_id       = var.client_id
  client_secret   = var.client_secret
}
```

### Azure-specific environment variables

* `ARM_ENVIRONMENT` - `public`, `usgovernment`, `german`, `china`
* `ARM_SUBSCRIPTION_ID` - Azure subscription ID
* `ARM_TENANT_ID` - Azure AD tenant ID for service principal
* `ARM_USE_MSI` - Use Managed Service Identity
* `ARM_CLIENT_ID` - Service principal ID
* `ARM_CLIENT_SECRET` - Service principal secret

## Remote state: the [`"azurerm"`](https://www.terraform.io/docs/backends/types/azurerm.html) backend

Stores state in a blob, in a container, in an Azure storage account.

```
terraform {
  backend "azurerm" {
    resource_group_name  = "longterm"
    storage_account_name = "chgeuer"
    container_name       = "terraformstate"
    key                  = "demo2.tfstate"
  }
}
```

### Authenticating to remote state backend

* Inherit authN info from outer environment, such as `az` CLI or service principal
* `use_msi`: Managed identity within Azure Compute
* `access_key`: The storage account's access key
* `sas_token`: A 'shared access signature' token

```bash
terraform init –backend-config="sas_token=gh67il=="`
```

Alternatively, Azure CosmosDB provides an etcd protocol head.

## Data Sources

Many data sources, including

* `azurerm`
  * [`"azurerm_subscriptions"`](https://www.terraform.io/docs/providers/azurerm/d/subscriptions.html): information about all the Subscriptions currently available
  * [`"azurerm_subscription"`](https://www.terraform.io/docs/providers/azurerm/d/subscription.html): information about an existing Subscription.
  * [`"azurerm_resource_group"`](https://www.terraform.io/docs/providers/azurerm/d/resource_group.html)
  * KeyVault, Networking, API Management, Compute, ...
* `azuread`
  * [`"azuread_application"`](https://www.terraform.io/docs/providers/azuread/r/application.html)
  * [`"azuread_service_principal"`](https://www.terraform.io/docs/providers/azuread/r/service_principal.html)
  * Users, Groups, Roles, ...

## Azure Modules in the Terraform Registry

<http://aka.ms/tfmodules>

![Screenshot from aka.ms/tfmodules](/files/PW08dBGCadZW8OkrAMTW)

## ARM / Terraform Interoperability

### [`"azurerm_template_deployment"`](https://www.terraform.io/docs/providers/azurerm/r/template_deployment.html): use ARM templates within Terraform

Example: <https://github.com/chgeuer/azure-snippets/blob/master/logic-app-reading-xml/terraform/modules/logicapp/main.tf>

```
resource "azurerm_template_deployment" "logicapp" {
  name                   = "deployment-${formatdate("YYYY-MM-DD--hh-mm-ss", timestamp())}"
  resource_group_name    = var.resource_group_name
  deployment_mode        = "Incremental"
  template_body          = file(local.arm_template_file)
  parameters = {
    "logicAppName"       = var.logic_app_name
    "logicAppDefinition" = var.logic_app_definition
  }
}
```

### Terraform Resource Provider (RP) in Azure ARM

* Private preview supporting three providers: Kubernetes, Cloudflare and Datadog
* <https://azure.microsoft.com/en-us/blog/introducing-the-azure-terraform-resource-provider/>

![](/files/dYzDSMdwaaPDyy8AJOUG)

## Available environments

* TF [installed](https://docs.microsoft.com/en-us/azure/terraform/terraform-cloud-shell) in the Azure Cloud Shell [shell.azure.com](https://shell.azure.com)
* [Marketplace VM images w/ terraform and MSI](http://aka.ms/aztfmkt)
* [VS Code Plugin for terraform](https://docs.microsoft.com/en-us/azure/terraform/terraform-vscode-extension)

![Screenshot from the Terraform VM marketplace image](/files/XZL1qdeW0tpPUlB9lYST)

## Learning resources for terraform on Azure

* [aka.ms/tfhub -- docs.microsoft.com](https://docs.microsoft.com/en-us/azure/terraform/)
* [Hashicorp Azure learning track](https://learn.hashicorp.com/terraform?track=azure#azure)
* [chrismatteson/hashicorp\_azure\_training](https://github.com/chrismatteson/hashicorp_azure_training) and the [slides](https://chrismatteson.github.io/hashicorp_azure_training/#55)
* [CardinalNow/TerraformWorkshop](https://github.com/CardinalNow/TerraformWorkshop)
* [Source Code aka.ms/tfgit](http://aka.ms/tfgit)
* [Using Azure DevOps pipelines to deploy via Terraform](https://www.azuredevopslabs.com/labs/vstsextend/terraform/)
