Add support for Azure Blob Storage backup policies and instances
This commit is contained in:
29
README.md
29
README.md
@@ -21,6 +21,22 @@ This module creates an Azure Data Protection Backup Vault with the specified nam
|
|||||||
|
|
||||||
**SnapshotStore** is a legacy/compatibility datastore value that appears in provider schemas and older patterns. For newer Azure Backup workflows, Microsoft guidance and examples more often emphasize `OperationalStore` and `VaultStore`, with `OperationalStore` generally preferred over snapshot-style behavior for active operational protection.
|
**SnapshotStore** is a legacy/compatibility datastore value that appears in provider schemas and older patterns. For newer Azure Backup workflows, Microsoft guidance and examples more often emphasize `OperationalStore` and `VaultStore`, with `OperationalStore` generally preferred over snapshot-style behavior for active operational protection.
|
||||||
|
|
||||||
|
## Protecting Resources
|
||||||
|
|
||||||
|
This module can protect multiple resource types. Azure Blob Storage is the first supported resource type, and additional types will be added over time.
|
||||||
|
|
||||||
|
### Azure Blob Storage
|
||||||
|
|
||||||
|
Use `blob_backup_policies` to define one or more Blob backup policy profiles, and `protected_blob_storage_accounts` to map each storage account to a selected policy via `backup_policy_key`.
|
||||||
|
|
||||||
|
For each protected storage account, you can optionally set:
|
||||||
|
|
||||||
|
- `container_names` to protect specific containers (when omitted/null, all containers are included)
|
||||||
|
- `backup_instance_location` to override backup instance location
|
||||||
|
- `backup_instance_name` to override backup instance naming
|
||||||
|
|
||||||
|
Note: the `Storage Account Backup Contributor` role assignment for the vault identity should be configured by the caller (for example, using a separate IAM module).
|
||||||
|
|
||||||
## Module Inputs, Outputs, and Examples
|
## Module Inputs, Outputs, and Examples
|
||||||
|
|
||||||
### Variables
|
### Variables
|
||||||
@@ -39,6 +55,17 @@ This module creates an Azure Data Protection Backup Vault with the specified nam
|
|||||||
- `type`: Identity type. Allowed values: `SystemAssigned`, `UserAssigned`, `SystemAssigned, UserAssigned`.
|
- `type`: Identity type. Allowed values: `SystemAssigned`, `UserAssigned`, `SystemAssigned, UserAssigned`.
|
||||||
- `identity_ids`: Optional list of user-assigned identity IDs (required when `type = "UserAssigned"`).
|
- `identity_ids`: Optional list of user-assigned identity IDs (required when `type = "UserAssigned"`).
|
||||||
- `tags`: A map of tags to apply to the backup vault.
|
- `tags`: A map of tags to apply to the backup vault.
|
||||||
|
- `protected_blob_storage_accounts`: Map of Blob Storage accounts to protect. Each object supports:
|
||||||
|
- `id`: Storage account resource ID (required).
|
||||||
|
- `container_names`: Optional container filter list (null/omitted means all containers).
|
||||||
|
- `backup_instance_location`: Optional override for backup instance location.
|
||||||
|
- `backup_instance_name`: Optional override for backup instance name.
|
||||||
|
- `backup_policy_key`: Optional key selecting an entry from `blob_backup_policies`.
|
||||||
|
- `blob_backup_policies`: Map of Blob backup policy definitions. Each object supports:
|
||||||
|
- `name`: Optional policy name.
|
||||||
|
- `backup_repeating_time_intervals`: Optional schedule list in ISO 8601 repeating interval format.
|
||||||
|
- `operational_default_retention_duration`: Optional operational retention duration (ISO 8601 duration).
|
||||||
|
- `vault_default_retention_duration`: Optional vaulted retention duration (ISO 8601 duration).
|
||||||
|
|
||||||
### Outputs
|
### Outputs
|
||||||
|
|
||||||
@@ -46,6 +73,8 @@ This module creates an Azure Data Protection Backup Vault with the specified nam
|
|||||||
- `backup_vault_name`: The name of the created backup vault.
|
- `backup_vault_name`: The name of the created backup vault.
|
||||||
- `backup_vault_identity_principal_id`: Principal ID of the assigned managed identity, if configured.
|
- `backup_vault_identity_principal_id`: Principal ID of the assigned managed identity, if configured.
|
||||||
- `backup_vault_identity_tenant_id`: Tenant ID of the assigned managed identity, if configured.
|
- `backup_vault_identity_tenant_id`: Tenant ID of the assigned managed identity, if configured.
|
||||||
|
- `backup_policy_blob_storage_ids`: Map of Blob backup policy IDs keyed by policy key.
|
||||||
|
- `backup_instance_blob_storage_ids`: Map of Blob backup instance IDs keyed by protected account key.
|
||||||
|
|
||||||
### Example Usage
|
### Example Usage
|
||||||
|
|
||||||
|
|||||||
46
main.tf
46
main.tf
@@ -7,6 +7,29 @@ locals {
|
|||||||
var.name :
|
var.name :
|
||||||
"${coalesce(var.base_name, "")}${substr(md5("${data.azurerm_client_config.current.subscription_id}/${var.rg_name}/${coalesce(var.base_name, "")}"), 0, 6)}"
|
"${coalesce(var.base_name, "")}${substr(md5("${data.azurerm_client_config.current.subscription_id}/${var.rg_name}/${coalesce(var.base_name, "")}"), 0, 6)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
blob_storage_accounts = var.protected_blob_storage_accounts
|
||||||
|
blob_backup_enabled = length(local.blob_storage_accounts) > 0
|
||||||
|
|
||||||
|
default_backup_policies = {
|
||||||
|
default = {
|
||||||
|
name = "${local.backup_vault_name}-blob-policy"
|
||||||
|
backup_repeating_time_intervals = ["R/2026-01-01T01:00:00+00:00/P1D"]
|
||||||
|
operational_default_retention_duration = "P30D"
|
||||||
|
vault_default_retention_duration = "P30D"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blob_backup_policies = length(var.blob_backup_policies) > 0 ? {
|
||||||
|
for key, policy in var.blob_backup_policies : key => {
|
||||||
|
name = coalesce(try(policy.name, null), "${local.backup_vault_name}-${key}-blob-policy")
|
||||||
|
backup_repeating_time_intervals = coalesce(try(policy.backup_repeating_time_intervals, null), local.default_backup_policies.default.backup_repeating_time_intervals)
|
||||||
|
operational_default_retention_duration = coalesce(try(policy.operational_default_retention_duration, null), local.default_backup_policies.default.operational_default_retention_duration)
|
||||||
|
vault_default_retention_duration = coalesce(try(policy.vault_default_retention_duration, null), local.default_backup_policies.default.vault_default_retention_duration)
|
||||||
|
}
|
||||||
|
} : local.default_backup_policies
|
||||||
|
|
||||||
|
default_backup_policy_key = contains(keys(local.blob_backup_policies), "default") ? "default" : sort(keys(local.blob_backup_policies))[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "azurerm_data_protection_backup_vault" "this" {
|
resource "azurerm_data_protection_backup_vault" "this" {
|
||||||
@@ -32,3 +55,26 @@ resource "azurerm_data_protection_backup_vault" "this" {
|
|||||||
|
|
||||||
tags = var.tags
|
tags = var.tags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "azurerm_data_protection_backup_policy_blob_storage" "this" {
|
||||||
|
for_each = local.blob_backup_enabled ? local.blob_backup_policies : {}
|
||||||
|
|
||||||
|
name = each.value.name
|
||||||
|
vault_id = azurerm_data_protection_backup_vault.this.id
|
||||||
|
|
||||||
|
backup_repeating_time_intervals = each.value.backup_repeating_time_intervals
|
||||||
|
operational_default_retention_duration = each.value.operational_default_retention_duration
|
||||||
|
vault_default_retention_duration = each.value.vault_default_retention_duration
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "azurerm_data_protection_backup_instance_blob_storage" "this" {
|
||||||
|
for_each = local.blob_storage_accounts
|
||||||
|
|
||||||
|
name = coalesce(try(each.value.backup_instance_name, null), "${local.backup_vault_name}-${each.key}-blob-instance")
|
||||||
|
vault_id = azurerm_data_protection_backup_vault.this.id
|
||||||
|
location = coalesce(try(each.value.backup_instance_location, null), var.location)
|
||||||
|
storage_account_id = each.value.id
|
||||||
|
backup_policy_id = azurerm_data_protection_backup_policy_blob_storage.this[coalesce(try(each.value.backup_policy_key, null), local.default_backup_policy_key)].id
|
||||||
|
|
||||||
|
storage_account_container_names = try(each.value.container_names, null)
|
||||||
|
}
|
||||||
|
|||||||
14
outputs.tf
14
outputs.tf
@@ -13,3 +13,17 @@ output "backup_vault_identity_principal_id" {
|
|||||||
output "backup_vault_identity_tenant_id" {
|
output "backup_vault_identity_tenant_id" {
|
||||||
value = try(azurerm_data_protection_backup_vault.this.identity[0].tenant_id, null)
|
value = try(azurerm_data_protection_backup_vault.this.identity[0].tenant_id, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "backup_policy_blob_storage_ids" {
|
||||||
|
value = {
|
||||||
|
for key, policy in azurerm_data_protection_backup_policy_blob_storage.this :
|
||||||
|
key => policy.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output "backup_instance_blob_storage_ids" {
|
||||||
|
value = {
|
||||||
|
for key, instance in azurerm_data_protection_backup_instance_blob_storage.this :
|
||||||
|
key => instance.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
45
variables.tf
45
variables.tf
@@ -117,3 +117,48 @@ variable "tags" {
|
|||||||
type = map(string)
|
type = map(string)
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "protected_blob_storage_accounts" {
|
||||||
|
type = map(object({
|
||||||
|
id = string
|
||||||
|
container_names = optional(list(string))
|
||||||
|
backup_instance_location = optional(string)
|
||||||
|
backup_instance_name = optional(string)
|
||||||
|
backup_policy_key = optional(string)
|
||||||
|
}))
|
||||||
|
default = {}
|
||||||
|
|
||||||
|
validation {
|
||||||
|
condition = (
|
||||||
|
length(var.protected_blob_storage_accounts) == 0 ||
|
||||||
|
(
|
||||||
|
var.identity != null &&
|
||||||
|
contains([
|
||||||
|
"SystemAssigned",
|
||||||
|
"SystemAssigned, UserAssigned",
|
||||||
|
], var.identity.type)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
error_message = "When protected_blob_storage_accounts is set, identity.type must include SystemAssigned."
|
||||||
|
}
|
||||||
|
|
||||||
|
validation {
|
||||||
|
condition = alltrue([
|
||||||
|
for sa in values(var.protected_blob_storage_accounts) : (
|
||||||
|
try(sa.backup_policy_key, null) == null ||
|
||||||
|
contains(keys(var.blob_backup_policies), sa.backup_policy_key)
|
||||||
|
)
|
||||||
|
])
|
||||||
|
error_message = "Each protected_blob_storage_accounts[*].backup_policy_key must exist in blob_backup_policies."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "blob_backup_policies" {
|
||||||
|
type = map(object({
|
||||||
|
name = optional(string)
|
||||||
|
backup_repeating_time_intervals = optional(list(string))
|
||||||
|
operational_default_retention_duration = optional(string)
|
||||||
|
vault_default_retention_duration = optional(string)
|
||||||
|
}))
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user