Setting this question up to self-answer because I lost too much time solving it, and I want to make sure the answer is put out there for future sufferers to find and avoid the same rabbit-hole I went down...
Issue
I'm trying to use the az network dns zone export command from the Az Cli in a PowerShell script to export the configuration from an Azure DNS Zone, but for some reason it's only exporting the first 100 records if I use az login to connect as a Service Principal with a custom IAM role assigned.
E.g.:
$ErrorActionPreference = "Stop";
Set-StrictMode -Version "Latest";
# see https://github.com/Azure/azure-cli/issues/26052
az config unset core.allow_broker
# log out any existing user
az logout
# log back in as the spn
az login --service-principal `
--username "my-client-id" `
--password "my-client-secret" `
--tenant "my-tenant-id"
# export the dns zone (only the first 100 records get exported :-(
az network dns zone export --resource-group "my-dns-rg" --name "mydnszone.com"
If I run the az network dns zone export command with my personal account logged in (which is an Owner on My Subscription) it works fine and exports all 575 records, so the problem appears to be permission-related, but it's confusing because the first 100 records are exported as the Service Principal so it has at least some permissions to read them.
Environment
My environment setup is as follows:
I have an Azure subscription My Subscription
In this subscription I have a public Azure DNS Zone mydnszone.com which has 575 zone records
I have a custom IAM role called My DNS Reader Role which has the following Microsoft.Network provider operations allowed:
Operation Description Microsoft.Network/dnsZones/read Get the DNS zone, in JSON format. The zone properties include tags, etag, numberOfRecordSets, and maxNumberOfRecordSets. Note that this command does not retrieve the record sets contained within the zone. Microsoft.Network/dnsZones/recordsets/read Gets DNS record sets across types I also have an Azure Service Principal my_dns_reader which has been assigned My DNS Reader Role IAM role scoped to My Subscription
tl;dr
Permissions required to export all pages of records via the
az network dns zone exportcommand are:Summary
The Az Cli uses the Record Sets - List By Dns Zone Azure REST endpoint to export a dns zone with the
az network dns zone exportcommand.This endpoint uses pagination (with a default page size of 100 recordsets) to return recordsets in a DNS zone. The
Microsoft.Network/dnsZones/recordsets/readprovider operation grants access to this endpoint.The first page of results includes a
nextLinkwhich points to a different endpoint - Record Sets - List All By Dns Zone - for page 2 onwards, and this endpoint requires theMicrosoft.Network/dnszones/all/readprovider operation.If this provider operation is missing from the current account the "Record Sets - List All By Dns Zone" endpoint returns paginated results but with zero rows of data in it.
Adding the
Microsoft.Network/dnszones/all/readto my custom IAM role allowed theaz network dns zone exportcommand to export all recordsets in the zone.Confusingly, no error messages are shown if the
Microsoft.Network/dnsZones/recordsets/readprovider operation is present but theMicrosoft.Network/dnszones/all/readprovider operation is missing - instead the "Record Sets - List All By Dns Zone" endpoint returns pagination responses but with zero records included in the data.More details
Running the
az network dns zone exportcommand with the--debugflag shows it first makes a call to the Record Sets - List By Dns Zone Azure REST endpoint - e.g.If the current account has the
Microsoft.Network/dnszones/recordsets/readprovider operation this returns a response in the format:(If there are less than 100 records the
nextLinkfield is missing from the response).Note that the
nextLinkends in/ALLwhich is the Record Sets - List All By Dns Zone endpoint, so subsequent calls made by the Az Cli to read paginated data hit this endpoint instead of the original "Record Sets - List By Dns Zone".Unfortunately, this endpoint requires a different provider operation - namely
Microsoft.Network/dnszones/all/read- if this is missing the response is in the following format:Note that pagination still works. For a zone with 575 records the
nextLinkredirects to a chain of 5 additional pages after the initial request, which is the correct number for a zone with 575 records, but the requests ending in/ALLcontain"value": [].Epilogue
When trying to create a minimal custom IAM role for exporting dns zones, be sure to add all the provider operations in the "tl;dr" section at the top of this answer.