This is a terraform module for initializing a terraform state backend in Azure.
By default, it creates a resource group named terraform-state
, a storage account with a unique name, and a container named "terraform-state".
A common pattern for using this is to create a folder within your terraform IaC project for setting up your environment, such as /environments/{env_name}/setup
, containing a main.tf
like:
module "state_backend" {
source = "github.com/tamu-edu/it-ae-tfmod-azure-state?ref=v0.2"
container_name = "tfstate"
location = "southcentralus"
resource_group_name = "your-project-tfstate-dev"
# storage_account_name = "LeaveBlankToAutoGen"
subscription_id = "f5358b4a-0a02-4485-8157-367fc107a27d"
tenant_id = "68f381e3-46da-47b9-ba57-6f322b8f0da1"
remove_secrets_from_state = false
}
# Note: Azure does not automatically grant access to the storage account to its creator, so this module does.
# To grant access to someone or something else (such as a service principal) you will need to implement your own role scope grant. This example has Github pipeline usage in mind. Ex:
resource "azurerm_role_assignment" "tfstate_role_assignment" {
scope = module.state_backend.container_role_access_scope
role_definition_name = "Storage Blob Data Owner"
principal_id = "<object id of entity you need to have access>"
}
output "container_name" {
value = module.state_backend.container_name
}
output "resource_group_name" {
value = module.state_backend.resource_group_name
}
output "storage_account_name" {
value = module.state_backend.storage_account_name
}
output "backend_config" {
value = module.state_backend.backend
}
To execute, first az login
with an appropriately permissioned Azure account using the Azure CLI. Once logged in, run command terraform init
within the new terraform-state
folder. Then, run terraform plan
to see what will be created. If satisfied with the results, run command terraform apply
. This will create the appropriate Azure Blob Storage for holding state files for the main project. Azure Blobs are semaphore-locked from concurrent writes automatically. The state file for this remote state terraform script will be stored on the file system. Be sure to capture the results of the output (run terraform output
to see it again) and copy it into your main Terraform stack variables. It is recommended to alter the name of the key to fit the granularity of separation of concerns that you require. By default, this will assign the role "Storage Blob Data Contributor" on the created tfstate container to the identity that runs this terraform.
Caution
The generated Azure storage account resource will contain storage account access keys to it if this feature is not disabled in Azure. Do not commit the statefile generated by this module until either the access keys are removed, rotated, or access keys disabled in Azure.
By default, this module sanitizes the tfstate file for you. Toggle the input remove_secrets_from_state
to false
to prevent this behavior.
Note
If you are using an identity that has limited access to the Azure subscription, be sure to set the value of resource_provider_registrations
to none
. If this is the case, you will also need to work with someone who has owner access to the subscription to enable provider registration for all the API's that you may need to use. You may also want to set the value of create_resource_group
to false
if the resource group has already been created for you. Additionally, if you have never done any resource provider registrations in a subscription, note that the first run of terraform plan
or terraform apply
may take quite some time as the provider will attempt to automatically do the provider registration.
Use the generated backend_config
output to help you consume this generated tfstate "azurerm" Terraform backend storage. Note that it is configured to use the Azure Active Directory with Azure CLI
method for authentication as documented here. If you need a different method, you will need to edit it per that documentation.
Your calling Terraform code could work with the output to automatically create (and manage) a standalone backend block file. In this example, the consuming Terraform code sits just above this tfstate setup folder:
resource "local_file" "backend_config" {
content = local.backend
filename = "${path.root}/../backend.tf"
}
Name | Version |
---|---|
terraform | >= 0.13 |
azurerm | =4.26.0 |
Name | Version |
---|---|
azurerm | 4.26.0 |
null | 3.2.3 |
random | 3.7.1 |
terraform | n/a |
No modules.
Name | Type |
---|---|
azurerm_resource_group.tfstate | resource |
azurerm_role_assignment.tfstate_role_assignment | resource |
azurerm_storage_account.tfstate | resource |
azurerm_storage_container.tfstate | resource |
null_resource.sanitize_state | resource |
random_string.storage_account_name | resource |
terraform_data.always_run | resource |
azurerm_client_config.current | data source |
azurerm_resource_group.tfstate | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
client_id | The client ID to use for authenticating to Azure. Terraform authentication will overwrite this. | string |
null |
no |
container_name | The name of the storage container to use for the Terraform state | string |
"terraform-state" |
no |
create_resource_group | Whether to create or to attach to an existing resource group. See resource_group_name . Defaults to true. |
bool |
true |
no |
location | The location to use for the Terraform state | string |
"centralus" |
no |
remove_secrets_from_state | Whether to sanitize tfstate of access keys automatically created on created resources. Actual, assigned keys remain untouched on created assets. | bool |
true |
no |
resource_group_name | The name of the resource group to use for the Terraform state. If create_resource_group is true, this will be the name of the created resource group. If create_resource_group is false, this module will find the existing resource group by that name. |
string |
"terraform-state" |
no |
resource_provider_registrations | Set to 'none' if using a limited user without permission to do provider registrations | string |
null |
no |
storage_account_name | The name of the storage account to use for the Terraform state. Leave blank to let Terraform manage a globally unique name to fit Azure constraints. | string |
null |
no |
subscription_id | The subscription ID to use for the Terraform state | string |
null |
no |
tenant_id | The tenant ID to use for the Terraform state | string |
null |
no |
Name | Description |
---|---|
backend_config | Will contain a block of Terraform code that can be used to consume the created backend config. |
container_id | Will output the tfstate storage container id |
container_name | Will output the tfstate storage container name |
container_role_access_scope | Complete scope string down to the tfstate storage container |
resource_group_name | Will output the name of the resource group |
storage_account_id | ID of the tfstate storage account suitable for very broad scope string building (see container_role_access_scope) |
storage_account_name | Will output the storage account name |
These output values will serve as your terraform IaC project inputs.