From ec2a695700f24df4c7db69578bb2cac7bb45b016 Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Mon, 17 Feb 2025 16:09:13 +0000 Subject: [PATCH 01/11] Adding Backup vault to the base workspace. Adding Backup vault to the base workspace. Allows enableing or disableing of the vault. Also added a step to purge the vault as apart of the clean up and removal. --- templates/workspaces/base/cleanup_vault.sh | 110 ++++++++++++++ templates/workspaces/base/parameters.json | 12 ++ templates/workspaces/base/porter.yaml | 95 +++++++++++- .../workspaces/base/template_schema.json | 8 ++ .../workspaces/base/terraform/aad/aad.tf | 1 + .../base/terraform/api-permissions.tf | 13 ++ .../base/terraform/backup/backup.tf | 136 ++++++++++++++++++ .../base/terraform/backup/locals.tf | 6 + .../base/terraform/backup/outputs.tf | 11 ++ .../base/terraform/backup/providers.tf | 13 ++ .../base/terraform/backup/variables.tf | 33 +++++ .../workspaces/base/terraform/outputs.tf | 12 ++ .../workspaces/base/terraform/storage.tf | 2 +- .../workspaces/base/terraform/variables.tf | 29 ++++ .../workspaces/base/terraform/workspace.tf | 26 ++++ 15 files changed, 505 insertions(+), 2 deletions(-) create mode 100644 templates/workspaces/base/cleanup_vault.sh create mode 100644 templates/workspaces/base/terraform/backup/backup.tf create mode 100644 templates/workspaces/base/terraform/backup/locals.tf create mode 100644 templates/workspaces/base/terraform/backup/outputs.tf create mode 100644 templates/workspaces/base/terraform/backup/providers.tf create mode 100644 templates/workspaces/base/terraform/backup/variables.tf diff --git a/templates/workspaces/base/cleanup_vault.sh b/templates/workspaces/base/cleanup_vault.sh new file mode 100644 index 0000000000..30d7910247 --- /dev/null +++ b/templates/workspaces/base/cleanup_vault.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o nounset + +# Uncomment for debugging (will show secrets) +# set -o xtrace + +function usage() { + cat < /dev/null; then + echo "Error: $cmd is not installed." + exit 1 + fi +done + +# Ensure environment variable is set +if [ -z "${AZURE_ENVIRONMENT:-}" ]; then + echo "Error: AZURE_ENVIRONMENT environment variable is not set." + usage +fi + +# Ensure arguments are provided +if [ $# -eq 0 ]; then + usage +fi + +# Parse arguments +while [ "$1" != "" ]; do + case $1 in + --resource-group) + shift + RESOURCE_GROUP=$1 + ;; + --vault-name) + shift + VAULT_NAME=$1 + ;; + *) + echo "Unexpected argument: '$1'" + usage + ;; + esac + + if [[ -z "$2" ]]; then + break + fi + + shift +done + +# Ensure required arguments are set +if [ -z "${RESOURCE_GROUP:-}" ] || [ -z "${VAULT_NAME:-}" ]; then + echo "Error: --resource-group and --vault-name are required." + usage +fi + +# Set Azure Cloud environment +az cloud set --name "$AZURE_ENVIRONMENT" + +# Check if Vault Exists +echo "Checking for Recovery Services Vault: $VAULT_NAME in $RESOURCE_GROUP" +vault_exists=$(az resource show --resource-group "$RESOURCE_GROUP" --name "$VAULT_NAME" --resource-type "Microsoft.RecoveryServices/vaults" --query "id" -o tsv || echo "") + +if [ -z "$vault_exists" ]; then + echo "Vault does not exist or is already deleted. Skipping cleanup." + exit 0 +fi + +# **Disable Soft Delete for the Vault** +echo "Disabling soft delete for Recovery Services Vault..." +az backup vault backup-properties set --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --soft-delete-feature-state Disable || echo "Warning: Unable to disable soft delete." + +# **Verify Soft Delete is Disabled** +soft_delete_status=$(az backup vault backup-properties show --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --query "softDeleteFeatureState" -o tsv) +if [[ "$soft_delete_status" != "Disabled" ]]; then + echo "Error: Soft delete is still enabled. Vault cannot be deleted." + exit 1 +fi + +# **Get all protected backup items (VMs, File Shares, SQL, etc.)** +echo "Fetching all protected backup items..." +protected_items=$(az backup item list --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --query "[].{name:name, containerName:properties.containerName, type:properties.protectedItemType}" -o json) + +# **Disable protection for each registered backup item** +for row in $(echo "$protected_items" | jq -c '.[]'); do + item_name=$(echo "$row" | jq -r '.name') + container_name=$(echo "$row" | jq -r '.containerName') + item_type=$(echo "$row" | jq -r '.type') + + echo "Disabling protection for: $item_name ($item_type)" + az backup protection disable --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --container-name "$container_name" --item-name "$item_name" --delete-backup-data true --yes || echo "Warning: Failed to disable protection for $item_name" +done + + + + diff --git a/templates/workspaces/base/parameters.json b/templates/workspaces/base/parameters.json index f95d146600..3d9896abb0 100755 --- a/templates/workspaces/base/parameters.json +++ b/templates/workspaces/base/parameters.json @@ -159,6 +159,18 @@ "source": { "env": "KEY_STORE_ID" } + }, + { + "name": "enable_backup", + "source": { + "env": "ENABLE_BACKUP" + } + }, + { + "name": "shared_storage_name", + "source": { + "env": "SHARED_STORAGE_NAME" + } } ] } diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index ed48af1a9b..572317ecea 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-workspace-base -version: 1.9.3 +version: 2.0.10 description: "A base Azure TRE workspace" dockerfile: Dockerfile.tmpl registry: azuretre @@ -126,6 +126,31 @@ parameters: type: string default: "GRS" description: "The redundancy option for the storage account in the workspace: GRS (Geo-Redundant Storage) or ZRS (Zone-Redundant Storage)." + - name: enable_backup + type: boolean + default: true + description: "Enable backups for the workspace, including the vm's & shared storage." + - name: shared_storage_name + type: string + default: "vm-shared-storage" + description: "The name of the shared storage used for the workspace VMs" + - name: backup_vault_name + type: string + default: "" + description: "The name of the backup vault to use for backups" + - name: backup_vault_vm_backup_policy_name + type: string + default: "" + description: "The name of the backup policy to use for VM backups" + - name: backup_vault_fileshare_backup_policy_name + type: string + default: "" + description: "The name of the backup policy to use for fileshare backups" + - name: workspace_resource_name_suffix + type: string + default: "" + description: "A suffix to append to the workspace resource names" + outputs: - name: app_role_id_workspace_owner @@ -158,6 +183,22 @@ outputs: applyTo: - install - upgrade + - name: backup_vault_name + type: string + applyTo: + - install + - upgrade + - name: backup_vault_vm_backup_policy_name + type: string + applyTo: + - install + - upgrade + - name: backup_vault_fileshare_backup_policy_name + type: string + applyTo: + - install + - upgrade + mixins: - exec @@ -196,6 +237,10 @@ install: enable_cmk_encryption: ${ bundle.parameters.enable_cmk_encryption } key_store_id: ${ bundle.parameters.key_store_id } storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy } + enable_backup: ${ bundle.parameters.enable_backup } + backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name } + backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name } + backup_vault_name: ${ bundle.parameters.backup_vault_name } backendConfig: use_azuread_auth: "true" use_oidc: "true" @@ -210,6 +255,9 @@ install: - name: client_id - name: scope_id - name: sp_id + - name: backup_vault_name + - name: backup_vault_vm_backup_policy_name + - name: backup_vault_fileshare_backup_policy_name upgrade: - terraform: @@ -241,6 +289,10 @@ upgrade: enable_cmk_encryption: ${ bundle.parameters.enable_cmk_encryption } key_store_id: ${ bundle.parameters.key_store_id } storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy } + enable_backup: ${ bundle.parameters.enable_backup } + backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name } + backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name } + backup_vault_name: ${ bundle.parameters.backup_vault_name } backendConfig: use_azuread_auth: "true" use_oidc: "true" @@ -255,6 +307,9 @@ upgrade: - name: client_id - name: scope_id - name: sp_id + - name: backup_vault_name + - name: backup_vault_vm_backup_policy_name + - name: backup_vault_fileshare_backup_policy_name - az: description: "Set Azure Cloud Environment" arguments: @@ -281,6 +336,30 @@ upgrade: register-aad-application: '${ bundle.parameters.register_aad_application }' uninstall: + - az: + description: "Set Azure Cloud Environment" + arguments: + - cloud + - set + flags: + name: ${ bundle.parameters.azure_environment } + - az: + description: "Azure Login" + arguments: + - login + flags: + service-principal: "" + username: '${ bundle.credentials.azure_client_id }' + password: '${ bundle.credentials.azure_client_secret }' + tenant: '${ bundle.credentials.azure_tenant_id }' + allow-no-subscriptions: "" + - exec: + description: "Running Recovery Services Vault Cleanup" + command: ./cleanup_vault.sh + flags: + resource-group: '${ bundle.parameters.workspace_resource_name_suffix }' + vault-name: '${ bundle.parameters.backup_vault_name }' + - terraform: description: "Tear down workspace" vars: @@ -309,6 +388,10 @@ uninstall: enable_cmk_encryption: ${ bundle.parameters.enable_cmk_encryption } key_store_id: ${ bundle.parameters.key_store_id } storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy } + enable_backup: ${ bundle.parameters.enable_backup } + backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name } + backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name } + backup_vault_name: ${ bundle.parameters.backup_vault_name } backendConfig: use_azuread_auth: "true" use_oidc: "true" @@ -316,3 +399,13 @@ uninstall: storage_account_name: ${ bundle.parameters.tfstate_storage_account_name } container_name: ${ bundle.parameters.tfstate_container_name } key: ${ bundle.parameters.tre_id }-ws-${ bundle.parameters.id } + outputs: + - name: app_role_id_workspace_owner + - name: app_role_id_workspace_researcher + - name: app_role_id_workspace_airlock_manager + - name: client_id + - name: scope_id + - name: sp_id + - name: backup_vault_name + - name: backup_vault_vm_backup_policy_name + - name: backup_vault_fileshare_backup_policy_name diff --git a/templates/workspaces/base/template_schema.json b/templates/workspaces/base/template_schema.json index 24cec47f34..bee7c282c7 100644 --- a/templates/workspaces/base/template_schema.json +++ b/templates/workspaces/base/template_schema.json @@ -73,6 +73,13 @@ "Manual" ], "updateable": true + }, + "enable_backup": { + "type": "boolean", + "title": "Enable Backup", + "description": "Enable backups for the workspace, including the vm's & shared storage.", + "default": true, + "updateable": true } }, "allOf": [ @@ -304,6 +311,7 @@ "create_aad_groups", "client_id", "client_secret", + "enable_backup", "enable_airlock", "configure_review_vms", "airlock_review_config", diff --git a/templates/workspaces/base/terraform/aad/aad.tf b/templates/workspaces/base/terraform/aad/aad.tf index 031f32b5a0..52005f432c 100644 --- a/templates/workspaces/base/terraform/aad/aad.tf +++ b/templates/workspaces/base/terraform/aad/aad.tf @@ -103,6 +103,7 @@ resource "azuread_service_principal" "workspace" { resource "azuread_service_principal_password" "workspace" { service_principal_id = azuread_service_principal.workspace.object_id + } resource "azurerm_key_vault_secret" "client_id" { diff --git a/templates/workspaces/base/terraform/api-permissions.tf b/templates/workspaces/base/terraform/api-permissions.tf index ee4f5ee6b8..1d5c427759 100644 --- a/templates/workspaces/base/terraform/api-permissions.tf +++ b/templates/workspaces/base/terraform/api-permissions.tf @@ -20,3 +20,16 @@ resource "azurerm_role_assignment" "api_reader" { role_definition_name = "Reader" principal_id = data.azurerm_user_assigned_identity.api_id.principal_id } + +# adds the needed permissions to the API to manage the backup and site recovery +resource "azurerm_role_assignment" "backup_contributor" { + scope = azurerm_resource_group.ws.id + role_definition_name = "Backup Contributor" + principal_id = data.azurerm_user_assigned_identity.api_id.principal_id +} + +resource "azurerm_role_assignment" "site_recover_contributor" { + scope = azurerm_resource_group.ws.id + role_definition_name = "Site Recovery Contributor" + principal_id = data.azurerm_user_assigned_identity.api_id.principal_id +} diff --git a/templates/workspaces/base/terraform/backup/backup.tf b/templates/workspaces/base/terraform/backup/backup.tf new file mode 100644 index 0000000000..04e3872f7e --- /dev/null +++ b/templates/workspaces/base/terraform/backup/backup.tf @@ -0,0 +1,136 @@ + +resource "azurerm_recovery_services_vault" "vault" { + name = local.vault_name + location = var.location + resource_group_name = var.resource_group_name + sku = "Standard" + soft_delete_enabled = true + storage_mode_type = "ZoneRedundant" # Possible values are "GeoRedundant", "LocallyRedundant" and "ZoneRedundant". Defaults to "GeoRedundant". + tags = var.tre_workspace_tags + + dynamic "identity" { + for_each = var.enable_cmk_encryption ? [1] : [] + content { + type = "UserAssigned" + identity_ids = [azurerm_user_assigned_identity.encryption_identity[0].id] + } + } + + dynamic "encryption" { + for_each = var.enable_cmk_encryption ? [1] : [] + content{ + key_id = azurerm_key_vault_key.encryption_key[0].versionless_id + infrastructure_encryption_enabled = true + user_assigned_identity_id = azurerm_user_assigned_identity.encryption_identity[0].id + use_system_assigned_identity = false + } + } + + lifecycle { ignore_changes = [encryption, tags] } + +} + +resource "azurerm_backup_policy_vm" "vm_policy" { + name = local.vm_backup_policy_name + resource_group_name = var.resource_group_name + recovery_vault_name = azurerm_recovery_services_vault.vault.name + + + timezone = "UTC" + + backup { + frequency = "Daily" + time = "22:00" + } + + retention_daily { + count = 14 + } + + retention_weekly { + count = 4 + weekdays = ["Sunday"] + } + + retention_monthly { + count = 12 + weekdays = ["Monday"] + weeks = ["First"] + } + + retention_yearly { + count = 2 + months = ["December"] + weekdays = ["Sunday"] + weeks = ["Last"] + } + + depends_on = [ + azurerm_recovery_services_vault.vault + ] + + +} + +resource "azurerm_backup_policy_file_share" "file_share_policy" { + name = local.fs_backup_policy_name + resource_group_name = var.resource_group_name + recovery_vault_name = azurerm_recovery_services_vault.vault.name + + timezone = "UTC" + + backup { + frequency = "Daily" + time = "23:00" + } + + retention_daily { + count = 14 + } + + retention_weekly { + count = 4 + weekdays = ["Sunday"] + } + + retention_monthly { + count = 12 + weekdays = ["Monday"] + weeks = ["First"] + } + + retention_yearly { + count = 2 + months = ["December"] + weekdays = ["Sunday"] + weeks = ["Last"] + } + + depends_on = [ + azurerm_recovery_services_vault.vault + ] + +} + +resource "azurerm_backup_container_storage_account" "storage_account" { + resource_group_name = var.resource_group_name + recovery_vault_name = azurerm_recovery_services_vault.vault.name + storage_account_id = var.azurerm_storage_account_id + + depends_on = [ + azurerm_recovery_services_vault.vault + ] +} + +resource "azurerm_backup_protected_file_share" "file_share" { + resource_group_name = var.resource_group_name + recovery_vault_name = azurerm_recovery_services_vault.vault.name + source_storage_account_id = var.azurerm_storage_account_id + source_file_share_name = var.shared_storage_name + backup_policy_id = azurerm_backup_policy_file_share.file_share_policy.id + + depends_on = [ + azurerm_backup_policy_file_share.file_share_policy, + azurerm_backup_container_storage_account.storage_account + ] +} diff --git a/templates/workspaces/base/terraform/backup/locals.tf b/templates/workspaces/base/terraform/backup/locals.tf new file mode 100644 index 0000000000..54be196867 --- /dev/null +++ b/templates/workspaces/base/terraform/backup/locals.tf @@ -0,0 +1,6 @@ +locals { + short_workspace_id = substr(var.tre_resource_id, -4, -1) + vault_name = "arsv-${var.tre_id}-ws-${local.short_workspace_id}" + vm_backup_policy_name = "abp-vm-${var.tre_id}-ws-${local.short_workspace_id}" + fs_backup_policy_name = "abp-fs-${var.tre_id}-ws-${local.short_workspace_id}" +} \ No newline at end of file diff --git a/templates/workspaces/base/terraform/backup/outputs.tf b/templates/workspaces/base/terraform/backup/outputs.tf new file mode 100644 index 0000000000..d9f78ca882 --- /dev/null +++ b/templates/workspaces/base/terraform/backup/outputs.tf @@ -0,0 +1,11 @@ +output "backup_vault_name" { + value = azurerm_recovery_services_vault.vault.name +} + +output "backup_vault_vm_backup_policy_name" { + value = azurerm_backup_policy_vm.vm_policy.name +} + +output "backup_vault_fileshare_backup_policy_name" { + value = azurerm_backup_policy_file_share.file_share_policy.name +} diff --git a/templates/workspaces/base/terraform/backup/providers.tf b/templates/workspaces/base/terraform/backup/providers.tf new file mode 100644 index 0000000000..e8faff4500 --- /dev/null +++ b/templates/workspaces/base/terraform/backup/providers.tf @@ -0,0 +1,13 @@ +terraform { + # In modules we should only specify the min version + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">= 3.117.0" + } + random = { + source = "hashicorp/random" + version = ">= 3.1.0" + } + } +} diff --git a/templates/workspaces/base/terraform/backup/variables.tf b/templates/workspaces/base/terraform/backup/variables.tf new file mode 100644 index 0000000000..bd29f28b64 --- /dev/null +++ b/templates/workspaces/base/terraform/backup/variables.tf @@ -0,0 +1,33 @@ +variable "location" { + type = string +} +variable "tre_id" { + type = string +} +variable "resource_group_name" { + type = string +} +variable "resource_group_id" { + type = string +} +variable "enable_local_debugging" { + type = bool +} +variable "tre_workspace_tags" { + type = map(string) +} +variable "arm_environment" { + type = string +} +variable "azurerm_storage_account_id" { + type = string +} +variable "tre_resource_id" { + type = string +} +variable "enable_cmk_encryption" { + type = bool +} +variable "shared_storage_name" { + type = string +} diff --git a/templates/workspaces/base/terraform/outputs.tf b/templates/workspaces/base/terraform/outputs.tf index 40fa8dcd69..691751cbfa 100644 --- a/templates/workspaces/base/terraform/outputs.tf +++ b/templates/workspaces/base/terraform/outputs.tf @@ -29,3 +29,15 @@ output "scope_id" { value = var.register_aad_application ? module.aad[0].scope_id : var.scope_id } +output "backup_vault_name" { + value = var.enable_backup ? module.backup[0].backup_vault_name : var.backup_vault_name +} + +output "backup_vault_vm_backup_policy_name" { + value = var.enable_backup ? module.backup[0].backup_vault_vm_backup_policy_name : var.backup_vault_vm_backup_policy_name +} + +output "backup_vault_fileshare_backup_policy_name" { + value = var.enable_backup ? module.backup[0].backup_vault_fileshare_backup_policy_name : var.backup_vault_fileshare_backup_policy_name +} + diff --git a/templates/workspaces/base/terraform/storage.tf b/templates/workspaces/base/terraform/storage.tf index 7fc6f00a2c..75f34786de 100644 --- a/templates/workspaces/base/terraform/storage.tf +++ b/templates/workspaces/base/terraform/storage.tf @@ -36,7 +36,7 @@ resource "azurerm_storage_account" "stg" { # Using AzAPI as AzureRM uses shared account key for Azure files operations resource "azapi_resource" "shared_storage" { type = "Microsoft.Storage/storageAccounts/fileServices/shares@2023-05-01" - name = "vm-shared-storage" + name = var.shared_storage_name parent_id = "${azurerm_storage_account.stg.id}/fileServices/default" body = jsonencode({ properties = { diff --git a/templates/workspaces/base/terraform/variables.tf b/templates/workspaces/base/terraform/variables.tf index b3e2812785..ed928f5c49 100644 --- a/templates/workspaces/base/terraform/variables.tf +++ b/templates/workspaces/base/terraform/variables.tf @@ -75,6 +75,17 @@ variable "auth_client_secret" { type = string description = "Used to authenticate into the AAD Tenant to create the AAD App" } +variable "enable_backup"{ + type = bool + default = true + description = "Enable backups for the workspace" +} + +variable "shared_storage_name" { + type = string + default = "vm-shared-storage" + description = "Name of the VM Shared Storage" +} # These variables are only passed in if you are not registering an AAD # application as they need passing back out @@ -139,3 +150,21 @@ variable "storage_account_redundancy" { default = "GRS" description = "The redundancy option for the storage account in the workspace: GRS (Geo-Redundant Storage) or ZRS (Zone-Redundant Storage)." } + +variable "backup_vault_name" { + type = string + default = "" + description = "Name of the backup vault" +} + +variable "backup_vault_vm_backup_policy_name" { + type = string + default = "" + description = "Name of the backup policy for VMs" +} + +variable "backup_vault_fileshare_backup_policy_name" { + type = string + default = "" + description = "Name of the backup policy for File Shares" +} diff --git a/templates/workspaces/base/terraform/workspace.tf b/templates/workspaces/base/terraform/workspace.tf index 10fb74c6a7..fe1fec2f33 100644 --- a/templates/workspaces/base/terraform/workspace.tf +++ b/templates/workspaces/base/terraform/workspace.tf @@ -88,3 +88,29 @@ module "azure_monitor" { module.airlock ] } + + +module "backup" { + count = var.enable_backup ? 1 : 0 + source = "./backup" + tre_id = var.tre_id + tre_resource_id = var.tre_resource_id + location = var.location + resource_group_name = azurerm_resource_group.ws.name + resource_group_id = azurerm_resource_group.ws.id + tre_workspace_tags = local.tre_workspace_tags + arm_environment = var.arm_environment + azurerm_storage_account_id = azurerm_storage_account.stg.id + enable_local_debugging = var.enable_local_debugging + enable_cmk_encryption = var.enable_cmk_encryption + shared_storage_name = var.shared_storage_name + + + depends_on = [ + azurerm_storage_account.stg, + azapi_resource.shared_storage, + module.network, + module.airlock, + module.aad + ] +} From 992eebc5e5c0065c0487286024988beb69852a5c Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Mon, 17 Feb 2025 23:29:00 +0000 Subject: [PATCH 02/11] Update workspace.tf removed the depends on to the airlock as that maynot be enabled. --- templates/workspaces/base/terraform/workspace.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/workspaces/base/terraform/workspace.tf b/templates/workspaces/base/terraform/workspace.tf index fe1fec2f33..33c763838c 100644 --- a/templates/workspaces/base/terraform/workspace.tf +++ b/templates/workspaces/base/terraform/workspace.tf @@ -110,7 +110,6 @@ module "backup" { azurerm_storage_account.stg, azapi_resource.shared_storage, module.network, - module.airlock, module.aad ] } From e7de56b900e6aad34d7de0a3d87d5ea8515204c9 Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:23:14 +0000 Subject: [PATCH 03/11] Update aad.tf removed the random new line that was added --- templates/workspaces/base/terraform/aad/aad.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/workspaces/base/terraform/aad/aad.tf b/templates/workspaces/base/terraform/aad/aad.tf index 52005f432c..031f32b5a0 100644 --- a/templates/workspaces/base/terraform/aad/aad.tf +++ b/templates/workspaces/base/terraform/aad/aad.tf @@ -103,7 +103,6 @@ resource "azuread_service_principal" "workspace" { resource "azuread_service_principal_password" "workspace" { service_principal_id = azuread_service_principal.workspace.object_id - } resource "azurerm_key_vault_secret" "client_id" { From 15c8f9887b967b05ba8a972a8644967333ec63d9 Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:30:00 +0000 Subject: [PATCH 04/11] removed the shared storage veriable. --- templates/workspaces/base/parameters.json | 6 ------ templates/workspaces/base/porter.yaml | 4 ---- templates/workspaces/base/terraform/locals.tf | 1 + templates/workspaces/base/terraform/variables.tf | 6 ------ templates/workspaces/base/terraform/workspace.tf | 2 +- 5 files changed, 2 insertions(+), 17 deletions(-) diff --git a/templates/workspaces/base/parameters.json b/templates/workspaces/base/parameters.json index 3d9896abb0..72f31b874b 100755 --- a/templates/workspaces/base/parameters.json +++ b/templates/workspaces/base/parameters.json @@ -165,12 +165,6 @@ "source": { "env": "ENABLE_BACKUP" } - }, - { - "name": "shared_storage_name", - "source": { - "env": "SHARED_STORAGE_NAME" - } } ] } diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index 572317ecea..aa71046d5e 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -130,10 +130,6 @@ parameters: type: boolean default: true description: "Enable backups for the workspace, including the vm's & shared storage." - - name: shared_storage_name - type: string - default: "vm-shared-storage" - description: "The name of the shared storage used for the workspace VMs" - name: backup_vault_name type: string default: "" diff --git a/templates/workspaces/base/terraform/locals.tf b/templates/workspaces/base/terraform/locals.tf index bc84d98e4d..cdac8356b5 100644 --- a/templates/workspaces/base/terraform/locals.tf +++ b/templates/workspaces/base/terraform/locals.tf @@ -10,4 +10,5 @@ locals { } kv_encryption_key_name = "tre-encryption-${local.workspace_resource_name_suffix}" encryption_identity_name = "id-encryption-${var.tre_id}-${local.short_workspace_id}" + shared_storage_name = "vm-shared-storage" } diff --git a/templates/workspaces/base/terraform/variables.tf b/templates/workspaces/base/terraform/variables.tf index ed928f5c49..545c58d04c 100644 --- a/templates/workspaces/base/terraform/variables.tf +++ b/templates/workspaces/base/terraform/variables.tf @@ -81,12 +81,6 @@ variable "enable_backup"{ description = "Enable backups for the workspace" } -variable "shared_storage_name" { - type = string - default = "vm-shared-storage" - description = "Name of the VM Shared Storage" -} - # These variables are only passed in if you are not registering an AAD # application as they need passing back out variable "app_role_id_workspace_owner" { diff --git a/templates/workspaces/base/terraform/workspace.tf b/templates/workspaces/base/terraform/workspace.tf index 33c763838c..031b9727ed 100644 --- a/templates/workspaces/base/terraform/workspace.tf +++ b/templates/workspaces/base/terraform/workspace.tf @@ -103,7 +103,7 @@ module "backup" { azurerm_storage_account_id = azurerm_storage_account.stg.id enable_local_debugging = var.enable_local_debugging enable_cmk_encryption = var.enable_cmk_encryption - shared_storage_name = var.shared_storage_name + shared_storage_name = local.shared_storage_name depends_on = [ From 5a58ad234a638288688d16f74bd15526973e3c3e Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:23:14 +0000 Subject: [PATCH 05/11] Update aad.tf removed the random new line that was added --- templates/workspaces/base/terraform/aad/aad.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/workspaces/base/terraform/aad/aad.tf b/templates/workspaces/base/terraform/aad/aad.tf index 52005f432c..031f32b5a0 100644 --- a/templates/workspaces/base/terraform/aad/aad.tf +++ b/templates/workspaces/base/terraform/aad/aad.tf @@ -103,7 +103,6 @@ resource "azuread_service_principal" "workspace" { resource "azuread_service_principal_password" "workspace" { service_principal_id = azuread_service_principal.workspace.object_id - } resource "azurerm_key_vault_secret" "client_id" { From 4aea32efafe91dcea726dfca0e580f0b9b28bef5 Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Tue, 18 Feb 2025 17:05:52 +0000 Subject: [PATCH 06/11] removed the script as not need and update the backup provider to allow purging of backup items. Testing ingoing. --- templates/workspaces/base/cleanup_vault.sh | 110 ------------------ templates/workspaces/base/porter.yaml | 26 +---- .../base/terraform/backup/providers.tf | 9 ++ 3 files changed, 10 insertions(+), 135 deletions(-) delete mode 100644 templates/workspaces/base/cleanup_vault.sh diff --git a/templates/workspaces/base/cleanup_vault.sh b/templates/workspaces/base/cleanup_vault.sh deleted file mode 100644 index 30d7910247..0000000000 --- a/templates/workspaces/base/cleanup_vault.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -set -o errexit -set -o pipefail -set -o nounset - -# Uncomment for debugging (will show secrets) -# set -o xtrace - -function usage() { - cat < /dev/null; then - echo "Error: $cmd is not installed." - exit 1 - fi -done - -# Ensure environment variable is set -if [ -z "${AZURE_ENVIRONMENT:-}" ]; then - echo "Error: AZURE_ENVIRONMENT environment variable is not set." - usage -fi - -# Ensure arguments are provided -if [ $# -eq 0 ]; then - usage -fi - -# Parse arguments -while [ "$1" != "" ]; do - case $1 in - --resource-group) - shift - RESOURCE_GROUP=$1 - ;; - --vault-name) - shift - VAULT_NAME=$1 - ;; - *) - echo "Unexpected argument: '$1'" - usage - ;; - esac - - if [[ -z "$2" ]]; then - break - fi - - shift -done - -# Ensure required arguments are set -if [ -z "${RESOURCE_GROUP:-}" ] || [ -z "${VAULT_NAME:-}" ]; then - echo "Error: --resource-group and --vault-name are required." - usage -fi - -# Set Azure Cloud environment -az cloud set --name "$AZURE_ENVIRONMENT" - -# Check if Vault Exists -echo "Checking for Recovery Services Vault: $VAULT_NAME in $RESOURCE_GROUP" -vault_exists=$(az resource show --resource-group "$RESOURCE_GROUP" --name "$VAULT_NAME" --resource-type "Microsoft.RecoveryServices/vaults" --query "id" -o tsv || echo "") - -if [ -z "$vault_exists" ]; then - echo "Vault does not exist or is already deleted. Skipping cleanup." - exit 0 -fi - -# **Disable Soft Delete for the Vault** -echo "Disabling soft delete for Recovery Services Vault..." -az backup vault backup-properties set --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --soft-delete-feature-state Disable || echo "Warning: Unable to disable soft delete." - -# **Verify Soft Delete is Disabled** -soft_delete_status=$(az backup vault backup-properties show --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --query "softDeleteFeatureState" -o tsv) -if [[ "$soft_delete_status" != "Disabled" ]]; then - echo "Error: Soft delete is still enabled. Vault cannot be deleted." - exit 1 -fi - -# **Get all protected backup items (VMs, File Shares, SQL, etc.)** -echo "Fetching all protected backup items..." -protected_items=$(az backup item list --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --query "[].{name:name, containerName:properties.containerName, type:properties.protectedItemType}" -o json) - -# **Disable protection for each registered backup item** -for row in $(echo "$protected_items" | jq -c '.[]'); do - item_name=$(echo "$row" | jq -r '.name') - container_name=$(echo "$row" | jq -r '.containerName') - item_type=$(echo "$row" | jq -r '.type') - - echo "Disabling protection for: $item_name ($item_type)" - az backup protection disable --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --container-name "$container_name" --item-name "$item_name" --delete-backup-data true --yes || echo "Warning: Failed to disable protection for $item_name" -done - - - - diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index aa71046d5e..655a7d3708 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-workspace-base -version: 2.0.10 +version: 2.0.11 description: "A base Azure TRE workspace" dockerfile: Dockerfile.tmpl registry: azuretre @@ -332,30 +332,6 @@ upgrade: register-aad-application: '${ bundle.parameters.register_aad_application }' uninstall: - - az: - description: "Set Azure Cloud Environment" - arguments: - - cloud - - set - flags: - name: ${ bundle.parameters.azure_environment } - - az: - description: "Azure Login" - arguments: - - login - flags: - service-principal: "" - username: '${ bundle.credentials.azure_client_id }' - password: '${ bundle.credentials.azure_client_secret }' - tenant: '${ bundle.credentials.azure_tenant_id }' - allow-no-subscriptions: "" - - exec: - description: "Running Recovery Services Vault Cleanup" - command: ./cleanup_vault.sh - flags: - resource-group: '${ bundle.parameters.workspace_resource_name_suffix }' - vault-name: '${ bundle.parameters.backup_vault_name }' - - terraform: description: "Tear down workspace" vars: diff --git a/templates/workspaces/base/terraform/backup/providers.tf b/templates/workspaces/base/terraform/backup/providers.tf index e8faff4500..5ea0d8fe92 100644 --- a/templates/workspaces/base/terraform/backup/providers.tf +++ b/templates/workspaces/base/terraform/backup/providers.tf @@ -11,3 +11,12 @@ terraform { } } } + + +provider "azurerm" { + features { + recovery_services_vault { + purge_protected_items_from_vault_on_destroy = true + } + } +} From e237d2078a7ce71ebad6204df98503289f298798 Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Wed, 19 Feb 2025 21:29:24 +0000 Subject: [PATCH 07/11] Update templates/workspaces/base/template_schema.json Co-authored-by: Marcus Robinson --- templates/workspaces/base/template_schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/workspaces/base/template_schema.json b/templates/workspaces/base/template_schema.json index bee7c282c7..2ee913d0c9 100644 --- a/templates/workspaces/base/template_schema.json +++ b/templates/workspaces/base/template_schema.json @@ -77,7 +77,7 @@ "enable_backup": { "type": "boolean", "title": "Enable Backup", - "description": "Enable backups for the workspace, including the vm's & shared storage.", + "description": "Enable backups for the workspace. This covers any VMs deployed, and the workspace file share", "default": true, "updateable": true } From 8bc41602519cf07caeeb636ffc984696099e7d22 Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Wed, 19 Feb 2025 22:09:16 +0000 Subject: [PATCH 08/11] updated azurerm provider and added the changes. Still cant removed workspaces. may need to look at the script approch again. --- CHANGELOG.md | 5 +-- templates/workspaces/base/porter.yaml | 11 +------ .../base/terraform/.terraform.lock.hcl | 31 +++++++++---------- .../base/terraform/aad/providers.tf | 2 +- .../base/terraform/airlock/providers.tf | 2 +- .../base/terraform/api-permissions.tf | 11 ------- .../base/terraform/azure-monitor/providers.tf | 2 +- .../base/terraform/backup/providers.tf | 11 +------ .../base/terraform/network/network.tf | 4 +-- .../base/terraform/network/providers.tf | 2 +- .../workspaces/base/terraform/providers.tf | 6 +++- .../workspaces/base/terraform/storage.tf | 2 +- 12 files changed, 32 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c596b48c02..fd7bc28a81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,12 @@ ENHANCEMENTS: * Add bundle target to Makefile for handling different bundle types in single command ([#4372](https://github.com/microsoft/AzureTRE/issues/4372)) * Migrate UI to Vite build engine and update dependencies ([#4368](https://github.com/microsoft/AzureTRE/pull/4368)) * Add Windows image field to the Admin VM template ([#4274](https://github.com/microsoft/AzureTRE/pull/4274)) -* Update TLS to the latest version for web apps / function apps (([#4351](https://github.com/microsoft/AzureTRE/issues/4351)) +* Update TLS to the latest version for web apps / function apps ([#4351](https://github.com/microsoft/AzureTRE/issues/4351)) +* Added backup vault to base workspace & updated Azurerm provider to match core. ([[#4362](https://github.com/microsoft/AzureTRE/issues/4362)]) BUG FIXES: * Fix upgrade when porter install has failed ([#4338](https://github.com/microsoft/AzureTRE/pull/4338)) -* Certs shared service: Secret nexus-ssl-password is currently in a deleted but recoverable state ([#4294](https://github.com/microsoft/AzureTRE/issues/4294)]) +* Certs shared service: Secret nexus-ssl-password is currently in a deleted but recoverable state ([#4294](https://github.com/microsoft/AzureTRE/issues/4294)) * Fix Cosmos DB local debugging configuration ([#4340](https://github.com/microsoft/AzureTRE/pull/4340)) COMPONENTS: diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index 655a7d3708..bf9a4c0977 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-workspace-base -version: 2.0.11 +version: 2.0.12 description: "A base Azure TRE workspace" dockerfile: Dockerfile.tmpl registry: azuretre @@ -234,9 +234,6 @@ install: key_store_id: ${ bundle.parameters.key_store_id } storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy } enable_backup: ${ bundle.parameters.enable_backup } - backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name } - backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name } - backup_vault_name: ${ bundle.parameters.backup_vault_name } backendConfig: use_azuread_auth: "true" use_oidc: "true" @@ -286,9 +283,6 @@ upgrade: key_store_id: ${ bundle.parameters.key_store_id } storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy } enable_backup: ${ bundle.parameters.enable_backup } - backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name } - backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name } - backup_vault_name: ${ bundle.parameters.backup_vault_name } backendConfig: use_azuread_auth: "true" use_oidc: "true" @@ -361,9 +355,6 @@ uninstall: key_store_id: ${ bundle.parameters.key_store_id } storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy } enable_backup: ${ bundle.parameters.enable_backup } - backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name } - backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name } - backup_vault_name: ${ bundle.parameters.backup_vault_name } backendConfig: use_azuread_auth: "true" use_oidc: "true" diff --git a/templates/workspaces/base/terraform/.terraform.lock.hcl b/templates/workspaces/base/terraform/.terraform.lock.hcl index 8a229681d9..e01a2a6b3f 100644 --- a/templates/workspaces/base/terraform/.terraform.lock.hcl +++ b/templates/workspaces/base/terraform/.terraform.lock.hcl @@ -6,7 +6,6 @@ provider "registry.terraform.io/azure/azapi" { constraints = ">= 1.15.0, 1.15.0" hashes = [ "h1:Y7ruMuPh8UJRTRl4rm+cdpGtmURx2taqiuqfYaH3o48=", - "h1:gIOgxVmFSxHrR+XOzgUEA+ybOmp8kxZlZH3eYeB/eFI=", "zh:0627a8bc77254debc25dc0c7b62e055138217c97b03221e593c3c56dc7550671", "zh:2fe045f07070ef75d0bec4b0595a74c14394daa838ddb964e2fd23cc98c40c34", "zh:343009f39c957883b2c06145a5954e524c70f93585f943f1ea3d28ef6995d0d0", @@ -43,28 +42,28 @@ provider "registry.terraform.io/hashicorp/azuread" { } provider "registry.terraform.io/hashicorp/azurerm" { - version = "3.117.0" - constraints = ">= 3.117.0, 3.117.0" + version = "4.14.0" + constraints = "4.14.0" hashes = [ - "h1:Ynfg+Iy7x6K8M6W1AhqXCe3wkoiqIQhROlca7C3KC3w=", - "zh:2e25f47492366821a786762369f0e0921cc9452d64bfd5075f6fdfcf1a9c6d70", - "zh:41eb34f2f7469bf3eb1019dfb0e7fc28256f809824016f4f8b9d691bf473b2ac", - "zh:48bb9c87b3d928da1abc1d3db75453c9725de4674c612daf3800160cc7145d30", - "zh:5d6b0de0bbd78943fcc65c53944ef4496329e247f434c6eab86ed051c5cea67b", - "zh:78c9f6fdb1206a89cf0e6706b4f46178169a93b6c964a4cad8a321058ccbd9b4", - "zh:793b702c352589d4360b580d4a1cf654a7439d2ad6bdb7bfea91de07bc4b0fac", - "zh:7ed687ff0a5509463a592f97431863574fe5cc80a34e395be06766215b8c6285", - "zh:955ba18789bd15592824eb426a8d0f38595bd09fffc6939c1c58933489c1a71e", - "zh:bf5949a55be0714cd9c8815d472eae4baa48ba06d0f6bf2b96775869acda8a54", - "zh:da5d31f635abd2c645ffc76d6176d73f646128e73720cc368247cc424975c127", - "zh:eed5a66d59883c9c56729b0a964a2b60d758ea7489ef3e920a6fbd48518ce5f5", + "h1:FYZ9qh8i3X2gDmUTe1jJ/VzdSyjGjVmhBzv2R8D6CBo=", + "zh:05aaea16fc5f27b14d9fbad81654edf0638949ed3585576b2219c76a2bee095a", + "zh:065ce6ed16ba3fa7efcf77888ea582aead54e6a28f184c6701b73d71edd64bb0", + "zh:3c0cd17c249d18aa2e0120acb5f0c14810725158b379a67fec1331110e7c50df", + "zh:5a3ba3ffb2f1ce519fe3bf84a7296aa5862c437c70c62f0b0a5293bea9f2d01c", + "zh:7a8e9d72fa2714f4d567270b1761d4b4e788de7c15dada7db0cf0e29933185a2", + "zh:a11e190073f31c1238c15af29b9162e0f4564f6b0cd0310a3fa94102738450dc", + "zh:a5c004114410cc6dcb8fed584c9f3b84283b58025b0073a7e88d2bdb27840dfa", + "zh:a674a41db118e244eda7591e455d2ec338626664e0856e4125e909eb038f78db", + "zh:b5139010e4cbb2cb1a27c775610593c1c8063d3a7c82b00a65006509c434df2f", + "zh:cbb031223ccd8b099ac4d19b92641142f330b90f2fc6452843e445bae28f832c", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f7e7db1b94082a4ac3d4af3dabe7bbd335e1679305bf8e29d011f0ee440724ca", ] } provider "registry.terraform.io/hashicorp/random" { version = "3.3.2" - constraints = "~> 3.3.0" + constraints = ">= 3.1.0, ~> 3.3.0" hashes = [ "h1:H5V+7iXol/EHB2+BUMzGlpIiCOdV74H8YjzCxnSAWcg=", "zh:038293aebfede983e45ee55c328e3fde82ae2e5719c9bd233c324cfacc437f9c", diff --git a/templates/workspaces/base/terraform/aad/providers.tf b/templates/workspaces/base/terraform/aad/providers.tf index 4cf4c2b88a..7a31f12bb1 100644 --- a/templates/workspaces/base/terraform/aad/providers.tf +++ b/templates/workspaces/base/terraform/aad/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = ">= 3.117.0" + version = "=4.14.0" } azuread = { source = "hashicorp/azuread" diff --git a/templates/workspaces/base/terraform/airlock/providers.tf b/templates/workspaces/base/terraform/airlock/providers.tf index 3bc52af981..eaa776f219 100644 --- a/templates/workspaces/base/terraform/airlock/providers.tf +++ b/templates/workspaces/base/terraform/airlock/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = ">= 3.117.0" + version = "=4.14.0" } } } diff --git a/templates/workspaces/base/terraform/api-permissions.tf b/templates/workspaces/base/terraform/api-permissions.tf index 1d5c427759..82b1fb7f98 100644 --- a/templates/workspaces/base/terraform/api-permissions.tf +++ b/templates/workspaces/base/terraform/api-permissions.tf @@ -21,15 +21,4 @@ resource "azurerm_role_assignment" "api_reader" { principal_id = data.azurerm_user_assigned_identity.api_id.principal_id } -# adds the needed permissions to the API to manage the backup and site recovery -resource "azurerm_role_assignment" "backup_contributor" { - scope = azurerm_resource_group.ws.id - role_definition_name = "Backup Contributor" - principal_id = data.azurerm_user_assigned_identity.api_id.principal_id -} -resource "azurerm_role_assignment" "site_recover_contributor" { - scope = azurerm_resource_group.ws.id - role_definition_name = "Site Recovery Contributor" - principal_id = data.azurerm_user_assigned_identity.api_id.principal_id -} diff --git a/templates/workspaces/base/terraform/azure-monitor/providers.tf b/templates/workspaces/base/terraform/azure-monitor/providers.tf index 073110f2d1..92e7dad7e2 100644 --- a/templates/workspaces/base/terraform/azure-monitor/providers.tf +++ b/templates/workspaces/base/terraform/azure-monitor/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = ">= 3.117.0" + version = "=4.14.0" } azapi = { diff --git a/templates/workspaces/base/terraform/backup/providers.tf b/templates/workspaces/base/terraform/backup/providers.tf index 5ea0d8fe92..c7a0b571d4 100644 --- a/templates/workspaces/base/terraform/backup/providers.tf +++ b/templates/workspaces/base/terraform/backup/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = ">= 3.117.0" + version = "=4.14.0" } random = { source = "hashicorp/random" @@ -11,12 +11,3 @@ terraform { } } } - - -provider "azurerm" { - features { - recovery_services_vault { - purge_protected_items_from_vault_on_destroy = true - } - } -} diff --git a/templates/workspaces/base/terraform/network/network.tf b/templates/workspaces/base/terraform/network/network.tf index bc9e5fadb3..e311809382 100644 --- a/templates/workspaces/base/terraform/network/network.tf +++ b/templates/workspaces/base/terraform/network/network.tf @@ -14,7 +14,7 @@ resource "azurerm_subnet" "services" { resource_group_name = var.ws_resource_group_name address_prefixes = [local.services_subnet_address_prefix] # notice that private endpoints do not adhere to NSG rules - private_endpoint_network_policies_enabled = false + private_endpoint_network_policies = "Disabled" private_link_service_network_policies_enabled = true } @@ -24,7 +24,7 @@ resource "azurerm_subnet" "webapps" { resource_group_name = var.ws_resource_group_name address_prefixes = [local.webapps_subnet_address_prefix] # notice that private endpoints do not adhere to NSG rules - private_endpoint_network_policies_enabled = false + private_endpoint_network_policies = "Disabled" private_link_service_network_policies_enabled = true delegation { diff --git a/templates/workspaces/base/terraform/network/providers.tf b/templates/workspaces/base/terraform/network/providers.tf index 2817aac3ab..e0bf9b3bf2 100644 --- a/templates/workspaces/base/terraform/network/providers.tf +++ b/templates/workspaces/base/terraform/network/providers.tf @@ -3,7 +3,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = ">=3.117.0" + version = "=4.14.0" } } } diff --git a/templates/workspaces/base/terraform/providers.tf b/templates/workspaces/base/terraform/providers.tf index e541b4a4c8..bb19c1d77b 100644 --- a/templates/workspaces/base/terraform/providers.tf +++ b/templates/workspaces/base/terraform/providers.tf @@ -2,7 +2,7 @@ terraform { required_providers { azurerm = { source = "hashicorp/azurerm" - version = "=3.117.0" + version = "=4.14.0" } azuread = { source = "hashicorp/azuread" @@ -31,6 +31,10 @@ provider "azurerm" { recover_soft_deleted_certificates = true recover_soft_deleted_keys = true } + recovery_service { + vm_backup_stop_protection_and_retain_data_on_destroy = false + purge_protected_items_from_vault_on_destroy = true + } } storage_use_azuread = true } diff --git a/templates/workspaces/base/terraform/storage.tf b/templates/workspaces/base/terraform/storage.tf index 75f34786de..35eb471271 100644 --- a/templates/workspaces/base/terraform/storage.tf +++ b/templates/workspaces/base/terraform/storage.tf @@ -36,7 +36,7 @@ resource "azurerm_storage_account" "stg" { # Using AzAPI as AzureRM uses shared account key for Azure files operations resource "azapi_resource" "shared_storage" { type = "Microsoft.Storage/storageAccounts/fileServices/shares@2023-05-01" - name = var.shared_storage_name + name = local.shared_storage_name parent_id = "${azurerm_storage_account.stg.id}/fileServices/default" body = jsonencode({ properties = { From f425e340f01852f3f5ce92eab20a2ff67c502b6e Mon Sep 17 00:00:00 2001 From: Marcus Robinson Date: Thu, 20 Feb 2025 16:46:08 +0000 Subject: [PATCH 09/11] Made a couple of changes. --- templates/workspaces/base/porter.yaml | 32 ++++--------------- .../workspaces/base/template_schema.json | 2 +- .../base/terraform/network/providers.tf | 9 ++++++ .../workspaces/base/terraform/outputs.tf | 7 ++-- .../workspaces/base/terraform/providers.tf | 4 --- .../workspaces/base/terraform/variables.tf | 20 +----------- 6 files changed, 21 insertions(+), 53 deletions(-) diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index bf9a4c0977..43ad35da60 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-workspace-base -version: 2.0.12 +version: 2.0.15 description: "A base Azure TRE workspace" dockerfile: Dockerfile.tmpl registry: azuretre @@ -130,23 +130,6 @@ parameters: type: boolean default: true description: "Enable backups for the workspace, including the vm's & shared storage." - - name: backup_vault_name - type: string - default: "" - description: "The name of the backup vault to use for backups" - - name: backup_vault_vm_backup_policy_name - type: string - default: "" - description: "The name of the backup policy to use for VM backups" - - name: backup_vault_fileshare_backup_policy_name - type: string - default: "" - description: "The name of the backup policy to use for fileshare backups" - - name: workspace_resource_name_suffix - type: string - default: "" - description: "A suffix to append to the workspace resource names" - outputs: - name: app_role_id_workspace_owner @@ -195,7 +178,6 @@ outputs: - install - upgrade - mixins: - exec - terraform: @@ -313,17 +295,17 @@ upgrade: - login flags: service-principal: "" - username: '${ bundle.credentials.auth_client_id }' - password: '${ bundle.credentials.auth_client_secret }' - tenant: '${ bundle.credentials.auth_tenant_id }' + username: "${ bundle.credentials.auth_client_id }" + password: "${ bundle.credentials.auth_client_secret }" + tenant: "${ bundle.credentials.auth_tenant_id }" allow-no-subscriptions: "" - exec: description: "Update workspace app redirect urls" command: ./update_redirect_urls.sh flags: - workspace-api-client-id: '${ bundle.parameters.client_id }' - aad-redirect-uris-b64: '${ bundle.parameters.aad_redirect_uris }' - register-aad-application: '${ bundle.parameters.register_aad_application }' + workspace-api-client-id: "${ bundle.parameters.client_id }" + aad-redirect-uris-b64: "${ bundle.parameters.aad_redirect_uris }" + register-aad-application: "${ bundle.parameters.register_aad_application }" uninstall: - terraform: diff --git a/templates/workspaces/base/template_schema.json b/templates/workspaces/base/template_schema.json index 2ee913d0c9..d1f554207a 100644 --- a/templates/workspaces/base/template_schema.json +++ b/templates/workspaces/base/template_schema.json @@ -77,7 +77,7 @@ "enable_backup": { "type": "boolean", "title": "Enable Backup", - "description": "Enable backups for the workspace. This covers any VMs deployed, and the workspace file share", + "description": "Enable backups for the workspace. Workspace services must support this feature.", "default": true, "updateable": true } diff --git a/templates/workspaces/base/terraform/network/providers.tf b/templates/workspaces/base/terraform/network/providers.tf index e0bf9b3bf2..52c3c0eea2 100644 --- a/templates/workspaces/base/terraform/network/providers.tf +++ b/templates/workspaces/base/terraform/network/providers.tf @@ -7,3 +7,12 @@ terraform { } } } + +provider "azurerm" { + features { + recovery_service { + vm_backup_stop_protection_and_retain_data_on_destroy = false + purge_protected_items_from_vault_on_destroy = true + } + } +} diff --git a/templates/workspaces/base/terraform/outputs.tf b/templates/workspaces/base/terraform/outputs.tf index 691751cbfa..223f2ea3b0 100644 --- a/templates/workspaces/base/terraform/outputs.tf +++ b/templates/workspaces/base/terraform/outputs.tf @@ -30,14 +30,13 @@ output "scope_id" { } output "backup_vault_name" { - value = var.enable_backup ? module.backup[0].backup_vault_name : var.backup_vault_name + value = var.enable_backup ? module.backup[0].backup_vault_name : "" } output "backup_vault_vm_backup_policy_name" { - value = var.enable_backup ? module.backup[0].backup_vault_vm_backup_policy_name : var.backup_vault_vm_backup_policy_name + value = var.enable_backup ? module.backup[0].backup_vault_vm_backup_policy_name : "" } output "backup_vault_fileshare_backup_policy_name" { - value = var.enable_backup ? module.backup[0].backup_vault_fileshare_backup_policy_name : var.backup_vault_fileshare_backup_policy_name + value = var.enable_backup ? module.backup[0].backup_vault_fileshare_backup_policy_name : "" } - diff --git a/templates/workspaces/base/terraform/providers.tf b/templates/workspaces/base/terraform/providers.tf index bb19c1d77b..59003f4bae 100644 --- a/templates/workspaces/base/terraform/providers.tf +++ b/templates/workspaces/base/terraform/providers.tf @@ -31,10 +31,6 @@ provider "azurerm" { recover_soft_deleted_certificates = true recover_soft_deleted_keys = true } - recovery_service { - vm_backup_stop_protection_and_retain_data_on_destroy = false - purge_protected_items_from_vault_on_destroy = true - } } storage_use_azuread = true } diff --git a/templates/workspaces/base/terraform/variables.tf b/templates/workspaces/base/terraform/variables.tf index 545c58d04c..cfb34b2181 100644 --- a/templates/workspaces/base/terraform/variables.tf +++ b/templates/workspaces/base/terraform/variables.tf @@ -75,7 +75,7 @@ variable "auth_client_secret" { type = string description = "Used to authenticate into the AAD Tenant to create the AAD App" } -variable "enable_backup"{ +variable "enable_backup" { type = bool default = true description = "Enable backups for the workspace" @@ -144,21 +144,3 @@ variable "storage_account_redundancy" { default = "GRS" description = "The redundancy option for the storage account in the workspace: GRS (Geo-Redundant Storage) or ZRS (Zone-Redundant Storage)." } - -variable "backup_vault_name" { - type = string - default = "" - description = "Name of the backup vault" -} - -variable "backup_vault_vm_backup_policy_name" { - type = string - default = "" - description = "Name of the backup policy for VMs" -} - -variable "backup_vault_fileshare_backup_policy_name" { - type = string - default = "" - description = "Name of the backup policy for File Shares" -} From b8223ec3756b7883e21939408babfad5fab6b6d8 Mon Sep 17 00:00:00 2001 From: Marcus Robinson Date: Thu, 20 Feb 2025 19:21:02 +0000 Subject: [PATCH 10/11] disable soft delete --- templates/workspaces/base/porter.yaml | 2 +- .../base/terraform/backup/backup.tf | 38 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index 43ad35da60..333f597538 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-workspace-base -version: 2.0.15 +version: 2.0.16 description: "A base Azure TRE workspace" dockerfile: Dockerfile.tmpl registry: azuretre diff --git a/templates/workspaces/base/terraform/backup/backup.tf b/templates/workspaces/base/terraform/backup/backup.tf index 04e3872f7e..22e5231e89 100644 --- a/templates/workspaces/base/terraform/backup/backup.tf +++ b/templates/workspaces/base/terraform/backup/backup.tf @@ -4,7 +4,7 @@ resource "azurerm_recovery_services_vault" "vault" { location = var.location resource_group_name = var.resource_group_name sku = "Standard" - soft_delete_enabled = true + soft_delete_enabled = false storage_mode_type = "ZoneRedundant" # Possible values are "GeoRedundant", "LocallyRedundant" and "ZoneRedundant". Defaults to "GeoRedundant". tags = var.tre_workspace_tags @@ -18,7 +18,7 @@ resource "azurerm_recovery_services_vault" "vault" { dynamic "encryption" { for_each = var.enable_cmk_encryption ? [1] : [] - content{ + content { key_id = azurerm_key_vault_key.encryption_key[0].versionless_id infrastructure_encryption_enabled = true user_assigned_identity_id = azurerm_user_assigned_identity.encryption_identity[0].id @@ -53,16 +53,16 @@ resource "azurerm_backup_policy_vm" "vm_policy" { } retention_monthly { - count = 12 - weekdays = ["Monday"] - weeks = ["First"] + count = 12 + weekdays = ["Monday"] + weeks = ["First"] } retention_yearly { - count = 2 - months = ["December"] + count = 2 + months = ["December"] weekdays = ["Sunday"] - weeks = ["Last"] + weeks = ["Last"] } depends_on = [ @@ -94,16 +94,16 @@ resource "azurerm_backup_policy_file_share" "file_share_policy" { } retention_monthly { - count = 12 - weekdays = ["Monday"] - weeks = ["First"] + count = 12 + weekdays = ["Monday"] + weeks = ["First"] } retention_yearly { - count = 2 - months = ["December"] + count = 2 + months = ["December"] weekdays = ["Sunday"] - weeks = ["Last"] + weeks = ["Last"] } depends_on = [ @@ -123,11 +123,11 @@ resource "azurerm_backup_container_storage_account" "storage_account" { } resource "azurerm_backup_protected_file_share" "file_share" { - resource_group_name = var.resource_group_name - recovery_vault_name = azurerm_recovery_services_vault.vault.name - source_storage_account_id = var.azurerm_storage_account_id - source_file_share_name = var.shared_storage_name - backup_policy_id = azurerm_backup_policy_file_share.file_share_policy.id + resource_group_name = var.resource_group_name + recovery_vault_name = azurerm_recovery_services_vault.vault.name + source_storage_account_id = var.azurerm_storage_account_id + source_file_share_name = var.shared_storage_name + backup_policy_id = azurerm_backup_policy_file_share.file_share_policy.id depends_on = [ azurerm_backup_policy_file_share.file_share_policy, From c2379417505c51e11665c9f1a672024c8f21db70 Mon Sep 17 00:00:00 2001 From: james-annages <45330941+james-annages@users.noreply.github.com> Date: Thu, 20 Feb 2025 20:21:25 +0000 Subject: [PATCH 11/11] bump version to 2.0.17 in porter.yaml --- templates/workspaces/base/porter.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/workspaces/base/porter.yaml b/templates/workspaces/base/porter.yaml index 333f597538..c8d907ddf2 100644 --- a/templates/workspaces/base/porter.yaml +++ b/templates/workspaces/base/porter.yaml @@ -1,7 +1,7 @@ --- schemaVersion: 1.0.0 name: tre-workspace-base -version: 2.0.16 +version: 2.0.17 description: "A base Azure TRE workspace" dockerfile: Dockerfile.tmpl registry: azuretre