Appearance
DDE Azure Site Recovery — Configuration Planning
Environment: Azure DDE (tenant ff1c5d68, ciriusdde.com) Scope: Disaster recovery for DDE VMs per Defender for Cloud finding Status: Planning doc — Terraform implementation is a separate PR in azure-dde-infra, requires Rory approval Related story: DDEENV-032 (DDE-020)
Why ASR for DDE
DDE is customer-facing Medicare billing. Loss of the AVD environment or the identity plane means customers cannot submit claims. HIPAA and HITRUST expect a documented DR strategy with tested RTO/RPO targets. Defender for Cloud flags DDE VMs as "unprotected" when they have no DR configuration, and this is a HIPAA-relevant finding.
DR Strategy Decision Matrix
Before provisioning ASR for a VM, classify it:
| VM Role | DR Strategy | Reason |
|---|---|---|
AVD session host (bc-host-*) | Cross-region image pool, NOT ASR per instance | Session hosts are stateless; rebuild from image in DR region is faster and cheaper than per-VM replication |
Domain controllers (ACTDIRAZC01, ACTDIRAZC02) | Cross-region backup + rebuild or ASR | Rebuild from a good backup is often cleaner than replicating AD state — replicating a compromised DC replicates the compromise |
Entra Connect (ENTRACAZC01) | ASR | Stateful config, painful to rebuild; ASR gets it back quickly |
| Application/file servers | ASR | Stateful, bespoke configuration |
| Jump / bastion hosts | Rebuild from image | Stateless |
| Test / sandbox VMs | No DR | Not in HIPAA scope |
Default when unsure: crash-consistent backup to Recovery Services Vault with cross-region restore enabled is the minimum. ASR is layered on top for the VMs that need lower RTO.
Target Region
| Source | Target |
|---|---|
| DDE primary region (Central US) | East US 2 as Azure DR region (paired region, Azure-managed) |
Cross-region pairing is the default — avoids manual capacity management in the secondary. East US 2 is the Microsoft-paired region for Central US.
VMs in Scope (April 2026 Inventory)
The Defender for Cloud finding lists 14 DDE VMs as unprotected. Classification below reflects current understanding; confirm against the live inventory before the Terraform PR lands.
| VM Name Pattern | Count (approx) | DR Strategy |
|---|---|---|
bc-host-* (AVD session hosts) | Variable (pool-driven) | Cross-region image pool — no per-VM ASR |
ACTDIRAZC01, ACTDIRAZC02 (DDE DCs) | 2 | ASR or cross-region backup + documented rebuild |
ENTRACAZC01 (Entra Connect) | 1 | ASR |
| Other stateful DDE VMs | TBD during inventory | Case-by-case |
Inventory source: run az vm list --subscription <dde-sub-id> plus a Defender for Cloud export filtered to the "Virtual machines should have disaster recovery configured" finding before finalizing the PR.
Terraform Resources Required
The azure-dde-infra PR creates:
Recovery Services Vault (prerequisite — may already exist)
hcl
resource "azurerm_recovery_services_vault" "dde_asr" {
name = "rsv-dde-asr"
location = "eastus2" # target region hosts the vault
resource_group_name = azurerm_resource_group.dde_asr.name
sku = "Standard"
soft_delete_enabled = true
storage_mode_type = "GeoRedundant"
cross_region_restore_enabled = true
tags = local.tags # required tag set per TF standards
}Note: reuse module recovery-vault if already established in azure-dde-infra to get diagnostic settings, immutability (Unlocked), and tagging for free.
ASR Fabric, Container, Network Mapping
hcl
resource "azurerm_site_recovery_fabric" "primary" {
name = "fabric-centralus"
resource_group_name = azurerm_resource_group.dde_asr.name
recovery_vault_name = azurerm_recovery_services_vault.dde_asr.name
location = "centralus"
}
resource "azurerm_site_recovery_fabric" "secondary" {
name = "fabric-eastus2"
resource_group_name = azurerm_resource_group.dde_asr.name
recovery_vault_name = azurerm_recovery_services_vault.dde_asr.name
location = "eastus2"
}
resource "azurerm_site_recovery_protection_container" "primary" {
name = "container-centralus"
resource_group_name = azurerm_resource_group.dde_asr.name
recovery_vault_name = azurerm_recovery_services_vault.dde_asr.name
recovery_fabric_name = azurerm_site_recovery_fabric.primary.name
}
resource "azurerm_site_recovery_protection_container" "secondary" {
name = "container-eastus2"
resource_group_name = azurerm_resource_group.dde_asr.name
recovery_vault_name = azurerm_recovery_services_vault.dde_asr.name
recovery_fabric_name = azurerm_site_recovery_fabric.secondary.name
}
resource "azurerm_site_recovery_network_mapping" "main" {
name = "netmap-centralus-to-eastus2"
resource_group_name = azurerm_resource_group.dde_asr.name
recovery_vault_name = azurerm_recovery_services_vault.dde_asr.name
source_recovery_fabric_name = azurerm_site_recovery_fabric.primary.name
target_recovery_fabric_name = azurerm_site_recovery_fabric.secondary.name
source_network_id = data.azurerm_virtual_network.dde_primary.id
target_network_id = data.azurerm_virtual_network.dde_secondary.id
}Replication Policy
hcl
resource "azurerm_site_recovery_replication_policy" "main" {
name = "policy-dde-asr"
resource_group_name = azurerm_resource_group.dde_asr.name
recovery_vault_name = azurerm_recovery_services_vault.dde_asr.name
recovery_point_retention_in_minutes = 24 * 60 # 24h
application_consistent_snapshot_frequency_in_minutes = 4 * 60 # 4h
}
resource "azurerm_site_recovery_protection_container_mapping" "main" {
name = "mapping-centralus-to-eastus2"
resource_group_name = azurerm_resource_group.dde_asr.name
recovery_vault_name = azurerm_recovery_services_vault.dde_asr.name
recovery_fabric_name = azurerm_site_recovery_fabric.primary.name
recovery_source_protection_container_name = azurerm_site_recovery_protection_container.primary.name
recovery_target_protection_container_name = azurerm_site_recovery_protection_container.secondary.name
recovery_replication_policy_id = azurerm_site_recovery_replication_policy.main.id
}Per-VM Replicated Item
Create one azurerm_site_recovery_replicated_vm per in-scope VM. Start with the highest-value stateful VMs (Entra Connect, any app servers) and measure cost before expanding.
Prerequisites (Must Exist Before PR Merges)
- Recovery Services Vault in the target region (East US 2), with geo-redundant storage and soft-delete enabled.
- Target VNet and subnet in East US 2 provisioned and peered (or routable) to the DDE primary VNet — the network mapping references this.
- Target resource group in East US 2 for the replicated VM resources.
- Target storage account (cache storage) for replication logs — ASR provisions this automatically on first replication, but the RG must exist.
- Diagnostic settings on the RSV forwarding to
cirius-logging-law-central. - IAM:
github-deploy-main(DDE) needsContributoron the ASR resource group andUser Access Administratorif it assigns replication identity roles. - Inventory confirmed — the Defender for Cloud VM list matches the expected scope; any VM classified as "no DR" has an explicit justification.
RTO / RPO Targets (Draft — Rory Approves)
| Tier | VM Class | RTO | RPO |
|---|---|---|---|
| Tier 1 | Entra Connect, app servers | 1 hour | 15 minutes |
| Tier 2 | Domain controllers (via rebuild) | 4 hours | 24 hours |
| Tier 3 | AVD session hosts (rebuild from image) | 4 hours | N/A (stateless) |
Testing and Validation
Ongoing:
- Test failover per Tier 1 VM quarterly — uses the replication without interrupting prod. Validate that the replicated VM boots, joins the network, and the application responds.
- Unplanned failover drill annually — simulated region outage, full DR execution against the runbook. Document RTO/RPO actuals vs. targets.
- Replication health alerts — enable
ReplicationHealthalerts on the RSV, route to SecOps action group.
Out of Scope
- AVD session host image management — handled by separate image build pipeline; ASR is not the right answer for ephemeral hosts.
- AWS DR — separate workstream in
aws-infra, uses cross-region AMI replication and RDS snapshots, not ASR. - Database replication — psql/SQL replication handled at the data tier, not ASR.
Implementation Process
- Confirm DDE VM inventory against the Defender for Cloud finding.
- Build the Terraform in
azure-dde-infraon a branchfeature/dde-asr. - Ensure all prerequisites above are met (vault exists, target VNet exists, etc.); if any prerequisite is missing, land that as a smaller PR first.
- Open PR — CI runs
terraform fmt, Checkov,terraform plan. - Rory reviews the plan — confirms VM classification, target region choice, and cost impact.
- Merge triggers apply via OIDC.
- After apply, wait for initial replication to reach "Protected" state on each VM (can take hours).
- Run a test failover per Tier 1 VM; document results.
- Close DDEENV-032 with evidence: Defender for Cloud finding clear, test failover artifacts attached.
Related
runbooks/backup-architecture.md— backup strategy that ASR complementssecurity/dde-subscription-security-controls.md— broader DDE baselinesecurity/terraform-standards.md— module usage, tagging, compliance defaults