Skip to content

Instantly share code, notes, and snippets.

@soderlind
Last active December 19, 2023 03:21
Show Gist options
  • Save soderlind/68e31c0b1df2329574500edb7fdcd214 to your computer and use it in GitHub Desktop.
Save soderlind/68e31c0b1df2329574500edb7fdcd214 to your computer and use it in GitHub Desktop.
Me talking with Copilot Chat

@soderlind: I need a bash script that read a list of domains from disk and use az cli to remove the domains from azure front door. I have several azure front doors in the resource group.

GitHub Copilot: Here's a step-by-step plan for the bash script:

  1. Define the script shebang to specify that the script should be run using bash.
  2. Read the file line by line using a while loop.
  3. Inside the loop, use the az network front-door frontend-endpoint delete command to delete the domain from each Azure Front Door in the resource group.
  4. The command requires the names of the resource group, the Front Door, and the endpoint (domain). You'll need to loop over each Front Door in the resource group.
  5. To get the list of Front Doors, use the az network front-door list command with the resource group name.
  6. Parse the output of the list command to extract the names of the Front Doors.
  7. Use a nested loop to delete the domain from each Front Door.

Here's the bash script:

#!/bin/bash

# Define your resource group
resource_group="my-resource-group"

# Read the domains file
while IFS= read -r domain
do
  # Get the list of Front Doors in the resource group
  front_doors=$(az network front-door list --resource-group "$resource_group" --query "[].name" -o tsv)

  # Loop over each Front Door
  for front_door in $front_doors
  do
    # Delete the domain from the Front Door
    az network front-door frontend-endpoint delete --resource-group "$resource_group" --front-door-name "$front_door" --name "$domain"
  done
done < "domains.txt"

Replace "my-resource-group" with the name of your resource group and "domains.txt" with the path to your file containing the list of domains. This script assumes that the domain names are the same as the endpoint names in Azure Front Door. If that's not the case, you'll need to adjust the script accordingly.

@soderlind: the dns record for the domain should be removed from azure dns before deleting the domain from azure front door. azure dns has its own resource group

GitHub Copilot: To remove the DNS record for the domain from Azure DNS before deleting the domain from Azure Front Door, you can modify the bash script as follows:

  1. Before deleting the domain from the Front Door, use the az network dns record-set a delete command to delete the A record for the domain from the DNS zone.
  2. The command requires the names of the resource group, the DNS zone, and the record set (domain). You'll need to specify these as variables at the start of the script.

Here's the updated bash script:

#!/bin/bash

# Define your resource groups and DNS zone
front_door_resource_group="my-front-door-resource-group"
dns_resource_group="my-dns-resource-group"
dns_zone="my-dns-zone"

# Read the domains file
while IFS= read -r domain
do
  # Delete the A record for the domain from the DNS zone
  az network dns record-set a delete --resource-group "$dns_resource_group" --zone-name "$dns_zone" --name "$domain" --yes

  # Get the list of Front Doors in the front door resource group
  front_doors=$(az network front-door list --resource-group "$front_door_resource_group" --query "[].name" -o tsv)

  # Loop over each Front Door
  for front_door in $front_doors
  do
    # Delete the domain from the Front Door
    az network front-door frontend-endpoint delete --resource-group "$front_door_resource_group" --front-door-name "$front_door" --name "$domain"
  done
done < "domains.txt"

Replace "my-front-door-resource-group", "my-dns-resource-group", and "my-dns-zone" with the names of your resource groups and DNS zone, and "domains.txt" with the path to your file containing the list of domains. This script assumes that the domain names are the same as the endpoint names in Azure Front Door and the record set names in Azure DNS. If that's not the case, you'll need to adjust the script accordingly.

@soderlind: the zone will differ from domain to domain, it's the same as the domain

GitHub Copilot: If the DNS zone is the same as the domain, you can modify the bash script to use the domain variable as the DNS zone. Here's the updated bash script:

#!/bin/bash

# Define your resource groups
front_door_resource_group="my-front-door-resource-group"
dns_resource_group="my-dns-resource-group"

