Skip to main content

Google Cloud DNS

CertAutoPilot authenticates to Cloud DNS with a service-account key (JSON). The account needs the DNS Administrator role or a narrower custom role restricted to dns.changes.create and dns.resourceRecordSets.* on the managed zone.

Prerequisites

  • A GCP project that owns the managed zone (Cloud DNS → Zones).
  • Permission to create service accounts + download keys (iam.serviceAccountKeys.create).

Minimum custom role

For tightest scope, create a role with these permissions, bound to the zone (or the project if zone-level bindings are too granular for your org policy):

dns.changes.create
dns.changes.get
dns.changes.list
dns.managedZones.list
dns.resourceRecordSets.create
dns.resourceRecordSets.delete
dns.resourceRecordSets.list
dns.resourceRecordSets.update

If custom roles are too much ceremony, roles/dns.admin is the stock choice.

Create the service account

gcloud iam service-accounts create certautopilot-dns \
--display-name "CertAutoPilot DNS-01"

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:certautopilot-dns@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/dns.admin

gcloud iam service-accounts keys create sa-key.json \
--iam-account certautopilot-dns@$PROJECT_ID.iam.gserviceaccount.com

The sa-key.json file is the credential you paste into CertAutoPilot. Treat it like a password.

Add the credential

  1. Settings → DNS CredentialsNewGoogle Cloud DNS.
  2. Paste the service-account JSON key directly into the Service account JSON field. The form auto-detects the format.
  3. Test connectivitySave.
Two supported formats

The form accepts either (a) the raw service-account key JSON as downloaded from GCP, or (b) a wrapped envelope {"project_id": "...", "service_account_json": {...}} where the inner object is the SA key. Use (a) unless your workflow already produces the wrapped form.

Config fields

FieldRequiredPurpose
Service account JSONyesFull JSON key with type: service_account. Envelope encrypted at rest.
project_idwrapped onlySet when using the wrapped envelope format.
zone_idnoPin to a specific managed zone when multiple zones share an apex name.

Propagation

Cloud DNS updates propagate within ~30 seconds globally. The default propagation check works without tuning.

Workload Identity (GKE)

If CertAutoPilot runs in GKE, you can avoid static service-account keys by binding the pod's Kubernetes service account to a GCP service account via Workload Identity. The credential form does not currently accept "no key — use metadata", so you still paste a minted short-lived key for now; full Workload Identity support is on the roadmap.

Troubleshooting

"403 Permission denied"

The service account lacks dns.changes.create on the zone. Grant roles/dns.admin or the custom role above.

"Service account JSON must be a JSON object or string"

The pasted value is neither the raw key nor a valid wrapped envelope. Re-download the key from GCP; don't edit it.

"Quota exceeded" during heavy issuance

Cloud DNS has per-project-per-minute change quotas. Use bulk-action rate limiting (Settings → General) to stay under them.

See also