项目作者: soderlind

项目描述 :
Moving multiple domains to Azure Front Door
高级语言: Shell
项目地址: git://github.com/soderlind/move-domains-to-afd.git
创建时间: 2021-02-04T16:21:48Z
项目社区:https://github.com/soderlind/move-domains-to-afd

开源协议:

下载


Moving multiple domains to Azure Front Door

I manage a WordPress Multisite and when migrating it to Azure, I had to move more than 100 domains.

NOTE: I highly recommend that you test the scripts below on your test platform in Azure before you do it in production, and please read the disclaimer at the end of this document.

Prerequisite

Tools

Either use Azure Shell (bash)

Or install

  • Azure CLI, aka az
  • jq, a lightweight and flexible command-line JSON processor.

Add the Azure Front Door CLI extension:

az extension add --name front-door

Domains must be moved to Azure DNS.

Azure Front Door only support apex (naked) domains when they are in Azure DNS.

I moved the domains using the following script

  • Add 3 sub folders, ok, failed and zones. In zones, add a zone file per domain in the format domain.tld. If the import fails for a zone file, it lands in failed. Fix the file and put it back into zones and run the script again.
  • Log in to Azure: az login
  • Run the script.
  1. #!/usr/bin/bash
  2. RG="MY-DNS-RG"
  3. zone_dir="./zones"
  4. # for each zone file, read zone file from folder
  5. for zone_file in "$zone_dir"/*
  6. do
  7. ZONE=` basename "$zone_file"`
  8. printf "Importing $ZONE\n"
  9. az network dns zone import --resource-group $RG --name $ZONE --file-name $zone_file
  10. if [ $? -eq 0 ]
  11. then
  12. mv $zone_file ok/.
  13. else
  14. mv $zone_file failed/.
  15. fi
  16. done
  • After you’ve created the zones in Azure DNS, get the nameservers per zone and tell the registrar to change them.

The az command below will create a csv-file, with zone and nameservers per line.

  1. az network dns zone list --resource-group MY-DNS-RG --output json | jq -r '[.[] | {zone: .name, nameservers: .nameServers[]}] | map({zone,nameservers}) | (first | keys_unsorted) as $keys | map([to_entries[] | .value]) as $rows | $keys,$rows[] | @csv' > zones-with-nameservers.csv

Certificates in Azure Key Vault

Azure Front Door (AFD) doesn’t support AFD managed certificates for the apex (root) domain :confused:, so you must bring your own certificates. I use Key Vault Acmebot and its bulk add form to create Let’s Encrypt certificates.

NOTE: The Let’s Encrypt SAN certificate doesn’t support more than 100 domains, so don’t add more at a time. I suggest you add 50 domains at a time.

Key Vault Acmebot, Azure Key Vault and Azure Front Door access policies

After installing Key Vault Acmebot, you need to setup the right permissions for Front Door to access your key vault:

  • Enable App Service Authentication

  • Register Azure Front Door Service as an app in your Azure Active Directory (AAD) via PowerShell using this command:
    New-AzADServicePrincipal -ApplicationId "ad0e1c7e-6d38-4ba4-9efd-0bc77ba9f037".

  • Grant Azure Front Door Service the permission to access the secrets in your Key vault. Go to “Access policies” from your Key vault to add a new policy, then grant “Microsoft.Azure.Frontdoor” service principal a “get-secret” permission.

    In your Azure Key Vault Access Policies set the following secret and certificate permissions:

    • Microsoft.Azure.Frontdoor (APPLICATION)
      • Secret Permissions: Get
      • Certificate Permissions: Get
    • The Function App created when you installed keyvault-acmebot (APPLICATION):
      • Certificate Permissions: Get, List, Update, Create
    • Your user (USER)
      • Secret Permissions: Get, List
      • Certificate Permissions: Get, List

Add domains to Azure Front Door

With the prerequisites in place, you’re ready to add the domains to Azure Front Door.

NOTE:

  • I assume Azure Front Door is up and running, and that you have created your routing rules.
  • Only domains with a certificate in your key vault will be added.

Config

I use these variables, you have to replace them with your own.

  1. RG="MY-AFD-RG"
  2. DNS_RG="MY-DNS-RG"
  3. AFD="MY-FD"
  4. AFD_HOST="MY-FD.azurefd.net"
  5. AFD_ROUTINGRULES="$AFD-routingrule httptohttps"
  6. KV="MY-KV"
  7. OUTPUT="json" # Change to "none" to get less output
  8. # The variable below are set by the script.
  9. AFD_ID=$(az network front-door show --resource-group $RG --name $AFD --query id -o tsv)
  10. KV_ID=$(az keyvault list --resource-group $RG | jq -r '[.[].id]|join("")')
  11. OLD_FRONTENDS=$(az network front-door frontend-endpoint list --resource-group $RG --front-door-name $AFD | jq -r '[.[].name]|join(" ")' )
  12. DNS_ZONES=$(az network dns zone list --resource-group $DNS_RG --query '[].name' | jq -r '.|join(" ")')

Point the domain to the Azure Front Door

The apex domain (@) must be aliased and pointed to the Azure Front Door. To verify ownership of the domain, a afdverify CNAME must be added. If the host/subdomain previously had an A record and pointed to an IP address, it must be changed to a CNAME pointing to the front door.

  1. echo -e "\nUPDATING AZURE DNS"
  2. SECRET_NAMES=$(az keyvault certificate list --vault-name $KV | jq -r '[.[].name]|join(" ")')
  3. for SECRET_NAME in $SECRET_NAMES; do
  4. CUSTOMDOMAINS=$(az keyvault certificate show --vault-name $KV --name $SECRET_NAME | jq -r '.. | objects | select(.subjectAlternativeNames).subjectAlternativeNames.dnsNames |join(" ")')
  5. for DOMAIN in $CUSTOMDOMAINS; do
  6. echo -e "\nUpdating $DOMAIN"
  7. ZONE=$(echo $DOMAIN | rev | cut -d. -f1-2 | rev) # NOTE, I assume domain.tld, if you have domain.co.tld you have to change this.
  8. # If the domain in the certificate is in our Azure DNS, modify it.
  9. if [[ $DNS_ZONES =~ (^|[[:space:]])$ZONE($|[[:space:]]) ]]; then
  10. if [[ $ZONE != $DOMAIN ]]; then
  11. HOST=$(echo $DOMAIN | cut -d. -f1)
  12. echo -e "\tHOST: finding record type for $HOST in zone $ZONE"
  13. record_type=$(az network dns record-set list --resource-group $DNS_RG --zone-name $ZONE --query "[?name=='$HOST'].type" | jq -r '.|join("")|split("/")[-1]' )
  14. echo -e "\tRecord type: $record_type"
  15. if [[ "A" == $record_type ]]; then
  16. echo -e "\tDELETE A-record"
  17. az network dns record-set a delete --resource-group $DNS_RG --zone-name $ZONE --name $HOST --yes --output $OUTPUT
  18. fi
  19. echo -e "\tCreate CNAME $HOST -> $AFD_HOST"
  20. az network dns record-set cname set-record --resource-group $DNS_RG --zone-name $ZONE --record-set-name $HOST --cname $AFD_HOST --output $OUTPUT
  21. else
  22. echo -e "\tpoint @ to $AFD_HOST"
  23. az network dns record-set a update --resource-group $DNS_RG --zone-name $ZONE --name "@" --target-resource $AFD_ID --output $OUTPUT
  24. echo -e "\tAdd CNAME afdverify -> afdverify.$AFD_HOST"
  25. az network dns record-set cname set-record --resource-group $DNS_RG --zone-name $ZONE --record-set-name "afdverify" --cname "afdverify.${AFD_HOST}" --output $OUTPUT
  26. fi
  27. fi
  28. done
  29. done

Add the domain to Azure Front Door and enable HTTPS for the domain

In the keyvault, find the certificates and the domains in each certificate. Add the domain to the Azure Front Door and then attache the certificate to the domain, i.e. enable HTTPS.

  1. echo -e "\nADDING DOMAINS TO AZURE FRONT DOOR"
  2. SECRET_NAMES=$(az keyvault certificate list --vault-name $KV | jq -r '[.[].name]|join(" ")')
  3. for SECRET_NAME in $SECRET_NAMES; do
  4. DOMAINS_WITH_CERTS=$(az keyvault certificate show --vault-name $KV --name $SECRET_NAME | jq -r '.. | objects | select(.subjectAlternativeNames).subjectAlternativeNames.dnsNames |join(" ")')
  5. SECRET_ID=$(az keyvault certificate show --vault-name $KV --name $SECRET_NAME |jq -r '[.sid]|join("")|split("/")[-1]')
  6. for DOMAIN_WITH_CERT in $DOMAINS_WITH_CERTS; do
  7. is_validated_domain=$(az network front-door check-custom-domain --resource-group $RG --name $AFD --host-name $DOMAIN_WITH_CERT --query customDomainValidated)
  8. if [[ "true" == $is_validated_domain ]]; then
  9. FRONTENDPOINT="$(echo $DOMAIN_WITH_CERT | tr "." "-")-frontend-endpoint"
  10. if [[ ! $OLD_FRONTENDS =~ (^|[[:space:]])$FRONTENDPOINT($|[[:space:]]) ]]; then
  11. echo -e "\tAdding domain $DOMAIN_WITH_CERT to Front Door\n"
  12. az network front-door frontend-endpoint create --resource-group $RG --front-door-name $AFD --name $FRONTENDPOINT --host-name $DOMAIN_WITH_CERT --output $OUTPUT
  13. az network front-door frontend-endpoint enable-https --resource-group $RG --front-door-name $AFD --name $FRONTENDPOINT --vault-id $KV_ID --certificate-source AzureKeyVault --secret-name $SECRET_NAME --secret-version $SECRET_ID --output $OUTPUT
  14. else
  15. echo -e "\tDomain $DOMAIN_WITH_CERT with frontend endpoit $FRONTENDPOINT allreary exists in $AFD\n"
  16. fi
  17. fi
  18. done
  19. done

Add routing rules to Azure Front Door

There’s no command to append a rule to a Azure Front Door, so we get all front-ends, including the new ones and update the routing rules.

  1. echo -e "\nUPDATING AZURE FRONT DOOR ROUTING RULES"
  2. AFD_FRONTENDS=$(az network front-door frontend-endpoint list --resource-group $RG --front-door-name $AFD | jq -r '[.[].name]|join(" ")' )
  3. for RULE in $AFD_ROUTINGRULES; do
  4. echo -e "\tAdding ALL endpoints/domains to rule: $RULE"
  5. az network front-door routing-rule update --resource-group $RG --front-door-name $AFD --name $RULE --frontend-endpoints $AFD_FRONTENDS --output $OUTPUT
  6. done

Scripts

The shell script examples above, are from

move-domains-to-afd.sh is copyright 2021 Per Soderlind

move-domains-to-afd.sh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

move-domains-to-afd.sh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with the Extension. If not, see http://www.gnu.org/licenses/.