9 How to use Azure DNS
Adam Bulgatz edited this page 2024-10-03 00:52:05 -05:00

Prerequisites

You need the Azure CLI 2.0 tools to create a service principal for access to your DNS Zone.

Either install Azure CLI 2.0 locally or use the Azure Cloud Shell in Bash mode.

(See the Azure Command-Line Interface (CLI) documentation for more details)

Log-in to Azure

(Not required when using the Azure Cloud Shell)

az login 
[
  {
    "cloudName": "AzureCloud",
    "id": "12345678-9abc-def0-1234-567890abcdef",
    "isDefault": true,
    "name": "myAzureSubscription",
    "state": "Enabled",
    "tenantId": "11111111-2222-3333-4444-555555555555",
    "user": {
      "name": "someone@example.com",
      "type": "user"
    }
  }
]

Set your Azure subscription if you have more than one

az account list
[
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "id": "baaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "isDefault": true,
    "managedByTenants": [],
    "name": "Subscription A",
    "state": "Enabled",
    "tenantId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "user": {
      "cloudShellID": true,
      "name": "email@example.com",
      "type": "user"
    }
  },
  {
    "cloudName": "AzureCloud",
    "homeTenantId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "id": "caaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "isDefault": false,
    "managedByTenants": [],
    "name": "Subscription B",
    "state": "Enabled",
    "tenantId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
    "user": {
      "cloudShellID": true,
      "name": "email@example.com",
      "type": "user"
    }
  }
]
az account set --subscription "Subscription B"

List your DNS Zones

az network dns zone list
[
  {
    "etag": "00000002-0000-0000-f641-73c64955d301",
    "id": "/subscriptions/12345678-9abc-def0-1234-567890abcdef/resourceGroups/exampledns_rg/providers/Microsoft.Network/dnszones/example.com",
    "location": "global",
    "maxNumberOfRecordSets": 5000,
    "name": "example.com",
    "nameServers": [
      "ns1-02.azure-dns.com.",
      "ns2-02.azure-dns.net.",
      "ns3-02.azure-dns.org.",
      "ns4-02.azure-dns.info."
    ],
    "numberOfRecordSets": 11,
    "resourceGroup": "exampledns_rg",
    "tags": {},
    "type": "Microsoft.Network/dnszones"
  }
]

Create a service principal

The service principal is used to grant acme.sh access to the DNS Zone using the id value from the previous commands output

(See the az ad sp create-for-rbac documentation for more details)

az ad sp create-for-rbac --name  "AcmeDnsValidator" --role "DNS Zone Contributor" --scopes \
    /subscriptions/12345678-9abc-def0-1234-567890abcdef/resourceGroups/exampledns_rg/providers/Microsoft.Network/dnszones/example.com
{
  "appId": "3b5033b5-7a66-43a5-b3b9-a36b9e7c25ed",
  "displayName": "AcmeDnsValidator",
  "name": "http://AcmeDnsValidator",
  "password": "e.L8Q~4jGhWHheCKjdRzw3gyBBwOmrTyYF9NYbxs",
  "tenant": "11111111-2222-3333-4444-555555555555"
}
Note: Dealing with multiple DNS Zones

If you are managing certificates for multiple DNS Zones, you can create the service principal with multiple scopes.

For example, if you are managing certificates for both example.com and example.edu, you can create the service principal with both scopes:

az ad sp create-for-rbac --name  "AcmeDnsValidator" --role "DNS Zone Contributor" --scopes \
    /subscriptions/12345678-9abc-def0-1234-567890abcdef/resourceGroups/exampledns_rg/providers/Microsoft.Network/dnszones/example.com \
    /subscriptions/12345678-9abc-def0-1234-567890abcdef/resourceGroups/exampledns2_rg/providers/Microsoft.Network/dnszones/example.edu

Or if the service principal has already been created, you can grant it access to the additional scope:

az ad sp list --filter "displayname eq 'AcmeDnsValidator'" | grep '^    \"id\":'

