diff --git a/modules/azure-sa-backup/.terraform-docs.yml b/modules/azure-sa-backup/.terraform-docs.yml new file mode 100644 index 000000000..49be8b854 --- /dev/null +++ b/modules/azure-sa-backup/.terraform-docs.yml @@ -0,0 +1,48 @@ +formatter: "markdown" # this is required + +version: "" + +header-from: docs/header.md +footer-from: docs/footer.md + +recursive: + enabled: false + path: modules + include-main: true + +sections: + hide: [] + show: [] + +content: "" + +output: + file: "README.md" + mode: inject + template: |- + + {{ .Content }} + + +output-values: + enabled: false + from: "" + +sort: + enabled: true + by: name + +settings: + anchor: true + color: true + default: true + description: false + escape: true + hide-empty: false + html: true + indent: 2 + lockfile: true + read-comments: true + required: true + sensitive: true + type: true diff --git a/modules/azure-sa-backup/README.md b/modules/azure-sa-backup/README.md index 27ca69088..198ba81ed 100644 --- a/modules/azure-sa-backup/README.md +++ b/modules/azure-sa-backup/README.md @@ -1,3 +1,93 @@ + +# Azure Storage Account backup Terraform module (`azure-sa-backup`) + +## Overview + +This module configures **Azure Backup** for an existing **storage account**, in two optional paths: + +- **Azure Files**: Recovery Services vault, registration of the storage account as a backup container, a **single file share backup policy**, and **one protected file share**. + + > ⚠️ **Known limitation**: Only a single value is supported in `backup_share.source_file_share_name`. Providing multiple entries will result in a validation error until multi-share support is implemented. +- **Blobs (Data Protection)**: Backup vault, **blob backup policy**, optional **managed identity**, **role assignment** on the storage account for the vault identity, and a **blob backup instance**. + + > ⚠️ **Known caveat**: Always set `backup_blob.identity_type` (for example, `SystemAssigned`) when enabling blob backup. The role assignment count uses `can(var.backup_blob.identity_type)`, which can evaluate to `true` even when the value is `null`; in that case plan/apply can fail when resolving `identity[0]`. + +You can enable **only shares**, **only blobs**, or **both**. The module reads an existing **resource group** (`backup_resource_group_name`) for location and optional tag merge; it does **not** create that resource group or the storage account. + +## Key features + +- **Tags**: `tags` plus optional merge from the backup resource group when `tags_from_rg = true` (default `false`). +- **Conditional resources**: `backup_share` and `backup_blob` are each optional (`null` disables that path). +- **Outputs**: vault and instance IDs for the blob path; Recovery Services vault ID and a map of protected file share item IDs for the share path (see `outputs.tf`). +- **Known limitation (file shares)**: Only one value in `backup_share.source_file_share_name` is supported; multiple entries will result in a validation error. +- **Known caveat (blobs)**: Omitting `backup_blob.identity_type` is unsafe with the current role assignment logic; set it explicitly for blob backup. + +## Prerequisites + +- Existing **resource group** for backup resources (`backup_resource_group_name`). +- Existing **storage account** and, for file share backup, a single existing **file share** name in `backup_share.source_file_share_name` (one element only). +- Appropriate **permissions** for Terraform in the subscription (Backup Contributor / relevant roles as required by your org). + +## Basic usage + +Provide `backup_resource_group_name`, `storage_account_id`, and at least one of `backup_share` or `backup_blob`. See the **Inputs** table for the full object shapes. + +### Example (file share backup only) + +```hcl +module "storage_backup" { + source = "git::https://github.com/prefapp/tfm.git//modules/azure-sa-backup?ref=" + + backup_resource_group_name = "my-backup-rg" + storage_account_id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sa-rg/providers/Microsoft.Storage/storageAccounts/mystorage" + + tags_from_rg = false + tags = { + environment = "dev" + } + + backup_share = { + policy_name = "daily-backup-policy" + recovery_services_vault_name = "my-rsvault" + sku = "Standard" + source_file_share_name = ["myshare"] + timezone = "UTC" + backup = { + frequency = "Daily" + time = "02:00" + } + retention_daily = { + count = 7 + } + } + + backup_blob = null + lifecycle_policy_rule = null +} +``` + +## File structure + +``` +. +├── CHANGELOG.md +├── blobs.tf +├── locals.tf +├── main.tf +├── outputs.tf +├── shares.tf +├── variables.tf +├── versions.tf +├── docs +│ ├── footer.md +│ └── header.md +├── _examples +│ ├── basic +│ └── comprehensive +├── README.md +└── .terraform-docs.yml +``` + ## Requirements | Name | Version | @@ -9,7 +99,11 @@ | Name | Version | |------|---------| -| [azurerm](#provider\_azurerm) | ~> 4.6.0 | +| [azurerm](#provider\_azurerm) | 4.6.0 | + +## Modules + +No modules. ## Resources @@ -30,92 +124,43 @@ | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [backup\_blob](#input\_backup\_blob) | Specifies the backup configuration for the storage blob |
object({
vault_name = string
datastore_type = string
redundancy = string
identity_type = optional(string)
role_assignment = string
instance_blob_name = string
storage_account_container_names = optional(list(string))
policy = object({
name = string
backup_repeating_time_intervals = optional(list(string))
operational_default_retention_duration = optional(string)
retention_rule = optional(list(object({
name = string
duration = string
criteria = object({
absolute_criteria = optional(string)
days_of_month = optional(list(number))
days_of_week = optional(list(string))
months_of_year = optional(list(string))
scheduled_backup_times = optional(list(string))
weeks_of_month = optional(list(string))
})
life_cycle = object({
data_store_type = string
duration = string
})
priority = number
})))
time_zone = optional(string)
vault_default_retention_duration = optional(string)
retention_duration = optional(string)
})
})
| `null` | no | -| [backup\_resource\_group\_name](#input\_backup\_resource\_group\_name) | The name for the resource group for the backups | `string` | n/a | yes | +| [backup\_resource\_group\_name](#input\_backup\_resource\_group\_name) | Name of the existing resource group where backup vaults and policies are created (also used for the data source and optional tag merge). | `string` | n/a | yes | | [backup\_share](#input\_backup\_share) | Specifies the backup configuration for the storage share |
object({
policy_name = string
recovery_services_vault_name = string
sku = string
soft_delete_enabled = optional(bool)
storage_mode_type = optional(string, "GeoRedundant")
cross_region_restore_enabled = optional(bool)
source_file_share_name = list(string)
identity = optional(object({
type = optional(string, "SystemAssigned")
identity_ids = optional(list(string), [])
}))
encryption = optional(object({
key_id = optional(string, null)
infrastructure_encryption_enabled = optional(bool, false)
user_assigned_identity_id = optional(string, null)
use_system_assigned_identity = optional(bool, false)
}))
timezone = optional(string)
backup = object({
frequency = string
time = string
})
retention_daily = object({
count = number
})
retention_weekly = optional(object({
count = number
weekdays = optional(list(string), ["Sunday"])
}))
retention_monthly = optional(object({
count = number
weekdays = optional(list(string), ["Sunday"])
weeks = optional(list(string), ["First"])
days = optional(list(number))
}))
retention_yearly = optional(object({
count = number
months = optional(list(string), ["January"])
weekdays = optional(list(string), ["Sunday"])
weeks = optional(list(string), ["First"])
days = optional(list(number))
}))
})
| `null` | no | -| [lifecycle\_policy\_rule](#input\_lifecycle\_policy\_rule) | n/a |
list(object({
name = string
enabled = bool
filters = object({
prefix_match = list(string)
blob_types = list(string)
})
actions = object({
base_blob = object({ delete_after_days_since_creation_greater_than = number })
snapshot = object({ delete_after_days_since_creation_greater_than = number })
version = object({ delete_after_days_since_creation = number })
})
}))
| `null` | no | -| [storage\_account\_id](#input\_storage\_account\_id) | The ID of the storage account | `string` | n/a | yes | +| [lifecycle\_policy\_rule](#input\_lifecycle\_policy\_rule) | DEPRECATED: Currently not used by any resource. Setting this variable has no effect. |
list(object({
name = string
enabled = bool
filters = object({
prefix_match = list(string)
blob_types = list(string)
})
actions = object({
base_blob = object({ delete_after_days_since_creation_greater_than = number })
snapshot = object({ delete_after_days_since_creation_greater_than = number })
version = object({ delete_after_days_since_creation = number })
})
}))
| `null` | no | +| [storage\_account\_id](#input\_storage\_account\_id) | Full Azure resource ID of the storage account to protect (file shares and/or blob backup). | `string` | n/a | yes | | [tags](#input\_tags) | Tags to apply to resources | `map(string)` | `{}` | no | -| [tags\_from\_rg - +| [tags\_from\_rg](#input\_tags\_from\_rg) | Use resource group tags as base for module tags | `bool` | `false` | no | ## Outputs -No outputs. - -## Example - -```yaml - values: - tags_from_rg: true - # General values - backup_resource_group_name: "backup-test-rg" - storage_account_id: "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx" # can use refs ${{tfworkspace:claim-name:outputs.id}} - - # Backup share values - backup_share: - policy_name: "daily-backup-policy" - recovery_services_vault_name: "test-vault" - sku: "Standard" - soft_delete_enabled: true - storage_mode_type: "GeoRedundant" - cross_region_restore_enabled: true - source_file_share_name: - - "datadir" - identity: - type: "SystemAssigned" - timezone: "UTC" - backup: - frequency: "Daily" - time: "02:00" - retention_daily: - count: 7 - retention_weekly: - count: 4 - weekdays: - - "Sunday" - retention_monthly: - count: 12 - weekdays: - - "Sunday" - weeks: - - "First" - retention_yearly: - count: 5 - weekdays: - - "Sunday" - weeks: - - "First" - months: - - "January" - - # Backup blob values - backup_blob: - vault_name: "test-vault" - datastore_type: "AzureBlob" - redundancy: "GeoRedundant" - identity_type: "SystemAssigned" - instance_blob_name: "datadir" - storage_account_container_names: - - "blob1" - - "blob2" - role_assignment: "StorageBlobDataContributor" - policy: - name: "daily-blob-backup-policy" - vault_id: "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.RecoveryServices/vaults/test-vault" - backup_repeating_time_intervals: - - "R/2023-01-01T02:00:00Z/P1D" - operational_default_retention_duration: "P30D" - retention_rule: - - name: "daily-retention" - duration: "P30D" - criteria: - days_of_week: - - "Sunday" - life_cycle: - data_store_type: "VaultStore" - duration: "P30D" - priority: 1 - time_zone: "UTC" - vault_default_retention_duration: "P30D" - retention_duration: "P30D" -``` +| Name | Description | +|------|-------------| +| [blob\_backup\_instance\_id](#output\_blob\_backup\_instance\_id) | Resource ID of the blob backup instance; null if `backup_blob` is not configured. | +| [blob\_backup\_policy\_id](#output\_blob\_backup\_policy\_id) | Resource ID of the blob backup policy; null if `backup_blob` is not configured. | +| [blob\_backup\_role\_assignment\_id](#output\_blob\_backup\_role\_assignment\_id) | Role assignment ID granting the backup vault access to the storage account; null if `backup_blob` is not configured or no identity is defined. | +| [blob\_backup\_vault\_principal\_id](#output\_blob\_backup\_vault\_principal\_id) | Principal ID of the backup vault managed identity; null if `backup_blob` is not configured or no identity is defined. | +| [blob\_data\_protection\_vault\_id](#output\_blob\_data\_protection\_vault\_id) | Resource ID of the Data Protection backup vault for blob backup; null if `backup_blob` is not configured. | +| [file\_share\_backup\_policy\_id](#output\_file\_share\_backup\_policy\_id) | Resource ID of the file share backup policy; null if `backup_share` is not configured. | +| [file\_share\_protected\_item\_ids](#output\_file\_share\_protected\_item\_ids) | Map containing the protected item ID for the configured file share (only one supported); empty if `backup_share` is not configured. | +| [file\_share\_recovery\_services\_vault\_id](#output\_file\_share\_recovery\_services\_vault\_id) | Resource ID of the Recovery Services vault for file share backup; null if `backup_share` is not configured. | + +## Examples + +For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples): + +- [basic](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples/basic) — Azure Files backup via Recovery Services vault (`backup_share`); set RG, storage account ID, vault/policy/share names (see folder README). +- [comprehensive](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples/comprehensive) — Reference YAML illustrating `backup_share`, `backup_blob`, and tags (documentation-oriented; see folder README). + +## External Resources + +Terraform resource docs use **4.6.0** as a baseline aligned with the `azurerm` constraint in `versions.tf` (`~> 4.6.0`). + +- **Azure Backup**: [https://learn.microsoft.com/azure/backup/](https://learn.microsoft.com/azure/backup/) +- **azurerm\_recovery\_services\_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/recovery_services_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/recovery_services_vault) +- **azurerm\_data\_protection\_backup\_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/data_protection_backup_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/data_protection_backup_vault) +- **Terraform AzureRM provider**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0](https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0) + +## Support + +For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues). + diff --git a/modules/azure-sa-backup/_examples/basic/README.md b/modules/azure-sa-backup/_examples/basic/README.md new file mode 100644 index 000000000..068f69bd5 --- /dev/null +++ b/modules/azure-sa-backup/_examples/basic/README.md @@ -0,0 +1,20 @@ +# Basic example + +Configures **Azure Files** backup only (`backup_share`). Replace: + +- `backup_resource_group_name` — existing resource group for the Recovery Services vault. +- `storage_account_id` — full ID of the storage account to back up. +- Vault name, policy name, and `source_file_share_name` (share must exist). + +`backup_blob` is disabled (`null`). + +## Usage + +```bash +terraform init +terraform plan +``` + +## Configuration + +See [`main.tf`](./main.tf). diff --git a/modules/azure-sa-backup/_examples/basic/main.tf b/modules/azure-sa-backup/_examples/basic/main.tf new file mode 100644 index 000000000..78897395b --- /dev/null +++ b/modules/azure-sa-backup/_examples/basic/main.tf @@ -0,0 +1,46 @@ +# File-share backup path only. Replace backup RG, storage account ID, vault/share names. + +terraform { + required_version = ">= 1.7.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.6.0" + } + } +} + +provider "azurerm" { + features {} +} + +module "storage_backup" { + source = "../.." + + backup_resource_group_name = "example-backup-rg" + storage_account_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Storage/storageAccounts/stexample" + + tags_from_rg = false + tags = { + example = "basic" + } + + backup_share = { + policy_name = "daily-policy" + recovery_services_vault_name = "example-rsvault" + sku = "Standard" + source_file_share_name = ["example-share"] + timezone = "UTC" + backup = { + frequency = "Daily" + time = "02:00" + } + retention_daily = { + count = 7 + } + } + + backup_blob = null + lifecycle_policy_rule = null +} diff --git a/modules/azure-sa-backup/_examples/comprehensive/README.md b/modules/azure-sa-backup/_examples/comprehensive/README.md new file mode 100644 index 000000000..e72320f6f --- /dev/null +++ b/modules/azure-sa-backup/_examples/comprehensive/README.md @@ -0,0 +1,7 @@ +# Comprehensive YAML reference + +[`values.reference.yaml`](./values.reference.yaml) shows **illustrative** `backup_share` and `backup_blob` blocks together with `tags_from_rg` and IDs. + +It is **not** loaded by this module. Use it as documentation or merge into your root module. + +**Convention:** keep large YAML samples under `_examples/**` instead of embedding them in the terraform-docs `README.md`. diff --git a/modules/azure-sa-backup/_examples/comprehensive/values.reference.yaml b/modules/azure-sa-backup/_examples/comprehensive/values.reference.yaml new file mode 100644 index 000000000..82e360052 --- /dev/null +++ b/modules/azure-sa-backup/_examples/comprehensive/values.reference.yaml @@ -0,0 +1,74 @@ +# Reference YAML for module inputs (illustrative — not applied by Terraform on its own). +# Map to module arguments or use with yamldecode() in a root module. +# Do not include fields that are not in variables.tf (e.g. no vault_id under backup_blob.policy; vault is created by the module). + +tags_from_rg: true + +backup_resource_group_name: "backup-test-rg" + +storage_account_id: "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Storage/storageAccounts/xxx" + +backup_share: + policy_name: "daily-backup-policy" + recovery_services_vault_name: "test-vault" + sku: "Standard" + soft_delete_enabled: true + storage_mode_type: "GeoRedundant" + cross_region_restore_enabled: true + source_file_share_name: + - "datadir" + identity: + type: "SystemAssigned" + timezone: "UTC" + backup: + frequency: "Daily" + time: "02:00" + retention_daily: + count: 7 + retention_weekly: + count: 4 + weekdays: + - "Sunday" + retention_monthly: + count: 12 + weekdays: + - "Sunday" + weeks: + - "First" + retention_yearly: + count: 5 + weekdays: + - "Sunday" + weeks: + - "First" + months: + - "January" + +backup_blob: + vault_name: "test-vault" + datastore_type: "AzureBlob" + redundancy: "GeoRedundant" + identity_type: "SystemAssigned" + instance_blob_name: "datadir" + storage_account_container_names: + - "blob1" + - "blob2" + role_assignment: "Storage Blob Data Contributor" + policy: + name: "daily-blob-backup-policy" + backup_repeating_time_intervals: + - "R/2023-01-01T02:00:00Z/P1D" + operational_default_retention_duration: "P30D" + retention_rule: + - name: "daily-retention" + duration: "P30D" + criteria: + days_of_week: + - "Sunday" + life_cycle: + data_store_type: "VaultStore" + duration: "P30D" + priority: 1 + time_zone: "UTC" + vault_default_retention_duration: "P30D" + retention_duration: "P30D" diff --git a/modules/azure-sa-backup/docs/footer.md b/modules/azure-sa-backup/docs/footer.md new file mode 100644 index 000000000..686517cdd --- /dev/null +++ b/modules/azure-sa-backup/docs/footer.md @@ -0,0 +1,19 @@ +## Examples + +For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples): + +- [basic](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples/basic) — Azure Files backup via Recovery Services vault (`backup_share`); set RG, storage account ID, vault/policy/share names (see folder README). +- [comprehensive](https://github.com/prefapp/tfm/tree/main/modules/azure-sa-backup/_examples/comprehensive) — Reference YAML illustrating `backup_share`, `backup_blob`, and tags (documentation-oriented; see folder README). + +## External Resources + +Terraform resource docs use **4.6.0** as a baseline aligned with the `azurerm` constraint in `versions.tf` (`~> 4.6.0`). + +- **Azure Backup**: [https://learn.microsoft.com/azure/backup/](https://learn.microsoft.com/azure/backup/) +- **azurerm_recovery_services_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/recovery_services_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/recovery_services_vault) +- **azurerm_data_protection_backup_vault**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/data_protection_backup_vault](https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0/docs/resources/data_protection_backup_vault) +- **Terraform AzureRM provider**: [https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0](https://registry.terraform.io/providers/hashicorp/azurerm/4.6.0) + +## Support + +For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues). diff --git a/modules/azure-sa-backup/docs/header.md b/modules/azure-sa-backup/docs/header.md new file mode 100644 index 000000000..dffa32ea6 --- /dev/null +++ b/modules/azure-sa-backup/docs/header.md @@ -0,0 +1,88 @@ +# Azure Storage Account backup Terraform module (`azure-sa-backup`) + +## Overview + +This module configures **Azure Backup** for an existing **storage account**, in two optional paths: + +- **Azure Files**: Recovery Services vault, registration of the storage account as a backup container, a **single file share backup policy**, and **one protected file share**. + + > ⚠️ **Known limitation**: Only a single value is supported in `backup_share.source_file_share_name`. Providing multiple entries will result in a validation error until multi-share support is implemented. +- **Blobs (Data Protection)**: Backup vault, **blob backup policy**, optional **managed identity**, **role assignment** on the storage account for the vault identity, and a **blob backup instance**. + + > ⚠️ **Known caveat**: Always set `backup_blob.identity_type` (for example, `SystemAssigned`) when enabling blob backup. The role assignment count uses `can(var.backup_blob.identity_type)`, which can evaluate to `true` even when the value is `null`; in that case plan/apply can fail when resolving `identity[0]`. + +You can enable **only shares**, **only blobs**, or **both**. The module reads an existing **resource group** (`backup_resource_group_name`) for location and optional tag merge; it does **not** create that resource group or the storage account. + +## Key features + +- **Tags**: `tags` plus optional merge from the backup resource group when `tags_from_rg = true` (default `false`). +- **Conditional resources**: `backup_share` and `backup_blob` are each optional (`null` disables that path). +- **Outputs**: vault and instance IDs for the blob path; Recovery Services vault ID and a map of protected file share item IDs for the share path (see `outputs.tf`). +- **Known limitation (file shares)**: Only one value in `backup_share.source_file_share_name` is supported; multiple entries will result in a validation error. +- **Known caveat (blobs)**: Omitting `backup_blob.identity_type` is unsafe with the current role assignment logic; set it explicitly for blob backup. + +## Prerequisites + +- Existing **resource group** for backup resources (`backup_resource_group_name`). +- Existing **storage account** and, for file share backup, a single existing **file share** name in `backup_share.source_file_share_name` (one element only). +- Appropriate **permissions** for Terraform in the subscription (Backup Contributor / relevant roles as required by your org). + +## Basic usage + +Provide `backup_resource_group_name`, `storage_account_id`, and at least one of `backup_share` or `backup_blob`. See the **Inputs** table for the full object shapes. + +### Example (file share backup only) + +```hcl +module "storage_backup" { + source = "git::https://github.com/prefapp/tfm.git//modules/azure-sa-backup?ref=" + + backup_resource_group_name = "my-backup-rg" + storage_account_id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sa-rg/providers/Microsoft.Storage/storageAccounts/mystorage" + + tags_from_rg = false + tags = { + environment = "dev" + } + + backup_share = { + policy_name = "daily-backup-policy" + recovery_services_vault_name = "my-rsvault" + sku = "Standard" + source_file_share_name = ["myshare"] + timezone = "UTC" + backup = { + frequency = "Daily" + time = "02:00" + } + retention_daily = { + count = 7 + } + } + + backup_blob = null + lifecycle_policy_rule = null +} +``` + +## File structure + +``` +. +├── CHANGELOG.md +├── blobs.tf +├── locals.tf +├── main.tf +├── outputs.tf +├── shares.tf +├── variables.tf +├── versions.tf +├── docs +│ ├── footer.md +│ └── header.md +├── _examples +│ ├── basic +│ └── comprehensive +├── README.md +└── .terraform-docs.yml +``` diff --git a/modules/azure-sa-backup/outputs.tf b/modules/azure-sa-backup/outputs.tf new file mode 100644 index 000000000..4e4a9971a --- /dev/null +++ b/modules/azure-sa-backup/outputs.tf @@ -0,0 +1,42 @@ +output "blob_data_protection_vault_id" { + description = "Resource ID of the Data Protection backup vault for blob backup; null if `backup_blob` is not configured." + value = var.backup_blob != null ? azurerm_data_protection_backup_vault.this[0].id : null +} + +output "blob_backup_instance_id" { + description = "Resource ID of the blob backup instance; null if `backup_blob` is not configured." + value = var.backup_blob != null ? azurerm_data_protection_backup_instance_blob_storage.this[0].id : null +} + +output "file_share_recovery_services_vault_id" { + description = "Resource ID of the Recovery Services vault for file share backup; null if `backup_share` is not configured." + value = var.backup_share != null ? azurerm_recovery_services_vault.this[0].id : null +} + +output "file_share_protected_item_ids" { + description = "Map containing the protected item ID for the configured file share (only one supported); empty if `backup_share` is not configured." + value = var.backup_share == null ? {} : { + for idx, name in var.backup_share.source_file_share_name : + name => azurerm_backup_protected_file_share.this[idx].id + } +} + +output "blob_backup_policy_id" { + description = "Resource ID of the blob backup policy; null if `backup_blob` is not configured." + value = var.backup_blob != null ? azurerm_data_protection_backup_policy_blob_storage.this[0].id : null +} + +output "blob_backup_vault_principal_id" { + description = "Principal ID of the backup vault managed identity; null if `backup_blob` is not configured or no identity is defined." + value = var.backup_blob != null && var.backup_blob.identity_type != null ? azurerm_data_protection_backup_vault.this[0].identity[0].principal_id : null +} + +output "file_share_backup_policy_id" { + description = "Resource ID of the file share backup policy; null if `backup_share` is not configured." + value = var.backup_share != null ? azurerm_backup_policy_file_share.this[0].id : null +} + +output "blob_backup_role_assignment_id" { + description = "Role assignment ID granting the backup vault access to the storage account; null if `backup_blob` is not configured or no identity is defined." + value = var.backup_blob != null && var.backup_blob.identity_type != null ? azurerm_role_assignment.this[0].id : null +} diff --git a/modules/azure-sa-backup/variables.tf b/modules/azure-sa-backup/variables.tf index 97f94b88a..94953f190 100644 --- a/modules/azure-sa-backup/variables.tf +++ b/modules/azure-sa-backup/variables.tf @@ -1,12 +1,12 @@ # VARIABLES SECTION ## General variable "backup_resource_group_name" { - description = "The name for the resource group for the backups" + description = "Name of the existing resource group where backup vaults and policies are created (also used for the data source and optional tag merge)." type = string } variable "storage_account_id" { - description = "The ID of the storage account" + description = "Full Azure resource ID of the storage account to protect (file shares and/or blob backup)." type = string } @@ -70,6 +70,10 @@ variable "backup_share" { })) }) default = null + validation { + condition = var.backup_share == null || length(var.backup_share.source_file_share_name) == 1 + error_message = "When backup_share is set, exactly one value must be provided in backup_share.source_file_share_name." + } } ## Backup blobs variables @@ -113,6 +117,7 @@ variable "backup_blob" { } variable "lifecycle_policy_rule" { + description = "DEPRECATED: Currently not used by any resource. Setting this variable has no effect." type = list(object({ name = string enabled = bool