Skip to content

Commit ec2a695

Browse files
author
james-annages
authored
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.
1 parent b416bd7 commit ec2a695

File tree

15 files changed

+505
-2
lines changed

15 files changed

+505
-2
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
set -o pipefail
5+
set -o nounset
6+
7+
# Uncomment for debugging (will show secrets)
8+
# set -o xtrace
9+
10+
function usage() {
11+
cat <<USAGE
12+
Usage: $0 --resource-group some_rg --vault-name some_vault
13+
Options:
14+
--resource-group The name of the Azure Resource Group containing the Recovery Services Vault.
15+
--vault-name The name of the Recovery Services Vault.
16+
Environment Variables:
17+
AZURE_ENVIRONMENT The name of the Azure environment (e.g., AzureCloud, AzureChinaCloud, etc.). Must be set.
18+
USAGE
19+
exit 1
20+
}
21+
22+
# Ensure required commands are available
23+
for cmd in az jq; do
24+
if ! command -v $cmd &> /dev/null; then
25+
echo "Error: $cmd is not installed."
26+
exit 1
27+
fi
28+
done
29+
30+
# Ensure environment variable is set
31+
if [ -z "${AZURE_ENVIRONMENT:-}" ]; then
32+
echo "Error: AZURE_ENVIRONMENT environment variable is not set."
33+
usage
34+
fi
35+
36+
# Ensure arguments are provided
37+
if [ $# -eq 0 ]; then
38+
usage
39+
fi
40+
41+
# Parse arguments
42+
while [ "$1" != "" ]; do
43+
case $1 in
44+
--resource-group)
45+
shift
46+
RESOURCE_GROUP=$1
47+
;;
48+
--vault-name)
49+
shift
50+
VAULT_NAME=$1
51+
;;
52+
*)
53+
echo "Unexpected argument: '$1'"
54+
usage
55+
;;
56+
esac
57+
58+
if [[ -z "$2" ]]; then
59+
break
60+
fi
61+
62+
shift
63+
done
64+
65+
# Ensure required arguments are set
66+
if [ -z "${RESOURCE_GROUP:-}" ] || [ -z "${VAULT_NAME:-}" ]; then
67+
echo "Error: --resource-group and --vault-name are required."
68+
usage
69+
fi
70+
71+
# Set Azure Cloud environment
72+
az cloud set --name "$AZURE_ENVIRONMENT"
73+
74+
# Check if Vault Exists
75+
echo "Checking for Recovery Services Vault: $VAULT_NAME in $RESOURCE_GROUP"
76+
vault_exists=$(az resource show --resource-group "$RESOURCE_GROUP" --name "$VAULT_NAME" --resource-type "Microsoft.RecoveryServices/vaults" --query "id" -o tsv || echo "")
77+
78+
if [ -z "$vault_exists" ]; then
79+
echo "Vault does not exist or is already deleted. Skipping cleanup."
80+
exit 0
81+
fi
82+
83+
# **Disable Soft Delete for the Vault**
84+
echo "Disabling soft delete for Recovery Services Vault..."
85+
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."
86+
87+
# **Verify Soft Delete is Disabled**
88+
soft_delete_status=$(az backup vault backup-properties show --resource-group "$RESOURCE_GROUP" --vault-name "$VAULT_NAME" --query "softDeleteFeatureState" -o tsv)
89+
if [[ "$soft_delete_status" != "Disabled" ]]; then
90+
echo "Error: Soft delete is still enabled. Vault cannot be deleted."
91+
exit 1
92+
fi
93+
94+
# **Get all protected backup items (VMs, File Shares, SQL, etc.)**
95+
echo "Fetching all protected backup items..."
96+
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)
97+
98+
# **Disable protection for each registered backup item**
99+
for row in $(echo "$protected_items" | jq -c '.[]'); do
100+
item_name=$(echo "$row" | jq -r '.name')
101+
container_name=$(echo "$row" | jq -r '.containerName')
102+
item_type=$(echo "$row" | jq -r '.type')
103+
104+
echo "Disabling protection for: $item_name ($item_type)"
105+
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"
106+
done
107+
108+
109+
110+

