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)
Buy me a beer, Donate to acme.sh if it saves your time. Your donation makes acme.sh better: https://donate.acme.sh/
如果 acme.sh 帮你节省了时间,请考虑赏我一杯啤酒🍺, 捐助: https://donate.acme.sh/ 你的支持将会使得 acme.sh 越来越好. 感谢