# Read the domains file
while IFS= read -r domain
do
  # Delete the A record for the domain from the DNS zone
  az network dns record-set a delete --resource-group "$dns_resource_group" --zone-name "$domain" --name "@" --yes

  # Get the list of Front Doors in the front door resource group
  front_doors=$(az network front-door list --resource-group "$front_door_resource_group" --query "[].name" -o tsv)

  # Loop over each Front Door
  for front_door in $front_doors
  do
    # Delete the domain from the Front Door
    az network front-door frontend-endpoint delete --resource-group "$front_door_resource_group" --front-door-name "$front_door" --name "$domain"
  done
done < "domains.txt"

Replace "my-front-door-resource-group" and "my-dns-resource-group" with the names of your resource groups, and "domains.txt" with the path to your file containing the list of domains. This script assumes that the domain names are the same as the endpoint names in Azure Front Door and the DNS zones in Azure DNS. The "@" symbol is used as the record set name to represent the root domain. If that's not the case, you'll need to adjust the script accordingly.

@soderlind: add dry run to the script

GitHub Copilot: To add a dry run option to the script, you can add a command-line argument that, when present, causes the script to print the commands it would run without actually running them. Here's the updated bash script:

#!/bin/bash

# Define your resource groups
front_door_resource_group="my-front-door-resource-group"
dns_resource_group="my-dns-resource-group"

# Check if the first argument is --dry-run
if [ "$1" == "--dry-run" ]; then
  dry_run=true
else
  dry_run=false
fi

# Read the domains file
while IFS= read -r domain
do
  # Print or run the command to delete the A record for the domain from the DNS zone
  cmd="az network dns record-set a delete --resource-group \"$dns_resource_group\" --zone-name \"$domain\" --name \"@\" --yes"
  if $dry_run; then
    echo "$cmd"
  else
    eval "$cmd"
  fi

  # Get the list of Front Doors in the front door resource group
  front_doors=$(az network front-door list --resource-group "$front_door_resource_group" --query "[].name" -o tsv)

  # Loop over each Front Door
  for front_door in $front_doors
  do
    # Print or run the command to delete the domain from the Front Door
    cmd="az network front-door frontend-endpoint delete --resource-group \"$front_door_resource_group\" --front-door-name \"$front_door\" --name \"$domain\""
    if $dry_run; then
      echo "$cmd"
    else
      eval "$cmd"
    fi
  done
done < "domains.txt"

Now you can run the script with the --dry-run argument to see the commands it would run:

./script.sh --dry-run

Replace "my-front-door-resource-group" and "my-dns-resource-group" with the names of your resource groups, and "domains.txt" with the path to your file containing the list of domains. This script assumes that the domain names are the same as the endpoint names in Azure Front Door and the DNS zones in Azure DNS. The "@" symbol is used as the record set name to represent the root domain. If that's not the case, you'll need to adjust the script accordingly.

@soderlind: the az cli accept --dry-run as a parameter

I thought the az cli accept --dry-run as a parameter, I stand corrected.

GitHub Copilot: The Azure CLI (az cli) does not natively support a --dry-run option. The --dry-run option is commonly used in other command-line tools to display the operations that would be performed without actually executing them.

However, you can simulate a dry run in your bash script by printing the commands instead of executing them when the --dry-run option is provided, as shown in the previous script example.

If you want to check what a command would do without actually doing it, you can use the --help option to display the command's documentation, which includes a description of what the command does and the options it accepts. For example:

az network dns record-set a delete --help

This will display the help documentation for the az network dns record-set a delete command.

@soderlind: if the domain starts with www it's a cname, also reome the cname from dns

Typos are my specialty ;)

GitHub Copilot: To handle the case where the domain starts with "www" and is a CNAME record, you can add a conditional statement to the bash script to check if the domain starts with "www". If it does, use the az network dns record-set cname delete command to delete the CNAME record. Here's the updated bash script:

#!/bin/bash

# Define your resource groups
front_door_resource_group="my-front-door-resource-group"
dns_resource_group="my-dns-resource-group"

