acmesh-official / acme.sh

A pure Unix shell script implementing ACME client protocol
https://acme.sh
GNU General Public License v3.0
39.2k stars 4.96k forks source link

acme.sh Azure DNS does not support Azure Arc endpoints #4567

Open wahidsaleemi opened 1 year ago

wahidsaleemi commented 1 year ago

When using the Managed Identity option (instead of Service Principal), the VM must have rights on the Azure DNS Zone. If this VM is not hosted in Azure, the Instance Metadata Service will be different and will not be able to get credentials needed for it's Managed Identity. For a VM in Azure, it is http://169.254.169.254/metadata/. If the VM is on-premises (for example) and is Arc-enabled so that it's Managed Identity can be used, the Instance Metadata Service is at http://localhost:40342/metadata/. See this documentation.

Steps to reproduce

  1. Stand up a virtual machine in any cloud or on-premises and Arc-enable it using instructions.
  2. In your Azure DNS Zone, give the Azure Arc resource (representation of the virtual machine which was created in previous step) access to the zone. It should have DNS Zone Contributor access. For general information on how to give a Managed Identity access to Azure, see these instructions.
  3. Export the two variables needed to use Managed Identity: export AZUREDNS_SUBSCRIPTIONID="<your subscription>"; export AZUREDNS_MANAGEDIDENTITY=true
  4. Run acme.sh using the DNS method: acme.sh --issue --dns dns_azure --dnssleep 10 --force -d domain.com --staging

Debug log

/root/.acme.sh/acme.sh --issue --dns dns_azure --dnssleep 10 --force -d domain.com --staging --debug 2

acme.sh.log

Potential solution

A solution is to modify the _azure_getaccess_token() function in dns_azure.sh within the existing code block for if [ "$managedIdentity" = true ]; then.

  if [ "$managedIdentity" = true ]; then
    # https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http

    # Modification for Arc-enabled server
    ChallengeTokenPath=$(curl -s -D - -H Metadata:true "http://localhost:40342/metadata/identity/oauth2/token?api-version=2020-06-01&resource=https%3A%2F%2Fmanagement.azure.com" | grep Www-Authenticate | cut -d "=" -f 2 | tr -d "[:cntrl:]")
    ChallengeToken="$(cat $ChallengeTokenPath)"
    if [ $? -ne 0 ]; then
        echo "Could not retrieve challenge token, double check that this command is run with root privileges."
    else
        response=$(curl -s -H Metadata:true -H "Authorization: Basic $ChallengeToken" "http://127.0.0.1:40342/metadata/identity/oauth2/token?api-version=2020-06-01&resource=https%3A%2F%2Fmanagement.azure.com")
        response="$(echo "$response" | _normalizeJson)"
        accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
        expires_on=$(echo "$response" | _egrep_o "\"expires_on\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
    fi
    # Modification end

I have tested this on my on-premises proxmox server. I did not submit a pull request because I don't know of a good way to check if the machine is running in Azure or if it's Arc-enabled.

github-actions[bot] commented 1 year ago

Please upgrade to the latest code and try again first. Maybe it's already fixed. acme.sh --upgrade If it's still not working, please provide the log with --debug 2, otherwise, nobody can help you.

wahidsaleemi commented 1 year ago

Added debug log to original post