templates/workspaces/base/parameters.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@
159159
"source": {
160160
"env": "KEY_STORE_ID"
161161
}
162+
},
163+
{
164+
"name": "enable_backup",
165+
"source": {
166+
"env": "ENABLE_BACKUP"
167+
}
168+
},
169+
{
170+
"name": "shared_storage_name",
171+
"source": {
172+
"env": "SHARED_STORAGE_NAME"
173+
}
162174
}
163175
]
164176
}

templates/workspaces/base/porter.yaml

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
schemaVersion: 1.0.0
33
name: tre-workspace-base
4-
version: 1.9.3
4+
version: 2.0.10
55
description: "A base Azure TRE workspace"
66
dockerfile: Dockerfile.tmpl
77
registry: azuretre
@@ -126,6 +126,31 @@ parameters:
126126
type: string
127127
default: "GRS"
128128
description: "The redundancy option for the storage account in the workspace: GRS (Geo-Redundant Storage) or ZRS (Zone-Redundant Storage)."
129+
- name: enable_backup
130+
type: boolean
131+
default: true
132+
description: "Enable backups for the workspace, including the vm's & shared storage."
133+
- name: shared_storage_name
134+
type: string
135+
default: "vm-shared-storage"
136+
description: "The name of the shared storage used for the workspace VMs"
137+
- name: backup_vault_name
138+
type: string
139+
default: ""
140+
description: "The name of the backup vault to use for backups"
141+
- name: backup_vault_vm_backup_policy_name
142+
type: string
143+
default: ""
144+
description: "The name of the backup policy to use for VM backups"
145+
- name: backup_vault_fileshare_backup_policy_name
146+
type: string
147+
default: ""
148+
description: "The name of the backup policy to use for fileshare backups"
149+
- name: workspace_resource_name_suffix
150+
type: string
151+
default: ""
152+
description: "A suffix to append to the workspace resource names"
153+
129154

130155
outputs:
131156
- name: app_role_id_workspace_owner
@@ -158,6 +183,22 @@ outputs:
158183
applyTo:
159184
- install
160185
- upgrade
186+
- name: backup_vault_name
187+
type: string
188+
applyTo:
189+
- install
190+
- upgrade
191+
- name: backup_vault_vm_backup_policy_name
192+
type: string
193+
applyTo:
194+
- install
195+
- upgrade
196+
- name: backup_vault_fileshare_backup_policy_name
197+
type: string
198+
applyTo:
199+
- install
200+
- upgrade
201+
161202

162203
mixins:
163204
- exec
@@ -196,6 +237,10 @@ install:
196237
enable_cmk_encryption: ${ bundle.parameters.enable_cmk_encryption }
197238
key_store_id: ${ bundle.parameters.key_store_id }
198239
storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy }
240+
enable_backup: ${ bundle.parameters.enable_backup }
241+
backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name }
242+
backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name }
243+
backup_vault_name: ${ bundle.parameters.backup_vault_name }
199244
backendConfig:
200245
use_azuread_auth: "true"
201246
use_oidc: "true"
@@ -210,6 +255,9 @@ install:
210255
- name: client_id
211256
- name: scope_id
212257
- name: sp_id
258+
- name: backup_vault_name
259+
- name: backup_vault_vm_backup_policy_name
260+
- name: backup_vault_fileshare_backup_policy_name
213261

214262
upgrade:
215263
- terraform:
@@ -241,6 +289,10 @@ upgrade:
241289
enable_cmk_encryption: ${ bundle.parameters.enable_cmk_encryption }
242290
key_store_id: ${ bundle.parameters.key_store_id }
243291
storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy }
292+
enable_backup: ${ bundle.parameters.enable_backup }
293+
backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name }
294+
backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name }
295+
backup_vault_name: ${ bundle.parameters.backup_vault_name }
244296
backendConfig:
245297
use_azuread_auth: "true"
246298
use_oidc: "true"
@@ -255,6 +307,9 @@ upgrade:
255307
- name: client_id
256308
- name: scope_id
257309
- name: sp_id
310+
- name: backup_vault_name
311+
- name: backup_vault_vm_backup_policy_name
312+
- name: backup_vault_fileshare_backup_policy_name
258313
- az:
259314
description: "Set Azure Cloud Environment"
260315
arguments:
@@ -281,6 +336,30 @@ upgrade:
281336
register-aad-application: '${ bundle.parameters.register_aad_application }'
282337