# Check if the first argument is --dry-run
if [ "$1" == "--dry-run" ]; then
  dry_run=true
else
  dry_run=false
fi

# Read the domains file
while IFS= read -r domain
do
  # Check if the domain starts with www
  if [[ $domain == www* ]]; then
    # Print or run the command to delete the CNAME record for the domain from the DNS zone
    cmd="az network dns record-set cname delete --resource-group \"$dns_resource_group\" --zone-name \"${domain#www.}\" --name \"www\" --yes"
  else
    # Print or run the command to delete the A record for the domain from the DNS zone
    cmd="az network dns record-set a delete --resource-group \"$dns_resource_group\" --zone-name \"$domain\" --name \"@\" --yes"
  fi

  if $dry_run; then
    echo "$cmd"
  else
    eval "$cmd"
  fi

  # Get the list of Front Doors in the front door resource group
  front_doors=$(az network front-door list --resource-group "$front_door_resource_group" --query "[].name" -o tsv)

  # Loop over each Front Door
  for front_door in $front_doors
  do
    # Print or run the command to delete the domain from the Front Door
    cmd="az network front-door frontend-endpoint delete --resource-group \"$front_door_resource_group\" --front-door-name \"$front_door\" --name \"$domain\""
    if $dry_run; then
      echo "$cmd"
    else
      eval "$cmd"
    fi
  done
done < "domains.txt"

Replace "my-front-door-resource-group" and "my-dns-resource-group" with the names of your resource groups, and "domains.txt" with the path to your file containing the list of domains. This script assumes that the domain names are the same as the endpoint names in Azure Front Door and the DNS zones in Azure DNS. The "@" symbol is used as the record set name to represent the root domain. If that's not the case, you'll need to adjust the script accordingly.

@soderlind: @workspace /explain selected code

