Create an Azure Alert Rule for VM Created by Packer

My employer’s IT department is very strict. When a virtual machine is created, alert rules must be applied. There is a brief 5-10 minute grace period, but when the Azure policy and other monitoring tools find a newly created VM without, for example, CPU Utilization % alert then the VM is quarantined/stopped/removed which will cause the packer build to disconnect and fail.

I’m working with the IT Security team in finding a resolution that they would find acceptable. Ideas include… a Special Vnet, an Exception or longer grace period for resource groups and images that begin with ‘pkr’.

Of course their first response was to add the necessary alerts to the running VM that packer has created.

To add a CPU % alert rule, I’ve tried a few ways to get the name of the VM and the resource group from packer to set environment variables using the shell-local provisioner and the azure-cli. This is just one example. I’ve also tried to reference the ${build. } map as well.

build {
  sources = ["source.azure-arm.default"]

  provisioner "shell-local" {

    environment_vars = [
      "resource_group_name={{.TempResourceGroupName}}",
      "deployment_name={{.TempComputeName}}",
    ]

    inline = [
      "scope=$(az vm show --resource-group $resource_group_name --name $deployment_name --output tsv --query id)",
    ]
  }
}

After re-reading the documentation a few times, I tried using the temp_compute_name and temp_resource_group_name. I was expecting to be able to get the names generated by packer but if I generate the names myself then I will know the names.

Here’s a snippet of what I came up with…

locals {
  suffix = split( "-", uuidv4())[0]
  compute_name = "pkrvm${local.suffix}"
  resource_group_name = "pkr-Resource-Group-${local.suffix}"
}

source "azure-arm" "default" {
 ..snip...
  temp_compute_name = local.compute_name
  temp_resource_group_name = local.resource_group_name
}

build {
  sources = ["source.azure-arm.default"]

  provisioner "shell-local" {
  
    environment_vars = [
          "resource_group_name=${local.resource_group_name}",
          "compute_name=${local.compute_name}",
    ]
  
    inline = [
      "scope=$(az vm show --resource-group $resource_group_name --name $compute_name --output tsv --query id)",
      "action=$(az monitor action-group show --name testing --resource-group devops-action-groups --output tsv --query id)",
      "condition=$(az monitor metrics alert condition create --aggregation Average --metric \"Percentage CPU\" --op GreaterThan --type static --threshold 95 --output tsv)",
      "az monitor metrics alert create --name packer-alert-cpu --resource-group $resource_group_name --scopes $scope --action $action --condition $condition --description \"Test High CPU\" --auto-mitigate true --target-resource-type 'Microsoft.Compute/virtualMachines' --region eastus ",
    ]
 }
}