Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add backups to workspaces. #4374

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions templates/workspaces/base/cleanup_vault.sh
Original file line number Diff line number Diff line change
@@ -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 <<USAGE
Usage: $0 --resource-group some_rg --vault-name some_vault
Options:
--resource-group The name of the Azure Resource Group containing the Recovery Services Vault.
--vault-name The name of the Recovery Services Vault.
Environment Variables:
AZURE_ENVIRONMENT The name of the Azure environment (e.g., AzureCloud, AzureChinaCloud, etc.). Must be set.
USAGE
exit 1
}

# Ensure required commands are available
for cmd in az jq; do
if ! command -v $cmd &> /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




12 changes: 12 additions & 0 deletions templates/workspaces/base/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
]
}
95 changes: 94 additions & 1 deletion templates/workspaces/base/porter.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand All @@ -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:
Expand Down Expand Up @@ -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"
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -309,10 +388,24 @@ 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"
resource_group_name: ${ bundle.parameters.tfstate_resource_group_name }
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
8 changes: 8 additions & 0 deletions templates/workspaces/base/template_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down Expand Up @@ -304,6 +311,7 @@
"create_aad_groups",
"client_id",
"client_secret",
"enable_backup",
"enable_airlock",
"configure_review_vms",
"airlock_review_config",
Expand Down
13 changes: 13 additions & 0 deletions templates/workspaces/base/terraform/api-permissions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Loading