Never used ${domain#www.} before, so I selected the code and asked for an explanation.

GitHub Copilot: The selected line of code is a shell command that is being assigned to the variable cmd. This command is used to delete a CNAME record from a DNS zone in Azure DNS.

Here's a breakdown of the command:

  • az network dns record-set cname delete: This is the Azure CLI command to delete a CNAME record from a DNS zone.
  • --resource-group \"$dns_resource_group\": This option specifies the resource group that contains the DNS zone. The value is taken from the dns_resource_group variable, which should be set to the name of your resource group.
  • --zone-name \"${domain#www.}\": This option specifies the name of the DNS zone. The value is taken from the domain variable, with the leading "www." removed. This is done using the shell parameter expansion ${domain#www.}, which removes the shortest match of "www." from the start of $domain.
  • --name \"www\": This option specifies the name of the record set to delete. In this case, it's "www", which is typically used for CNAME records.
  • --yes: This option confirms that you want to perform the delete operation without being prompted to do so.

This command is wrapped in double quotes and assigned to the cmd variable so it can be printed or executed later in the script. The backslashes before the inner double quotes are used to escape them, so they are included in the command string rather than ending the string.

@soderlind: I'm also using Key Vault Acmebot for certificates, are you able to remove the domain from Key Vault Acmebot?

GitHub Copilot: Key Vault Acmebot does not provide a direct command-line interface or API to remove a domain. However, you can manually remove a domain from Key Vault Acmebot by deleting the corresponding certificate from the Azure Key Vault.

Here's how you can do it using Azure CLI:

az keyvault certificate delete --name "<certificate-name>" --vault-name "<vault-name>"

Replace <certificate-name> with the name of the certificate corresponding to the domain you want to remove, and <vault-name> with the name of your Azure Key Vault.

Please note that you should be careful when deleting certificates, as it could impact any services or applications that are using them. Also, the certificate name usually matches the domain name, but you should verify this in your specific setup.

If you want to automate this in your script, you can add a command similar to the one above, replacing <certificate-name> and <vault-name> with the appropriate variables or values. However, automating this process could be risky if not done correctly, as you could accidentally delete the wrong certificates.

@soderlind: the keyvault is in the same resourcegroup as the azure front doors, remove the certificate from the keyvault. The sertificate name is the same as the domain, but with a - instead of a . Check if the certificate exist. It might start with www

GitHub Copilot: To remove a certificate from the Key Vault, you can use the az keyvault certificate delete command. You can replace the . in the domain name with - to get the certificate name. If the domain starts with "www", you should remove it before forming the certificate name. Here's how you can add this to your script:

#!/bin/bash

# Define your resource groups
front_door_resource_group="my-front-door-resource-group"
dns_resource_group="my-dns-resource-group"
key_vault_name="my-key-vault"

# Check if the first argument is --dry-run
if [ "$1" == "--dry-run" ]; then
  dry_run=true
else
  dry_run=false
fi

# Read the domains file
while IFS= read -r domain
do
  # Form the certificate name by replacing . with - and removing www. if present
  certificate_name=${domain/www./}
  certificate_name=${certificate_name//./-}

  # Check if the certificate exists
  certificate_exists=$(az keyvault certificate show --name "$certificate_name" --vault-name "$key_vault_name" --query "id" -o tsv)

  if [ -n "$certificate_exists" ]; then
    # Print or run the command to delete the certificate from the Key Vault
    cmd="az keyvault certificate delete --name \"$certificate_name\" --vault-name \"$key_vault_name\""
    if $dry_run; then
      echo "$cmd"
    else
      eval "$cmd"
    fi
  fi

  # Check if the domain starts with www
  if [[ $domain == www* ]]; then
    # Print or run the command to delete the CNAME record for the domain from the DNS zone
    cmd="az network dns record-set cname delete --resource-group \"$dns_resource_group\" --zone-name \"${domain#www.}\" --name \"www\" --yes"
  else
    # Print or run the command to delete the A record for the domain from the DNS zone
    cmd="az network dns record-set a delete --resource-group \"$dns_resource_group\" --zone-name \"$domain\" --name \"@\" --yes"
  fi

  if $dry_run; then
    echo "$cmd"
  else
    eval "$cmd"
  fi

  # Get the list of Front Doors in the front door resource group
  front_doors=$(az network front-door list --resource-group "$front_door_resource_group" --query "[].name" -o tsv)

  # Loop over each Front Door
  for front_door in $front_doors
  do
    # Print or run the command to delete the domain from the Front Door
    cmd="az network front-door frontend-endpoint delete --resource-group \"$front_door_resource_group\" --front-door-name \"$front_door\" --name \"$domain\""
    if $dry_run; then
      echo "$cmd"
    else
      eval "$cmd"
    fi
  done
done < "domains.txt"

Replace "my-front-door-resource-group", "my-dns-resource-group", and "my-key-vault" with the names of your resource groups and Key Vault, and "domains.txt" with the path to your file containing the list of domains. This script assumes that the domain names are the same as the endpoint names in Azure Front Door and the DNS zones in Azure DNS. The "@" symbol is used as the record set name to represent the root domain. If that's not the case, you'll need to adjust the script accordingly.

@soderlind: remeber to check if the domain exists in dns

Copilot forgot to check if the domain exists in dns before deleting it.

GitHub Copilot: To check if a domain exists in Azure DNS, you can use the az network dns record-set cname show command for CNAME records. If the domain exists, this command will return details about the record; if it doesn't, the command will return an error. You can capture the output of this command and check if it contains an error to determine whether the domain exists.

Here's how you can modify the selected line of code to check if the domain exists before trying to delete it:

# Form the DNS zone name by removing www. if present
dns_zone_name=${domain#www.}

# Check if the CNAME record exists
cname_exists=$(az network dns record-set cname show --resource-group "$dns_resource_group" --zone-name "$dns_zone_name" --name "www" --query "id" -o tsv 2>/dev/null)

if [ -n "$cname_exists" ]; then
  # Print or run the command to delete the CNAME record for the domain from the DNS zone
  cmd="az network dns record-set cname delete --resource-group \"$dns_resource_group\" --zone-name \"$dns_zone_name\" --name \"www\" --yes"
  if $dry_run; then
    echo "$cmd"
  else
    eval "$cmd"
  fi
fi

This code first checks if the CNAME record exists by running the az network dns record-set cname show command and capturing its output. The 2>/dev/null part redirects stderr to /dev/null, suppressing error messages. If the cname_exists variable is not empty after running the command, that means the CNAME record exists, and the script proceeds to delete it.

@soderlind: for selected code, only delete certificate it removing the domain from dns and azure front door is successful

GitHub Copilot: To ensure that the certificate is only deleted if the domain is successfully removed from both DNS and Azure Front Door, you can use a flag to track whether the deletion operations were successful. If both operations are successful, then you can proceed to delete the certificate.

Here's how you can modify the selected code to implement this:

#!/bin/bash

# Define your resource groups
front_door_resource_group="my-front-door-resource-group"
dns_resource_group="my-dns-resource-group"
key_vault_name="my-key-vault"

# Check if the first argument is --dry-run
if [ "$1" == "--dry-run" ]; then
	dry_run=true
else
	dry_run=false
fi

# Read the domains file
while IFS= read -r domain; do
	# Initialize the flag as true
	domain_deleted=true

	# Check if the domain starts with www
	if [[ $domain == www* ]]; then
		# Check if the CNAME record set exists for the domain in the DNS zone
		if az network dns record-set show --resource-group "$dns_resource_group" --zone-name "${domain#www.}" --name "www" &>/dev/null; then
			# Print or run the command to delete the CNAME record for the domain from the DNS zone
			cmd="az network dns record-set cname delete --resource-group \"$dns_resource_group\" --zone-name \"${domain#www.}\" --name \"www\" --yes"
			if $dry_run; then
				echo "$cmd"
			else
				if ! eval "$cmd"; then
					domain_deleted=false
				fi
			fi
		else
			echo "CNAME record set does not exist for the domain: $domain"
			domain_deleted=false
		fi
	else
		# Check if the A record set exists for the domain in the DNS zone
		if az network dns record-set show --resource-group "$dns_resource_group" --zone-name "$domain" --name "@" &>/dev/null; then
			# Print or run the command to delete the A record for the domain from the DNS zone
			cmd="az network dns record-set a delete --resource-group \"$dns_resource_group\" --zone-name \"$domain\" --name \"@\" --yes"
			if $dry_run; then
				echo "$cmd"
			else
				if ! eval "$cmd"; then
					domain_deleted=false
				fi
			fi
		else
			echo "A record set does not exist for the domain: $domain"
			domain_deleted=false
		fi
	fi

	# Get the list of Front Doors in the front door resource group
	front_doors=$(az network front-door list --resource-group "$front_door_resource_group" --query "[].name" -o tsv)

	# Loop over each Front Door
	for front_door in $front_doors; do
		# Print or run the command to delete the domain from the Front Door
		cmd="az network front-door frontend-endpoint delete --resource-group \"$front_door_resource_group\" --front-door-name \"$front_door\" --name \"$domain\""
		if $dry_run; then
			echo "$cmd"
		else
			if ! eval "$cmd"; then
				domain_deleted=false
			fi
		fi
	done

	certificate_name=${domain//./-}
	certificate_name=${certificate_name/#www-/}

	# Check if the certificate exists
	certificate_exists=$(az keyvault certificate show --name "$certificate_name" --vault-name "$key_vault_name" --query "id" -o tsv)

	if [ -n "$certificate_exists" ] && [ "$domain_deleted" = true ]; then
		# Print or run the command to delete the certificate from the Key Vault
		cmd="az keyvault certificate delete --name \"$certificate_name\" --vault-name \"$key_vault_name\""
		if $dry_run; then
			echo "$cmd"
		else
			eval "$cmd"
		fi
	fi

done <"domains.txt"

In this modified script, a domain_deleted flag is used to track whether the domain deletion operations were successful. If any operation fails (i.e., the eval "$cmd" command returns a non-zero exit status), the flag is set to false. The certificate is only deleted if the domain_deleted flag is true and the certificate exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment