Managing backups for virtual machines (VMs) in the cloud is crucial for ensuring data security and continuity. Manually configuring backups for each VM can be time-consuming and error-prone. Thankfully, Azure Policy provides a powerful way to automate and enforce backup configurations. In this guide, I’ll walk through how to automatically configure Azure VM backups using Azure Policy targeting VMs with a specific tag and backing them up to an existing Recovery Services vault. I’ll also show you how to create and assign the Azure Policy using Terraform, a popular Infrastructure as Code (IaC) tool.

Note: Code given in this blog is only tested in LAB Environment so thoroughly test this before you use in your environment.

What We Will Achieve:

  1. Tag-Based Targeting: Only VMs with a specific tag will be backed up.
  2. Automatic Backup Configuration: VMs will be automatically configured for backup in an existing Recovery Services vault.
  3. Enforcement via Azure Policy: We’ll use Azure Policy to enforce this configuration.
  4. Terraform Automation: We’ll create and assign the Azure Policy using Terraform.

Step 1: Preparing Your Environment

Before diving into the setup, ensure you have the following:

  • Azure Subscription: With the necessary permissions to create and assign policies.
  • Recovery Services Vault: Already created in the same region as the VMs you want to back up.
  • Tagged VMs: The VMs you want to back up should have a specific tag (e.g., BackupPolicy: Yes).
  • Terraform Installed: Make sure you have Terraform installed and configured to work with Azure.

Step 2: Understanding Azure Policy

Azure Policy allows you to enforce organizational standards and assess compliance across your resources. By creating a policy definition, you can ensure that certain configurations, like VM backups, are automatically applied based on specific criteria, such as resource tags.

Step 3: Creating a Custom Policy Definition

Azure Policy definitions are JSON files that describe the policy. For our task, we’ll create a custom policy that:

  • Identifies VMs with a Specific Tag: The policy will target VMs that have a particular tag.
  • Assigns Them to a Backup Policy: It will configure these VMs to be backed up to a specified Recovery Services vault.

Here’s a sample JSON for the policy definition:

{
  "properties": {
    "displayName": "Configure backup on VMs with a specific tag to a Recovery Services vault",
    "policyType": "Custom",
    "mode": "All",
    "parameters": {
      "tagName": {
        "type": "String",
        "metadata": {
          "description": "The name of the tag that the policy will look for.",
          "displayName": "Tag Name",
          "defaultValue": "BackupPolicy"
        }
      },
      "tagValue": {
        "type": "String",
        "metadata": {
          "description": "The value of the tag that the policy will look for.",
          "displayName": "Tag Value",
          "defaultValue": "Yes"
        }
      },
      "vaultName": {
        "type": "String",
        "metadata": {
          "description": "The name of the Recovery Services vault to back up the VMs to.",
          "displayName": "Recovery Services Vault Name"
        }
      },
      "backupPolicyName": {
        "type": "String",
        "metadata": {
          "description": "The name of the backup policy to apply.",
          "displayName": "Backup Policy Name"
        }
      }
    },
    "policyRule": {
      "if": {
        "allOf": [
          {
            "field": "type",
            "equals": "Microsoft.Compute/virtualMachines"
          },
          {
            "field": "[concat('tags[', parameters('tagName'), ']')]",
            "equals": "[parameters('tagValue')]"
          }
        ]
      },
      "then": {
        "effect": "DeployIfNotExists",
        "details": {
          "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
          "existenceCondition": {
            "allOf": [
              {
                "field": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems/properties.friendlyName",
                "equals": "[field('name')]"
              },
              {
                "field": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems/properties.policyName",
                "equals": "[parameters('backupPolicyName')]"
              }
            ]
          },
          "roleDefinitionIds": [
            "/providers/microsoft.authorization/roleDefinitions/aaf6465c-3d9a-4d1a-bb4a-2b3d7e18b503"
          ],
          "deployment": {
            "properties": {
              "mode": "Incremental",
              "template": {
                "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
                "contentVersion": "1.0.0.0",
                "resources": [
                  {
                    "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
                    "apiVersion": "2019-06-15",
                    "name": "[concat(parameters('vaultName'), '/Azure/protectionContainers/vmworkload/iaasvmcontainerv2/', field('name'))]",
                    "properties": {
                      "protectedItemType": "Microsoft.Compute/virtualMachines",
                      "policyId": "[parameters('backupPolicyName')]"
                    }
                  }
                ]
              }
            }
          }
        }
      }
    }
  }
}

