# terraform

![Azure loves Terraform](https://439978545-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDiEVTiIb6z0zL45wfNrM%2Fuploads%2Fgit-blob-76ebb5cbfaf095e743d3367642cd792a314a794d%2Fazure-loves-terraform.svg?alt=media)

## 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](https://439978545-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDiEVTiIb6z0zL45wfNrM%2Fuploads%2Fgit-blob-47545ccb071279432f758ad5724860eff697204e%2Fterraform-azure-modules.png?alt=media)

## 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/>

![](https://439978545-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDiEVTiIb6z0zL45wfNrM%2Fuploads%2Fgit-blob-07eb7443f81723a9d5bc77b7394989c202d0626f%2Fterraform-azure-rp.svg?alt=media)

## 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](https://439978545-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDiEVTiIb6z0zL45wfNrM%2Fuploads%2Fgit-blob-4479f525454bda6d3e7fb873863bab1aef8749a4%2Fterraform-azure-vm.png?alt=media)

## 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/)
