# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # E2E Test: Compute/VirtualMachineReplication_AzureSiteRecovery_DINE # Real Azure Policy: "Configure disaster recovery on virtual machines by # enabling replication via Azure Site Recovery" # Source: regolator/policyDefinitions/Compute/VirtualMachineReplication_AzureSiteRecovery_DINE.json # # Features exercised: # - DeployIfNotExists effect # - concat('tags[', parameters('tagName'), ']') — dynamic tag field access # - empty() function for Boolean branching # - in / notIn operators on tag values # - Multi-branch anyOf/allOf with parameterised control flow # - existenceCondition with like + contains operators # - host_await for cross-resource lookup aliases: test_aliases.json policy_definition: | { "properties": { "displayName": "Configure disaster recovery on virtual machines", "policyType": "BuiltIn", "mode": "Indexed", "parameters": { "sourceRegion": { "type": "String" }, "targetRegion": { "type": "String" }, "targetResourceGroupId": { "type": "String" }, "vaultResourceGroupId": { "type": "String" }, "vaultId": { "type": "String" }, "recoveryNetworkId": { "type": "String", "defaultValue": "" }, "targetZone": { "type": "String", "defaultValue": "" }, "cacheStorageAccountId": { "type": "String", "defaultValue": "" }, "tagName": { "type": "String", "defaultValue": "" }, "tagValue": { "type": "Array", "defaultValue": [] }, "tagType": { "type": "String", "allowedValues": ["Inclusion", "Exclusion", ""], "defaultValue": "" }, "effect": { "type": "String", "allowedValues": ["DeployIfNotExists", "Disabled"], "defaultValue": "DeployIfNotExists" } }, "policyRule": { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Compute/virtualMachines" }, { "field": "location", "equals": "[parameters('sourceRegion')]" }, { "anyOf": [ { "allOf": [ { "value": "[parameters('tagType')]", "equals": "Inclusion" }, { "field": "[concat('tags[', parameters('tagName'), ']')]", "in": "[parameters('tagValue')]" } ] }, { "allOf": [ { "value": "[parameters('tagType')]", "equals": "Exclusion" }, { "field": "[concat('tags[', parameters('tagName'), ']')]", "notIn": "[parameters('tagValue')]" } ] }, { "anyOf": [ { "value": "[empty(parameters('tagName'))]", "equals": "true" }, { "value": "[empty(parameters('tagValue'))]", "equals": "true" }, { "value": "[empty(parameters('tagType'))]", "equals": "true" } ] } ] } ] }, "then": { "effect": "[parameters('effect')]", "details": { "type": "Microsoft.Resources/links", "existenceCondition": { "allOf": [ { "field": "name", "like": "ASR-Policy-Protect-*" }, { "field": "Microsoft.Resources/links/targetId", "contains": "/replicationProtectedItems/" } ] } } } } } } cases: # ========================================================================= # No tag filters (all params empty) → matches, related resource not found → DINE # ========================================================================= - note: dine_no_tag_filter_no_related resource: type: "Microsoft.Compute/virtualMachines" name: "vm-no-dr" location: "eastus" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" host_await: - key: operation: "lookup_related_resources" type: "Microsoft.Resources/links" response: null want_effect: "DeployIfNotExists" # ========================================================================= # No tag filter, related resource found with matching name/targetId → compliant # ========================================================================= - note: compliant_dr_configured resource: type: "Microsoft.Compute/virtualMachines" name: "vm-dr-ok" location: "eastus" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" host_await: - response: name: "ASR-Policy-Protect-vm-dr-ok" properties: targetid: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1/replicationProtectedItems/item1" want_undefined: true # ========================================================================= # Related resource found but name doesn't match like → DINE # ========================================================================= - note: dine_wrong_link_name resource: type: "Microsoft.Compute/virtualMachines" name: "vm-wrong-link" location: "eastus" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" host_await: - response: name: "some-other-link" properties: targetid: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1/replicationProtectedItems/item1" want_effect: "DeployIfNotExists" # ========================================================================= # Inclusion tag type — VM has matching tag → if-condition matches # ========================================================================= - note: dine_inclusion_tag_match resource: type: "Microsoft.Compute/virtualMachines" name: "vm-tagged" location: "eastus" tags: Environment: "production" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" tagName: "Environment" tagValue: - "production" - "staging" tagType: "Inclusion" host_await: - response: null want_effect: "DeployIfNotExists" # ========================================================================= # Inclusion tag type — VM tag doesn't match → if-condition fails → pass # ========================================================================= - note: pass_inclusion_tag_no_match resource: type: "Microsoft.Compute/virtualMachines" name: "vm-dev" location: "eastus" tags: Environment: "development" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" tagName: "Environment" tagValue: - "production" - "staging" tagType: "Inclusion" want_undefined: true # ========================================================================= # Exclusion tag type — VM tag in exclusion list → pass (excluded from scope) # ========================================================================= - note: pass_exclusion_tag_excluded resource: type: "Microsoft.Compute/virtualMachines" name: "vm-excluded" location: "eastus" tags: Environment: "sandbox" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" tagName: "Environment" tagValue: - "sandbox" - "test" tagType: "Exclusion" want_undefined: true # ========================================================================= # Exclusion tag type — VM tag NOT in exclusion list → matches → DINE # ========================================================================= - note: dine_exclusion_tag_not_excluded resource: type: "Microsoft.Compute/virtualMachines" name: "vm-prod-excl" location: "eastus" tags: Environment: "production" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" tagName: "Environment" tagValue: - "sandbox" - "test" tagType: "Exclusion" host_await: - response: null want_effect: "DeployIfNotExists" # ========================================================================= # Wrong location → if-condition fails → pass # ========================================================================= - note: pass_wrong_location resource: type: "Microsoft.Compute/virtualMachines" name: "vm-wrong-loc" location: "westus" properties: {} parameters: sourceRegion: "eastus" targetRegion: "westus" targetResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-dr" vaultResourceGroupId: "/subscriptions/sub1/resourceGroups/rg-vault" vaultId: "/subscriptions/sub1/resourceGroups/rg-vault/providers/Microsoft.RecoveryServices/vaults/vault1" want_undefined: true