283338
uninstall:
339+
- az:
340+
description: "Set Azure Cloud Environment"
341+
arguments:
342+
- cloud
343+
- set
344+
flags:
345+
name: ${ bundle.parameters.azure_environment }
346+
- az:
347+
description: "Azure Login"
348+
arguments:
349+
- login
350+
flags:
351+
service-principal: ""
352+
username: '${ bundle.credentials.azure_client_id }'
353+
password: '${ bundle.credentials.azure_client_secret }'
354+
tenant: '${ bundle.credentials.azure_tenant_id }'
355+
allow-no-subscriptions: ""
356+
- exec:
357+
description: "Running Recovery Services Vault Cleanup"
358+
command: ./cleanup_vault.sh
359+
flags:
360+
resource-group: '${ bundle.parameters.workspace_resource_name_suffix }'
361+
vault-name: '${ bundle.parameters.backup_vault_name }'
362+
284363
- terraform:
285364
description: "Tear down workspace"
286365
vars:
@@ -309,10 +388,24 @@ uninstall:
309388
enable_cmk_encryption: ${ bundle.parameters.enable_cmk_encryption }
310389
key_store_id: ${ bundle.parameters.key_store_id }
311390
storage_account_redundancy: ${ bundle.parameters.storage_account_redundancy }
391+
enable_backup: ${ bundle.parameters.enable_backup }
392+
backup_vault_fileshare_backup_policy_name: ${ bundle.parameters.backup_vault_fileshare_backup_policy_name }
393+
backup_vault_vm_backup_policy_name: ${ bundle.parameters.backup_vault_vm_backup_policy_name }
394+
backup_vault_name: ${ bundle.parameters.backup_vault_name }
312395
backendConfig:
313396
use_azuread_auth: "true"
314397
use_oidc: "true"
315398
resource_group_name: ${ bundle.parameters.tfstate_resource_group_name }
316399
storage_account_name: ${ bundle.parameters.tfstate_storage_account_name }
317400
container_name: ${ bundle.parameters.tfstate_container_name }
318401
key: ${ bundle.parameters.tre_id }-ws-${ bundle.parameters.id }
402+
outputs:
403+
- name: app_role_id_workspace_owner
404+
- name: app_role_id_workspace_researcher
405+
- name: app_role_id_workspace_airlock_manager
406+
- name: client_id
407+
- name: scope_id
408+
- name: sp_id
409+
- name: backup_vault_name
410+
- name: backup_vault_vm_backup_policy_name
411+
- name: backup_vault_fileshare_backup_policy_name

templates/workspaces/base/template_schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@
7373
"Manual"
7474
],
7575
"updateable": true
76+
},
77+
"enable_backup": {
78+
"type": "boolean",
79+
"title": "Enable Backup",
80+
"description": "Enable backups for the workspace, including the vm's & shared storage.",
81+
"default": true,
82+
"updateable": true
7683
}
7784
},
7885
"allOf": [
@@ -304,6 +311,7 @@
304311
"create_aad_groups",
305312
"client_id",
306313
"client_secret",
314+
"enable_backup",
307315
"enable_airlock",
308316
"configure_review_vms",
309317
"airlock_review_config",

templates/workspaces/base/terraform/aad/aad.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ resource "azuread_service_principal" "workspace" {
103103

104104
resource "azuread_service_principal_password" "workspace" {
105105
service_principal_id = azuread_service_principal.workspace.object_id
106+
106107
}
107108

108109
resource "azurerm_key_vault_secret" "client_id" {

templates/workspaces/base/terraform/api-permissions.tf

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,16 @@ resource "azurerm_role_assignment" "api_reader" {
2020
role_definition_name = "Reader"
2121
principal_id = data.azurerm_user_assigned_identity.api_id.principal_id
2222
}
23+
24+
# adds the needed permissions to the API to manage the backup and site recovery
25+
resource "azurerm_role_assignment" "backup_contributor" {
26+
scope = azurerm_resource_group.ws.id
27+
role_definition_name = "Backup Contributor"
28+
principal_id = data.azurerm_user_assigned_identity.api_id.principal_id
29+
}
30+
31+
resource "azurerm_role_assignment" "site_recover_contributor" {
32+
scope = azurerm_resource_group.ws.id
33+
role_definition_name = "Site Recovery Contributor"
34+
principal_id = data.azurerm_user_assigned_identity.api_id.principal_id
35+
}

0 commit comments

Comments
 (0)