mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
Refactor the azurerm backend (#3034)
Signed-off-by: Larry Bordowitz <laurence.bordowitz@gmail.com>
This commit is contained in:
@@ -9,81 +9,11 @@ Stores the state as a Blob with the given Key within the Blob Container within [
|
||||
|
||||
This backend supports state locking and consistency checking with Azure Blob Storage native capabilities.
|
||||
|
||||
## Example Configuration
|
||||
## Example Configurations
|
||||
|
||||
When authenticating using the Azure CLI or a Service Principal (either with a Client Certificate or a Client Secret):
|
||||
### Access Key
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "StorageAccount-ResourceGroup"
|
||||
storage_account_name = "abcd1234"
|
||||
container_name = "tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
When authenticating using Managed Service Identity (MSI):
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "StorageAccount-ResourceGroup"
|
||||
storage_account_name = "abcd1234"
|
||||
container_name = "tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
use_msi = true
|
||||
subscription_id = "00000000-0000-0000-0000-000000000000"
|
||||
tenant_id = "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
When authenticating using OpenID Connect (OIDC):
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "StorageAccount-ResourceGroup"
|
||||
storage_account_name = "abcd1234"
|
||||
container_name = "tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
use_oidc = true
|
||||
subscription_id = "00000000-0000-0000-0000-000000000000"
|
||||
tenant_id = "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
When authenticating using Azure AD Authentication:
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
storage_account_name = "abcd1234"
|
||||
container_name = "tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
use_azuread_auth = true
|
||||
subscription_id = "00000000-0000-0000-0000-000000000000"
|
||||
tenant_id = "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
When using AzureAD for Authentication to Storage you also need to ensure the `Storage Blob Data Owner` role is assigned.
|
||||
:::
|
||||
|
||||
***
|
||||
|
||||
When authenticating using the Access Key associated with the Storage Account:
|
||||
This examples authenticates using the Access Key associated with the Storage Account:
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
@@ -92,43 +22,199 @@ terraform {
|
||||
container_name = "tfstate"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
# rather than defining this inline, the Access Key can also be sourced
|
||||
# from an Environment Variable - more information is available below.
|
||||
access_key = "abcdefghijklmnopqrstuvwxyz0123456789..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We recommend using the environment variable `ARM_ACCESS_KEY` instead of storing sensitive information in your source code.
|
||||
|
||||
***
|
||||
|
||||
When authenticating using a SAS Token associated with the Storage Account:
|
||||
|
||||
### Shared Access Signature
|
||||
|
||||
This example authenticates using the SAS Token, which is a set of query parameters signed with the Access Key associated with the Storage Account:
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
storage_account_name = "abcd1234"
|
||||
container_name = "tfstate"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
# rather than defining this inline, the SAS Token can also be sourced
|
||||
# from an Environment Variable - more information is available below.
|
||||
sas_token = "abcdefghijklmnopqrstuvwxyz0123456789..."
|
||||
sas_token = "sv=2024-11-04&ss=b&srt=sco&sp=rwdlaciytfx&se=2025-08-05T23:46:49Z&st=2025-08-05T15:31:49Z&spr=https&sig=abcdefg..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We recommend using the environment variable `ARM_SAS_TOKEN` instead of storing sensitive information in your source code.
|
||||
|
||||
***
|
||||
|
||||
### Using Entra ID (Previously AzureAD)
|
||||
|
||||
The previous two authentication methods are specific to the storage account, and are not tied to any Service Principal. Every authentication method after those two can be modified to use Entra ID authentication rather than storage account-based authentication using the following parameter:
|
||||
|
||||
```hcl
|
||||
...
|
||||
use_azuread_auth = true
|
||||
...
|
||||
```
|
||||
|
||||
Using Entra ID, you can authenticate directly to the storage account or storage container using the service principal, which only requires the `Storage Blob Data Contributor` role. Without this parameter, OpenTofu will authenticate and try to obtain the Access Key for the Storage Account.
|
||||
|
||||
:::note
|
||||
The `Owner` role does not automatically grant access to the storage container through Entra ID; you need to explicitly provide a role for the storage account such as `Storage Blob Data Contributor`. However, having an `Owner` role does allow the principal to obtain the Access Key to the Storage Account.
|
||||
:::
|
||||
|
||||
:::note
|
||||
If you do not set `use_azuread_auth = true`, you *must* set the `resource_group_name`. A `resource_group_name` is not required when using Entra ID authentication.
|
||||
:::
|
||||
|
||||
***
|
||||
|
||||
### CLI Authentication
|
||||
|
||||
This example authenticates the user with the azure profile set up by the `az` command.
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "tofu-rg"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
When using a Service Principal or an Access Key - we recommend using a [Partial Configuration](../../../language/settings/backends/configuration.mdx#partial-configuration) for the credentials.
|
||||
You can disable CLI Authentication by setting `use_cli = false`.
|
||||
:::
|
||||
|
||||
***
|
||||
|
||||
### Certificate Authentication
|
||||
|
||||
This example authenticates the principal using a certificate authentication.
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "tofu-rg"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
client_certificate_path = "cert.pfx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### Basic Authentication
|
||||
|
||||
This example authenticates the principal using a basic secret.
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "tofu-rg"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
client_secret = "hunter2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We recommend using the environment variable `ARM_CLIENT_SECRET` instead of storing sensitive information in your source code.
|
||||
|
||||
***
|
||||
|
||||
### OpenID Connect Token
|
||||
|
||||
This example authenticates the principal using an OpenID Connect token for Federated Credentials.
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "tofu-rg"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
use_oidc = true
|
||||
oidc_token_file_path = "token.env"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
#### GitHub Token Request
|
||||
|
||||
If you're using GitHub Actions, the environment variables `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN` will provide you with a way to obtain the OIDC request token. OpenTofu is programmed to accept these environment variables; a workload with OpenTofu on GitHub Actions using OIDC will have this backend configuration to authenticate.
|
||||
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "tofu-rg"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
client_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
use_oidc = true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### Managed Service Identity
|
||||
|
||||
This example authenticates a managed service identity attached to the Azure VM or other compute.
|
||||
```hcl
|
||||
terraform {
|
||||
backend "azurerm" {
|
||||
resource_group_name = "tofu-rg"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
subscription_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
use_msi = true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Data Source Configuration
|
||||
|
||||
When authenticating using a Service Principal (either with a Client Certificate or a Client Secret):
|
||||
Authentication for a data source works equivalently to the remote state authentication shown above, though with slightly different syntax. For example, this is how to obtain the remote state using CLI Authentication:
|
||||
|
||||
```hcl
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "azurerm"
|
||||
config = {
|
||||
resource_group_name = "tofu-rg"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
@@ -136,104 +222,6 @@ data "terraform_remote_state" "foo" {
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
When authenticating using Managed Service Identity (MSI):
|
||||
|
||||
```hcl
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "azurerm"
|
||||
config = {
|
||||
resource_group_name = "StorageAccount-ResourceGroup"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
use_msi = true
|
||||
subscription_id = "00000000-0000-0000-0000-000000000000"
|
||||
tenant_id = "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
When authenticating using OpenID Connect (OIDC):
|
||||
|
||||
```hcl
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "azurerm"
|
||||
config = {
|
||||
resource_group_name = "StorageAccount-ResourceGroup"
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
use_oidc = true
|
||||
subscription_id = "00000000-0000-0000-0000-000000000000"
|
||||
tenant_id = "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
When authenticating using AzureAD Authentication:
|
||||
|
||||
```hcl
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "azurerm"
|
||||
config = {
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
use_azuread_auth = true
|
||||
subscription_id = "00000000-0000-0000-0000-000000000000"
|
||||
tenant_id = "00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::note
|
||||
When using AzureAD for Authentication to Storage you also need to ensure the `Storage Blob Data Owner` role is assigned.
|
||||
:::
|
||||
|
||||
***
|
||||
|
||||
When authenticating using the Access Key associated with the Storage Account:
|
||||
|
||||
```hcl
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "azurerm"
|
||||
config = {
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
# rather than defining this inline, the Access Key can also be sourced
|
||||
# from an Environment Variable - more information is available below.
|
||||
access_key = "abcdefghijklmnopqrstuvwxyz0123456789..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
When authenticating using a SAS Token associated with the Storage Account:
|
||||
|
||||
```hcl
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "azurerm"
|
||||
config = {
|
||||
storage_account_name = "tofu123abc"
|
||||
container_name = "tofu-state"
|
||||
key = "prod.terraform.tfstate"
|
||||
|
||||
# rather than defining this inline, the SAS Token can also be sourced
|
||||
# from an Environment Variable - more information is available below.
|
||||
sas_token = "abcdefghijklmnopqrstuvwxyz0123456789..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Variables
|
||||
|
||||
:::danger Warning
|
||||
@@ -248,12 +236,14 @@ The following configuration options are supported:
|
||||
|
||||
* `key` - (Required) The name of the Blob used to retrieve/store OpenTofu's State file inside the Storage Container.
|
||||
|
||||
* `environment` - (Optional) The Azure Environment which should be used. This can also be sourced from the `ARM_ENVIRONMENT` environment variable. Possible values are `public`, `china`, `german`, `stack` and `usgovernment`. Defaults to `public`.
|
||||
* `resource_group_name` - (Required when not using Entra ID auth) The name of the Resource Group in which the Storage Account exists.
|
||||
|
||||
* `endpoint` - (Optional) The Custom Endpoint for Azure Resource Manager. This can also be sourced from the `ARM_ENDPOINT` environment variable.
|
||||
* `environment` - (Optional) The Azure Cloud Configuration which should be used; set this for special compliance environments like Azure China or Azure US Government. This can also be sourced from the `ARM_ENVIRONMENT` environment variable. Possible values are `public`, `china`, and `usgovernment`. Defaults to `public`.
|
||||
|
||||
* `endpoint` - (**Deprecated in 1.1x.xx**) The Custom Endpoint for Azure Resource Manager. This can also be sourced from the `ARM_ENDPOINT` environment variable.
|
||||
|
||||
:::warning Note
|
||||
An `endpoint` should only be configured when using Azure Stack.
|
||||
An `endpoint` should only be configured when using Azure Stack. This variable has no effect on operation from OpenTofu version 1.1x.xx onward.
|
||||
:::
|
||||
|
||||
* `timeout_seconds` - (Optional) The number of seconds before a timeout is reached when attempting to initialize a client, retrieve a Blob or a Metadata from Azure. This can also be sourced from the `ARM_TIMEOUT_SECONDS` environment variable. Defaults to `300` (5 minutes). To disable the timeout, set this to `0`.
|
||||
@@ -264,15 +254,25 @@ The following configuration options are supported:
|
||||
|
||||
* `metadata_host` - (Optional) The Hostname of the Azure Metadata Service (for example `management.azure.com`), used to obtain the Cloud Environment when using a Custom Azure Environment. This can also be sourced from the `ARM_METADATA_HOSTNAME` Environment Variable.
|
||||
|
||||
:::warning Note
|
||||
We recommend `metadata_host` only be configured when using Azure Stack.
|
||||
:::
|
||||
|
||||
* `snapshot` - (Optional) Should the Blob used to store the OpenTofu Statefile be snapshotted before use? Defaults to `false`. This value can also be sourced from the `ARM_SNAPSHOT` environment variable.
|
||||
|
||||
:::note
|
||||
Rather than using snapshots, we recommend enabling versioning and soft deletion on your Azure storage container.
|
||||
:::
|
||||
|
||||
***
|
||||
|
||||
When authenticating using the Managed Service Identity (MSI) - the following fields are also supported:
|
||||
|
||||
* `resource_group_name` - (Required) The Name of the Resource Group in which the Storage Account exists.
|
||||
* `msi_endpoint` - (**Deprecated in 1.1x.xx**) The path to a custom Managed Service Identity endpoint which is automatically determined if not specified. This can also be sourced from the `ARM_MSI_ENDPOINT` environment variable.
|
||||
|
||||
* `msi_endpoint` - (Optional) The path to a custom Managed Service Identity endpoint which is automatically determined if not specified. This can also be sourced from the `ARM_MSI_ENDPOINT` environment variable.
|
||||
:::warning Note
|
||||
We recommend using the MSI_ENDPOINT environment variable instead.
|
||||
:::
|
||||
|
||||
* `subscription_id` - (Optional) The Subscription ID in which the Storage Account exists. This can also be sourced from the `ARM_SUBSCRIPTION_ID` environment variable.
|
||||
|
||||
@@ -284,6 +284,12 @@ When authenticating using the Managed Service Identity (MSI) - the following fie
|
||||
|
||||
When authenticating using a Service Principal with OpenID Connect (OIDC) - the following fields are also supported:
|
||||
|
||||
* `client_id` - (Optional) The Client ID of the Service Principal. This can also be sourced from the `ARM_CLIENT_ID` environment variable.
|
||||
|
||||
* `subscription_id` - (Optional) The Subscription ID in which the Storage Account exists. This can also be sourced from the `ARM_SUBSCRIPTION_ID` environment variable.
|
||||
|
||||
* `tenant_id` - (Optional) The Tenant ID in which the Subscription exists. This can also be sourced from the `ARM_TENANT_ID` environment variable.
|
||||
|
||||
* `oidc_request_url` - (Optional) The URL for the OIDC provider from which to request an ID token. This can also be sourced from the `ARM_OIDC_REQUEST_URL` or `ACTIONS_ID_TOKEN_REQUEST_URL` environment variables.
|
||||
|
||||
* `oidc_request_token` - (Optional) The bearer token for the request to the OIDC provider. This can also be sourced from the `ARM_OIDC_REQUEST_TOKEN` or `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variables.
|
||||
@@ -308,19 +314,24 @@ When authenticating using the Storage Account's Access Key - the following field
|
||||
|
||||
***
|
||||
|
||||
When authenticating using AzureAD Authentication - the following fields are also supported:
|
||||
When authenticating using Entra ID Authentication - the following fields are also supported:
|
||||
|
||||
* `use_azuread_auth` - (Optional) Should AzureAD Authentication be used to access the Blob Storage Account. This can also be sourced from the `ARM_USE_AZUREAD` environment variable.
|
||||
* `use_azuread_auth` - (Optional) Whether to use Entra ID Authentication to access the Storage Account or Container. This can also be sourced from the `ARM_USE_AZUREAD` environment variable.
|
||||
|
||||
:::note
|
||||
When using AzureAD for Authentication to Storage you also need to ensure the `Storage Blob Data Owner` role is assigned.
|
||||
When using Entra ID for Authentication to Storage you also need to ensure the `Storage Blob Data Contributor` role is assigned.
|
||||
:::
|
||||
|
||||
***
|
||||
|
||||
When authenticating using a Service Principal with a Client Certificate - the following fields are also supported:
|
||||
When authenticating using the command line - the following fields are also supported:
|
||||
|
||||
* `resource_group_name` - (Required) The Name of the Resource Group in which the Storage Account exists.
|
||||
* `use_cli` - (Optional) Whether to authenticate with the CLI. Defaults to `true`. This can also be sourced from the `ARM_USE_CLI` environment variable.
|
||||
|
||||
|
||||
***
|
||||
|
||||
When authenticating using a Service Principal with a Client Certificate - the following fields are also supported:
|
||||
|
||||
* `client_id` - (Optional) The Client ID of the Service Principal. This can also be sourced from the `ARM_CLIENT_ID` environment variable.
|
||||
|
||||
@@ -336,7 +347,6 @@ When authenticating using a Service Principal with a Client Certificate - the fo
|
||||
|
||||
When authenticating using a Service Principal with a Client Secret - the following fields are also supported:
|
||||
|
||||
* `resource_group_name` - (Required) The Name of the Resource Group in which the Storage Account exists.
|
||||
|
||||
* `client_id` - (Optional) The Client ID of the Service Principal. This can also be sourced from the `ARM_CLIENT_ID` environment variable.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user