Step 4: Implementing Azure Policy with Terraform

Now, let’s automate the creation and assignment of this Azure Policy using Terraform.

Step 4.1: Creating the Terraform Configuration

Create a Terraform file (main.tf) with the following configuration:

provider "azurerm" {
  features {}
}

resource "azurerm_policy_definition" "vm_backup_policy" {
  name         = "vm-backup-policy"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "Configure backup on VMs with a specific tag to a Recovery Services vault"
  description  = "This policy configures VMs with a specific tag to be backed up to a specified Recovery Services vault."

  policy_rule = <<POLICY_RULE
{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Compute/virtualMachines"
      },
      {
        "field": "[concat('tags[', parameters('tagName'), ']')]",
        "equals": "[parameters('tagValue')]"
      }
    ]
  },
  "then": {
    "effect": "DeployIfNotExists",
    "details": {
      "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
      "existenceCondition": {
        "allOf": [
          {
            "field": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems/properties.friendlyName",
            "equals": "[field('name')]"
          },
          {
            "field": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems/properties.policyName",
            "equals": "[parameters('backupPolicyName')]"
          }
        ]
      },
      "roleDefinitionIds": [
        "/providers/microsoft.authorization/roleDefinitions/aaf6465c-3d9a-4d1a-bb4a-2b3d7e18b503"
      ],
      "deployment": {
        "properties": {
          "mode": "Incremental",
          "template": {
            "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
            "contentVersion": "1.0.0.0",
            "resources": [
              {
                "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems",
                "apiVersion": "2019-06-15",
                "name": "[concat(parameters('vaultName'), '/Azure/protectionContainers/vmworkload/iaasvmcontainerv2/', field('name'))]",
                "properties": {
                  "protectedItemType": "Microsoft.Compute/virtualMachines",
                  "policyId": "[parameters('backupPolicyName')]"
                }
              }
            ]
          }
        }
      }
    }
  }
}
POLICY_RULE

  parameters = <<PARAMETERS
{
  "tagName": {
    "type": "String",
    "metadata": {
      "description": "The name of the tag that the policy will look for.",
      "displayName": "Tag Name",
      "defaultValue": "BackupPolicy"
    }
  },
  "tagValue": {
    "type": "String",
    "metadata": {
      "description": "The value of the tag that the policy will look for.",
      "displayName": "Tag Value",
      "defaultValue": "Yes"
    }
  },
  "vaultName": {
    "type": "String",
    "metadata": {
      "description": "The name of the Recovery Services vault to back up the VMs to.",
      "displayName": "Recovery Services Vault Name"
    }
  },
  "backupPolicyName": {
    "type": "String",
    "metadata": {
      "description": "The name of the backup policy to apply.",
      "displayName":

 "Backup Policy Name"
    }
  }
}
PARAMETERS
}

resource "azurerm_policy_assignment" "vm_backup_assignment" {
  name         = "assign-vm-backup-policy"
  policy_definition_id = azurerm_policy_definition.vm_backup_policy.id
  scope        = data.azurerm_subscription.primary.id

  parameters = {
    tagName          = "BackupPolicy"
    tagValue         = "Yes"
    vaultName        = "YourRecoveryServicesVaultName"
    backupPolicyName = "YourBackupPolicyName"
  }
}

Step 4.2: Deploying the Terraform Configuration

  1. Initialize Terraform: In the directory where you created the main.tf file, run the following command to initialize Terraform:
   terraform init
  1. Apply the Configuration: Run the following command to deploy the policy and assignment:
   terraform apply

Terraform will prompt you to confirm the changes. Type yes to proceed.

This will create the custom Azure Policy and assign it to your Azure subscription, automatically configuring backups for any VMs with the specified tag.

Step 5: Monitoring and Compliance

After assigning the policy, Azure will automatically enforce the backup configuration on any existing or newly tagged VMs. You can monitor compliance by navigating to the Compliance section within Azure Policy. This section will show you which VMs are compliant (backed up) and which are not.

With Azure Policy and Terraform, you can automate and enforce backup configurations across your VMs effortlessly. By targeting VMs with specific tags, you ensure that only the necessary resources are backed up, saving costs and improving efficiency. This approach not only simplifies backup management but also ensures that your organizational policies are consistently applied.

By following the steps outlined in this guide, you’ll have a robust, automated backup solution that scales with your Azure environment and is easy to manage with Terraform.

Categories: Guides