@@ -72,90 +72,95 @@ script_dir=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
7272source " $script_dir /kv_add_network_exception.sh"
7373
7474group_show_result=$( az group show --name " ${core_tre_rg} " > /dev/null 2>&1 ; echo $? )
75- if [[ " $group_show_result " != " 0" ]]; then
76- echo " Resource group ${core_tre_rg} not found - skipping destroy"
75+ # We resolve matching groups up front so we can skip early when none exist,
76+ # and then reuse the same list for deletion at the end of the script.
77+ matching_resource_groups=$( az group list --query " [?starts_with(name, '${core_tre_rg} ')].[name]" -o tsv | sort -r)
78+ if [[ -z " ${matching_resource_groups} " ]]; then
79+ echo " No resource groups found with prefix ${core_tre_rg} - skipping destroy"
7780 exit 0
7881fi
7982
80- locks= $( az group lock list -g " ${core_tre_rg} " --query [].id -o tsv | tr -d \' )
81- if [ -n " ${locks :- } " ]
82- then
83- for lock in $locks
84- do
85- echo " Deleting lock ${lock} ..."
86- az resource lock delete --ids " ${lock} "
87- done
88- fi
83+ if [[ " $group_show_result " == " 0 " ]] ; then
84+ locks= $( az group lock list -g " ${core_tre_rg } " --query [].id -o tsv | tr -d \' )
85+ if [ -n " ${locks :- } " ] ; then
86+ for lock in $locks
87+ do
88+ echo " Deleting lock ${lock} ..."
89+ az resource lock delete --ids " ${lock} "
90+ done
91+ fi
8992
90- delete_resource_diagnostic () {
91- # the command will return an error if the resource doesn't support this setting, so need to suppress it.
92- # first line works on azcli 2.37, second line works on azcli 2.42
93- { az monitor diagnostic-settings list --resource " $1 " --query " value[].name" -o tsv 2> /dev/null \
94- && az monitor diagnostic-settings list --resource " $1 " --query " [].name" -o tsv 2> /dev/null ; } |
95- while read -r diag_name; do
96- echo " Deleting ${diag_name} on $1 "
97- az monitor diagnostic-settings delete --resource " $1 " --name " ${diag_name} "
98- done
99- }
100- export -f delete_resource_diagnostic
101-
102- echo " Looking for diagnostic settings..."
103- # sometimes, diagnostic settings aren't deleted with the resource group. we need to manually do that,
104- # and unfortunately, there's no easy way to list all that are present.
105- # using xargs to run in parallel.
106- az resource list --resource-group " ${core_tre_rg} " --query ' [].[id]' -o tsv | xargs -P 10 -I {} bash -c ' delete_resource_diagnostic "{}"'
107- tre_id=${core_tre_rg# " rg-" }
108-
109- # purge keyvault if possible (makes it possible to reuse the same tre_id later)
110- # this has to be done before we delete the resource group since we might not wait for it to complete
111- keyvault_name=" kv-${tre_id} "
112- keyvault=$( az keyvault show --name " ${keyvault_name} " --resource-group " ${core_tre_rg} " -o json || echo 0)
113- if [ " ${keyvault} " != " 0" ]; then
114- secrets=$( az keyvault secret list --vault-name " ${keyvault_name} " -o json | jq -r ' .[].id' )
115- for secret_id in ${secrets} ; do
116- echo " Deleting ${secret_id} "
117- az keyvault secret delete --id " ${secret_id} "
118- done
93+ delete_resource_diagnostic () {
94+ # the command will return an error if the resource doesn't support this setting, so need to suppress it.
95+ # first line works on azcli 2.37, second line works on azcli 2.42
96+ { az monitor diagnostic-settings list --resource " $1 " --query " value[].name" -o tsv 2> /dev/null \
97+ && az monitor diagnostic-settings list --resource " $1 " --query " [].name" -o tsv 2> /dev/null ; } |
98+ while read -r diag_name; do
99+ echo " Deleting ${diag_name} on $1 "
100+ az monitor diagnostic-settings delete --resource " $1 " --name " ${diag_name} "
101+ done
102+ }
103+ export -f delete_resource_diagnostic
104+
105+ echo " Looking for diagnostic settings..."
106+ # sometimes, diagnostic settings aren't deleted with the resource group. we need to manually do that,
107+ # and unfortunately, there's no easy way to list all that are present.
108+ # using xargs to run in parallel.
109+ az resource list --resource-group " ${core_tre_rg} " --query ' [].[id]' -o tsv | xargs -P 10 -I {} bash -c ' delete_resource_diagnostic "{}"'
110+ tre_id=${core_tre_rg# " rg-" }
111+
112+ # purge keyvault if possible (makes it possible to reuse the same tre_id later)
113+ # this has to be done before we delete the resource group since we might not wait for it to complete
114+ keyvault_name=" kv-${tre_id} "
115+ keyvault=$( az keyvault show --name " ${keyvault_name} " --resource-group " ${core_tre_rg} " -o json || echo 0)
116+ if [ " ${keyvault} " != " 0" ]; then
117+ secrets=$( az keyvault secret list --vault-name " ${keyvault_name} " -o json | jq -r ' .[].id' )
118+ for secret_id in ${secrets} ; do
119+ echo " Deleting ${secret_id} "
120+ az keyvault secret delete --id " ${secret_id} "
121+ done
119122
120- keys=$( az keyvault key list --vault-name " ${keyvault_name} " -o json | jq -r ' .[].id' )
121- for key_id in ${keys} ; do
122- echo " Deleting ${key_id} "
123- az keyvault key delete --id " ${key_id} "
124- done
123+ keys=$( az keyvault key list --vault-name " ${keyvault_name} " -o json | jq -r ' .[].id' )
124+ for key_id in ${keys} ; do
125+ echo " Deleting ${key_id} "
126+ az keyvault key delete --id " ${key_id} "
127+ done
125128
126- certificates=$( az keyvault certificate list --vault-name " ${keyvault_name} " -o json | jq -r ' .[].id' )
127- for certificate_id in ${certificates} ; do
128- echo " Deleting ${certificate_id} "
129- az keyvault certificate delete --id " ${certificate_id} "
130- done
129+ certificates=$( az keyvault certificate list --vault-name " ${keyvault_name} " -o json | jq -r ' .[].id' )
130+ for certificate_id in ${certificates} ; do
131+ echo " Deleting ${certificate_id} "
132+ az keyvault certificate delete --id " ${certificate_id} "
133+ done
131134
132- echo " Removing access policies so if the vault is recovered there are not there"
133- access_policies=$( echo " $keyvault " | jq -r ' .properties.accessPolicies[].objectId' )
134- for access_policy_id in ${access_policies} ; do
135- echo " Attempting to delete access policy ${access_policy_id} "
136- az keyvault delete-policy --name " ${keyvault_name} " --resource-group " ${core_tre_rg} " --object-id " ${access_policy_id} " || echo " Not deleting access policy for ${access_policy_id} ."
137- done
135+ echo " Removing access policies so if the vault is recovered they are not restored"
136+ access_policies=$( echo " $keyvault " | jq -r ' .properties.accessPolicies[].objectId' )
137+ for access_policy_id in ${access_policies} ; do
138+ echo " Attempting to delete access policy ${access_policy_id} "
139+ az keyvault delete-policy --name " ${keyvault_name} " --resource-group " ${core_tre_rg} " --object-id " ${access_policy_id} " || echo " Not deleting access policy for ${access_policy_id} ."
140+ done
141+ fi
138142
139- fi
143+ # Delete the vault if purge protection is not on.
144+ if [[ $( az keyvault list --resource-group " ${core_tre_rg} " --query " [?properties.enablePurgeProtection==` ` null` ` ] | length (@)" -o tsv) != 0 ]]; then
145+ echo " Deleting keyvault: ${keyvault_name} "
146+ az keyvault delete --name " ${keyvault_name} " --resource-group " ${core_tre_rg} "
140147
141- # Delete the vault if purge protection is not on.
142- if [[ $( az keyvault list --resource-group " ${core_tre_rg} " --query " [?properties.enablePurgeProtection==` ` null` ` ] | length (@)" -o tsv) != 0 ]]; then
143- echo " Deleting keyvault: ${keyvault_name} "
144- az keyvault delete --name " ${keyvault_name} " --resource-group " ${core_tre_rg} "
148+ echo " Purging keyvault: ${keyvault_name} "
149+ az keyvault purge --name " ${keyvault_name} " ${no_wait_option}
150+ else
151+ echo " Resource group ${core_tre_rg} doesn't have a keyvault without purge protection."
152+ fi
145153
146- echo " Purging keyvault: ${keyvault_name} "
147- az keyvault purge --name " ${keyvault_name} " ${no_wait_option}
154+ # linked storage accounts don't get deleted with the workspace
155+ workspace_name=" log-${tre_id} "
156+ workspace=$( az monitor log-analytics workspace show --workspace-name " ${workspace_name} " --resource-group " ${core_tre_rg} " || echo 0)
157+ if [ " ${workspace} " != " 0" ]; then
158+ echo " Deleting Linked Storage accounts if present..."
159+ az monitor log-analytics workspace linked-storage list -g " ${core_tre_rg} " --workspace-name " ${workspace_name} " -o tsv --query ' [].id' \
160+ | xargs -P 10 -I {} az rest --method delete --uri " {}?api-version=2020-08-01"
161+ fi
148162else
149- echo " Resource group ${core_tre_rg} doesn't have a keyvault without purge protection."
150- fi
151-
152- # linked storage accounts don't get deleted with the workspace
153- workspace_name=" log-${tre_id} "
154- workspace=$( az monitor log-analytics workspace show --workspace-name " ${workspace_name} " --resource-group " ${core_tre_rg} " || echo 0)
155- if [ " ${workspace} " != " 0" ]; then
156- echo " Deleting Linked Storage accounts if present..."
157- az monitor log-analytics workspace linked-storage list -g " ${core_tre_rg} " --workspace-name " ${workspace_name} " -o tsv --query ' [].id' \
158- | xargs -P 10 -I {} az rest --method delete --uri " {}?api-version=2020-08-01"
163+ echo " Skipping core resource group cleanup (locks, diagnostics, keyvault and log analytics linked storage) because ${core_tre_rg} was not found."
159164fi
160165
161166# delete container repositories individually otherwise defender doesn't purge image scans
@@ -183,7 +188,7 @@ function purge_container_repositories() {
183188# this will find the mgmt, core resource groups as well as any workspace ones
184189# we are reverse-sorting to first delete the workspace groups (might not be
185190# good enough because we use no-wait sometimes)
186- az group list --query " [?starts_with(name, ' ${core_tre_rg} ')].[name] " -o tsv | sort -r |
191+ echo " ${matching_resource_groups} " |
187192while read -r rg_item; do
188193 purge_container_repositories " $rg_item "
189194
0 commit comments