Terraform module which creates a Storage Account on Azure with secure defaults.
The simplest usage of this module is shown below. It requires a few parameters to passed in and already uses the recommended default configuraton values. Please note that the resource group used for the deployment will not be created by this module.
data "azurerm_resource_group" "tstate" {
name = "tstate"
}
module "terraform_state_storage_account" {
source = "ultratendency/secure-storage-account/azurerm"
version = "4.0.0"
storage_account_name = "tstate"
storage_account_resource_group_name = data.azurerm_resource_group.tstate.name
storage_account_location = "westeurope"
storage_container_name = "tstate"
key_vault_name = "tstate-vault"
key_vault_key_name = "tstate-vault-key"
key_vault_key_expiration_date = "2023-12-30T20:00:00Z"
}
A complete example looks like the following, where all inputs are configured. Please note that the following is only a descriptive example and does not follow recommended configuration values.
data "azurerm_resource_group" "tstate" {
name = "tstate"
}
module "terraform_state_storage_account" {
source = "ultratendency/secure-storage-account/azurerm"
version = "4.0.0"
storage_account_name = "tstate"
storage_account_resource_group_name = data.azurerm_resource_group.tstate.name
storage_account_location = "westeurope"
storage_account_account_tier = "Premium"
storage_account_account_replication_type = "GRS"
storage_account_min_tls_version = "TLS1_1"
storage_account_https_traffic_only_enabled = false
storage_account_queue_encryption_key_type = "Account"
storage_account_table_encryption_key_type = "Account"
storage_account_infrastructure_encryption_enabled = true
storage_account_allow_nested_items_to_be_public = true
storage_account_shared_access_key_enabled = true
storage_account_queue_properties_logging_delete = false
storage_account_queue_properties_logging_read = false
storage_account_queue_properties_logging_write = false
storage_account_queue_properties_logging_version = "1.0"
storage_account_queue_properties_logging_retention_policy_days = 20
storage_account_queue_properties_hour_metrics_include_apis = false
storage_account_queue_properties_hour_metrics_version = "1.0"
storage_account_queue_properties_hour_metrics_retention_policy_days = 20
storage_account_queue_properties_minute_metrics_include_apis = false
storage_account_queue_properties_minute_metrics_version = "1.0"
storage_account_queue_properties_minute_metrics_retention_policy_days = 20
storage_account_blob_properties_change_feed_enabled = false
storage_account_blob_properties_change_feed_retention_in_days = 14
storage_account_blob_properties_versioning_enabled = false
storage_account_blob_properties_container_delete_retention_policy_days = 14
storage_account_blob_properties_delete_retention_policy_days = 14
storage_container_name = "tstate"
storage_container_container_access_type = "blob"
key_vault_name = "tstate-vault"
key_vault_sku_name = "premium"
key_vault_enable_rbac_authorization = false
key_vault_purge_protection_enabled = false
key_vault_soft_delete_retention_days = 7
key_vault_key_name = "tstate-vault-key"
key_vault_key_key_type = "EC"
key_vault_key_key_size = "1024"
key_vault_key_key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify"]
key_vault_key_expiration_date = "2023-12-30T20:00:00Z"
}
When leaving the variable storage_account_shared_access_key_enabled
with the default value
false
shared access keys are turned off on the storage account. This needs some configuration on
the storage account itself, as outlined below
The user principal running Terraform needs to have the Storage Blob Data Contributor
role
assigned. Please note that having the Owner
or Contributor
role assigned is not sufficient as
the user prinicipal needs one of the Storage Blob Data xxx
roles to access data within the
storage blob.
Permissions can also directly assigned via the storage_account_role_assignments
variable (or the respective
key_vault_role_assignments
variable for the Key Vault), similar to the following example
...
storage_account_role_assignments = {
user_1 = {
principal_id = "123"
role_definition_name = "Storage Blob Data Contributor"
}
user_2 = {
principal_id = "456"
role_definition_name = "Storage Blob Data Contributor"
}
}
...
With the use of storage_account_shared_access_key_enabled
the authentication method for the
storage container will be switched to Microsoft Entra user account
. Ensure that this change
happened.
The recommended usage for the storage account as a Terraform backend is to use the authentication
method Service Principal or User Assigned Managed Identity via OIDC (Workload identity federation)
with Azure AD
as the storage account authentication type. To configure both, the Terraform
backend should contain the following configuration values
...
use_azuread_auth = true,
use_oidc = true,
...
A complete Terraform backend configuration would look like the following
terraform {
backend "azurerm" {
resource_group_name = "tstate"
storage_account_name = "tstate"
container_name = "tstate"
key = "terraform.tfstate"
use_azuread_auth = true
use_oidc = true
}
}
For a detailed look into available options, see the available configuration options.
To let the Terraform provider access the storage account without a shared access key, the following configuration needs to be set on the provider
...
storage_use_azuread = true
...
A complete Terraform provider configuration would look like the following
provider "azurerm" {
use_oidc = true
storage_use_azuread = true
features {}
}
Name | Version |
---|---|
terraform | >= 1.0 |
azurerm | >= 4.9.0 |
Name | Version |
---|---|
azurerm | >= 4.9.0 |
Name | Type |
---|---|
azurerm_key_vault.this | resource |
azurerm_key_vault_key.this | resource |
azurerm_role_assignment.this_key_vault | resource |
azurerm_role_assignment.this_storage_account | resource |
azurerm_storage_account.this | resource |
azurerm_storage_account_queue_properties.this | resource |
azurerm_storage_container.this | resource |
azurerm_client_config.current | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
key_vault_enable_rbac_authorization | (optional) Indicates whether the key vault uses Role Based Access Control (RBAC) for authorization of data actions | bool |
true |
no |
key_vault_key_expiration_date | Expiration UTC datetime of the key vault key | string |
n/a | yes |
key_vault_key_key_opts | (optional) A list of JSON web key operations | list(string) |
[ |
no |
key_vault_key_key_size | (optional) The size of the RSA key to create in bytes | number |
4096 |
no |
key_vault_key_key_type | (optional) The key type to use for this key vault key | string |
"RSA" |
no |
key_vault_key_name | The name of the key vault key | string |
n/a | yes |
key_vault_name | The name of the key vault | string |
n/a | yes |
key_vault_purge_protection_enabled | (optional) Indicates whether purge protection is enabled for the key vault | bool |
true |
no |
key_vault_role_assignments | (optional) A map of role assignments to be created for the key vault | map(object({ |
{} |
no |
key_vault_sku_name | (optiona) The name of the SKU used for the key vault | string |
"standard" |
no |
key_vault_soft_delete_retention_days | (optional) The number of days that items should be retained for once soft-deleted | number |
90 |
no |
storage_account_account_replication_type | (optional) The type of replication to use for this storage account | string |
"LRS" |
no |
storage_account_account_tier | (optional) The tier to use for this storage account | string |
"Standard" |
no |
storage_account_allow_nested_items_to_be_public | (optional) Allow or disallow nested items within this storage account to opt into being public | bool |
false |
no |
storage_account_blob_properties_change_feed_enabled | (optional) Indicates whether the blob service properties for change feeds are enabled | bool |
true |
no |
storage_account_blob_properties_change_feed_retention_in_days | (optional) The number of days that change feed eents will be retained | number |
7 |
no |
storage_account_blob_properties_container_delete_retention_policy_days | (optional) The number of days that the container should be retained | number |
7 |
no |
storage_account_blob_properties_delete_retention_policy_days | (optional) The number of days that the blob should be retained | number |
7 |
no |
storage_account_blob_properties_versioning_enabled | (optional) Indicates whether versioning is enabled | bool |
true |
no |
storage_account_https_traffic_only_enabled | (optional) Boolean flag which forces HTTPS if enabled | bool |
true |
no |
storage_account_infrastructure_encryption_enabled | (optional) Boolean flag which forces infrastructure encryption | bool |
false |
no |
storage_account_location | The location of the storage account | string |
n/a | yes |
storage_account_min_tls_version | (optional) The minimum supported TLS version for this storage account | string |
"TLS1_2" |
no |
storage_account_name | The name of the storage sccount | string |
n/a | yes |
storage_account_queue_encryption_key_type | (optional) The encryption of the queue service | string |
"Service" |
no |
storage_account_queue_properties_hour_metrics_include_apis | (optional) Indicates whether metrics should generate summary statistics for called API operations | bool |
true |
no |
storage_account_queue_properties_hour_metrics_retention_policy_days | (optional) The number of days that logs will be retained | number |
10 |
no |
storage_account_queue_properties_hour_metrics_version | (optional) The version of the storage analytics to configure | string |
"1.0" |
no |
storage_account_queue_properties_logging_delete | (optional) Indicates whether all delete requests should be logged | bool |
true |
no |
storage_account_queue_properties_logging_read | (optional) Indicates whether all read requests should be logged | bool |
true |
no |
storage_account_queue_properties_logging_retention_policy_days | (optional) The number of days that logs will be retained | number |
10 |
no |
storage_account_queue_properties_logging_version | (optional) The version of storage analytics to configure | string |
"1.0" |
no |
storage_account_queue_properties_logging_write | (optional) Indicates whether all write requests should be logged | bool |
true |
no |
storage_account_queue_properties_minute_metrics_include_apis | (optional) Indicates whether metrics should generate summary statistics for called API operations | bool |
true |
no |
storage_account_queue_properties_minute_metrics_retention_policy_days | (optional) The number of days that logs will be retained | number |
10 |
no |
storage_account_queue_properties_minute_metrics_version | (optional) The version of storage analytics to configure | string |
"1.0" |
no |
storage_account_resource_group_name | The name of the resource group to use | string |
n/a | yes |
storage_account_role_assignments | (optional) A map of role assignments to be created for the storage account | map(object({ |
{} |
no |
storage_account_shared_access_key_enabled | (optional) Indicates whether the storage account permits requests to be authorized with the account access key | bool |
false |
no |
storage_account_table_encryption_key_type | (optional) The encryption type of the table service | string |
"Service" |
no |
storage_container_container_access_type | (optional) The access level configured for the container | string |
"private" |
no |
storage_container_name | The name of the container which should be created within the storage account | string |
n/a | yes |
tags | General variables | map(string) |
{} |
no |
Name | Description |
---|---|
azurerm_key_vault_id | The ID of the key vault |
azurerm_key_vault_key_id | The ID of the key vault key |
azurerm_storage_account_id | The ID of the storage account |
azurerm_storage_container_id | The ID of the storage container |
An simple example of the default configuration can be found below:
provider "azurerm" {
features {}
}
data "azurerm_resource_group" "tstate" {
name = "tstate"
}
module "terraform_state_storage_account" {
source = "ultratendency/secure-storage-account/azurerm"
version = "4.0.0"
storage_account_name = "tstate"
storage_account_resource_group_name = data.azurerm_resource_group.tstate.name
storage_account_location = "westeurope"
storage_container_name = "tstate"
key_vault_name = "tstate-vault"
key_vault_key_name = "tstate-vault-key"
key_vault_key_expiration_date = "2023-12-30T20:00:00Z"
}
A more complex example can be found below:
provider "azurerm" {
features {}
}
data "azurerm_resource_group" "tstate" {
name = "tstate"
}
module "terraform_state_storage_account" {
source = "ultratendency/secure-storage-account/azurerm"
version = "4.0.0"
storage_account_name = "tstate"
storage_account_resource_group_name = data.azurerm_resource_group.tstate.name
storage_account_location = "westeurope"
storage_account_account_tier = "Premium"
storage_account_account_replication_type = "GRS"
storage_account_min_tls_version = "TLS1_1"
storage_account_https_traffic_only_enabled = false
storage_account_queue_encryption_key_type = "Account"
storage_account_table_encryption_key_type = "Account"
storage_account_infrastructure_encryption_enabled = true
storage_account_allow_nested_items_to_be_public = true
storage_account_shared_access_key_enabled = true
storage_account_queue_properties_logging_delete = false
storage_account_queue_properties_logging_read = false
storage_account_queue_properties_logging_write = false
storage_account_queue_properties_logging_version = "1.0"
storage_account_queue_properties_logging_retention_policy_days = 20
storage_account_queue_properties_hour_metrics_include_apis = false
storage_account_queue_properties_hour_metrics_version = "1.0"
storage_account_queue_properties_hour_metrics_retention_policy_days = 20
storage_account_queue_properties_minute_metrics_include_apis = false
storage_account_queue_properties_minute_metrics_version = "1.0"
storage_account_queue_properties_minute_metrics_retention_policy_days = 20
storage_account_blob_properties_change_feed_enabled = false
storage_account_blob_properties_change_feed_retention_in_days = 14
storage_account_blob_properties_versioning_enabled = false
storage_account_blob_properties_container_delete_retention_policy_days = 14
storage_account_blob_properties_delete_retention_policy_days = 14
storage_container_name = "tstate"
storage_container_container_access_type = "blob"
key_vault_name = "tstate-vault"
key_vault_sku_name = "premium"
key_vault_enable_rbac_authorization = false
key_vault_purge_protection_enabled = false
key_vault_soft_delete_retention_days = 7
key_vault_key_name = "tstate-vault-key"
key_vault_key_key_type = "EC"
key_vault_key_key_size = "1024"
key_vault_key_key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify"]
key_vault_key_expiration_date = "2023-12-30T20:00:00Z"
}