Production readiness pass
Your POC passed review; now a security checklist stands between it and the wider rollout. Every control on that list has its own docs page, but the pages do not tell you the order, and two of the classic mistakes here are one-way doors: locking every admin out by enabling SSO without a tested break-glass login, and going live with no proven backup. This tutorial sequences the hardening pass so the irreversible steps are protected first.
1. Tighten the management NSG
Section titled “1. Tighten the management NSG”The deployment already scopes the management ports (8443, 8080) to the
adminAddressPrefix parameter; it just defaults to the whole VNet. This
step is tightening that value to your admin subnet or jumpbox CIDR, not
authoring rules from scratch. Leave 53 open to your client subnets and
7946 between the DTM nodes only, per the
port table and the
operator responsibilities.
Verify both directions:
az network nsg rule list -g rg-dtm-poc --nsg-name nsg-dtm -o table
# From a NON-admin subnet, this should now time out:curl -sk --max-time 5 https://10.0.250.4:8443/readyz || echo "blocked (good)"2. Replace shared logins with named accounts
Section titled “2. Replace shared logins with named accounts”Create the account baseline that users and access recommends:
named admin accounts for the people who need them, editor for engineers
and automation that manage DNS data, readonly for dashboards and auditors,
and one break-glass local admin with a strong password stored in your
vault. The three roles are admin, editor, and readonly.
Verify a role boundary, not just a login. As a readonly user:
curl -sk -X POST https://10.0.250.4:8443/api/v1/zones \ -H "Authorization: Bearer $READONLY_TOKEN" \ -H "X-DTM-CSRF: 1" -H "Content-Type: application/json" \ -d '{"name": "should-fail.internal."}'# 4033. Enable Entra ID single sign-on
Section titled “3. Enable Entra ID single sign-on”Follow Entra ID SSO: register the app, assign App Roles,
and apply the configuration (PUT /api/v1/auth/entra/config, admin role).
People now sign in with their Microsoft identity, and their DTM role comes
from the Entra app role.
Verify: one SSO login with the expected role, one break-glass local login, both witnessed in separate private windows.
4. Give the API a stable certificate
Section titled “4. Give the API a stable certificate”Monitors, automation, and the Terraform provider should verify TLS rather
than skip it, and by default the API listener self-signs a fresh certificate
at every service start. Follow the
stable API certificate procedure
(listen.tls.cert_file / key_file, restart one node at a time, gating each
restart on /readyz).
If you plan to serve DoT or DoH soon, you can fold this into that rollout instead: the encrypted DNS tutorial starts with this same step.
Verify: curl without -k:
curl --cacert corp-ca.pem https://10.0.250.4:8443/readyz# 200: ready5. Schedule backups
Section titled “5. Schedule backups”Enable the built-in scheduler on each node, with an off-node copy to a versioned, soft-delete-enabled Storage Account via the node’s managed identity (grant it Storage Blob Data Contributor on the container; no SAS tokens or keys):
backup: schedule_enabled: true interval_minutes: 360 blob_container_url: https://<account>.blob.core.windows.net/dtm-backupsThe backup and restore
page covers the full key set, the local-first upload behavior, and the cron
alternative if you prefer an external trigger. Either way, wire the
dead-pipeline alert on dtm_backup_last_success_timestamp_seconds from that
page; a scheduler nobody watches is the old cron problem wearing a new hat.
Verify the first snapshot like you mean it:
az storage blob list --account-name <account> --container-name dtm-backups \ --auth-mode login -o table # snapshot landedA backup you have never listed, and a backup alert that has never been checked, are hopes, not controls. The full proof is a restore drill, which deserves its own session; put it on the calendar now.
6. Treat snapshots and the cluster key as secrets
Section titled “6. Treat snapshots and the cluster key as secrets”A snapshot contains all DNS data, users, and configuration, readable as-is; the stored secrets inside it are additionally protected by the cluster encryption key. So both the snapshot store and the key are production secrets: scope Storage Account access tightly, and guard the deployment’s Key Vault per rotating secrets.
7. Assign the Azure Policy governance pack
Section titled “7. Assign the Azure Policy governance pack”Deploy the shipped policy pack: 8 definitions (7 audit-by-default;
encryption-at-host ships disabled, opt-in) plus one
initiative, one az deployment sub create against its deploy.json, with
assignments defaulting to enforcementMode: DoNotEnforce. Details and the
per-control table are in
Azure Policy governance.
Verify: the initiative shows assigned in Azure Policy, and after the next evaluation cycle its compliance view lists your DTM resources.
8. The go-live gate
Section titled “8. The go-live gate”Run the checklist as a gate, not a memory:
| Control | Proven by |
|---|---|
| NSG scoped to admin CIDR | blocked curl from a non-admin subnet |
| Named accounts, least role | 403 probe as readonly |
| SSO on, break-glass tested | two private-window logins |
| Stable API certificate | curl --cacert with no -k |
| Backup scheduled and verified | listed blob, fresh success timestamp |
Policy pack assigned, DoNotEnforce |
initiative visible in Azure Policy |
Close with an audit spot check, run as your named admin account (the
audit log is readable by editor and admin):
curl -sk "https://10.0.250.4:8443/api/v1/audit?limit=100" \ -H "Authorization: Bearer $DTM_TOKEN"Every change you made above should be in that list, attributed to a person. If it is, your accountability story works; go live.
Where next
Section titled “Where next”- Zero to serving DNS: the POC this pass hardens, if you arrived here first.
- Adding nodes (scaling out): production means at least two nodes.
- Wire observability end to end: metrics and alerts before the rollout widens.
- Backup and restore: schedule the restore drill you promised yourself in step 5.
Need a hand? Email [email protected].
Last validated: 2026-07-26