(The grep above is assuming a json array of nested lists is returned with a tab size of two spaces and is finding the top-level id)

    "id": "daaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
az role assignment create --assignee daaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa --role "DNS Zone Contributor" --scope \
    /subscriptions/12345678-9abc-def0-1234-567890abcdef/resourceGroups/deleteme_rg/providers/Microsoft.Network/dnszones/example.edu
Note: Dealing with multiple credentials

By default acme.sh saves credentials in ~/.acme.sh/account.conf and these credentials are used for all DNS zones.

If you want to use different credentials, use the --accountconf switch to specify a configuration file.

Limit access permissions to TXT records

In Azure DNS you can limit the permissions for the service principal further and only grant permissions to modifiy TXT records for a given DNS Zone.

(See How to protect DNS zones and records for more details)

Example:

  • Azure Subscription is 12345678-9abc-def0-1234-567890abcdef
  • The resource group of your DNS Zone is exampledns_rg
  • The DNS Zone is example.com
#!/usr/bin/env sh
# Create a custom RBAC role that grants permissions to modify only TXT records
dnscustomrole='{ 
    "Name": "DNS TXT Contributor", 
    "Id": "",
     "IsCustom": true, 
    "Description": "Can manage DNS TXT records only.", 
    "Actions": [ 
        "Microsoft.Network/dnsZones/TXT/*", 
        "Microsoft.Network/dnsZones/read", 
        "Microsoft.Authorization/*/read", 
        "Microsoft.Insights/alertRules/*", 
        "Microsoft.ResourceHealth/availabilityStatuses/read", 
        "Microsoft.Resources/deployments/read", 
        "Microsoft.Resources/subscriptions/resourceGroups/read" 
    ],
    "NotActions": [ 
    ],
    "AssignableScopes": [ 
        "/subscriptions/12345678-9abc-def0-1234-567890abcdef" 
    ] 
}'
az role definition create --role-definition "$dnscustomrole"
# Create a new service principal and grant permissions to modify TXT recornds in the give DNS Zone
az ad sp create-for-rbac --name  "AcmeDnsValidator" --role "DNS TXT Contributor" --scopes "/subscriptions/12345678-9abc-def0-1234-567890abcdef/resourceGroups/exampledns_rg/providers/Microsoft.Network/dnszones/example.com" 

# or  grant an existing service principal permissions to modify TXT recornds in the give DNS Zone
#az role assignment create  --assignee 3b5033b5-7a66-43a5-b3b9-a36b9e7c25ed --scope "/subscriptions/12345678-9abc-def0-1234-567890abcdef/resourceGroups/exampledns_rg/providers/Microsoft.Network/dnszones/example.com" --role "DNS TXT Contributor"

You can now use acme.sh

export AZUREDNS_SUBSCRIPTIONID="12345678-9abc-def0-1234-567890abcdef"
export AZUREDNS_TENANTID="11111111-2222-3333-4444-555555555555"
export AZUREDNS_APPID="3b5033b5-7a66-43a5-b3b9-a36b9e7c25ed"          # appid of the service principal
export AZUREDNS_CLIENTSECRET="e.L8Q~4jGhWHheCKjdRzw3gyBBwOmrTyYF9NYbxs"   # password from creating the service principal

acme.sh --issue --dns dns_azure -d example.com -d www.example.com

Update service principal password

The service principal credentials may eventually expire.

Some acme.sh renewal errors that are signs of the credentials expiring:

  • no acccess token received. Check your Azure settings
  • access denied make sure your Azure settings are correct
az ad sp list --filter "displayname eq 'AcmeDnsValidator'" | grep '^    \"id\":'

(The grep above is assuming a json array of nested lists is returned with a tab size of two spaces and is finding the top-level id)

    "id": "daaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
az ad sp credential reset --id daaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa

Update ~/.acme.sh/account.conf with the new credentials.

(See az ad sp credential for details)