Setup Alerts for Power Off Virtual Machine Events
More Info:
Ensure that a Microsoft Azure activity log alert is fired whenever a 'Power Off Virtual Machine' event is triggered within your cloud account. An Azure activity log alert fires each time the action event that matches the condition defined in the alert configuration is triggered. The alert condition that this conformity rule checks for is Whenever the Administrative Activity Log 'Power Off Virtual Machine (Microsoft.Compute/virtualMachines)' has 'any' level, with 'any' status and event is initiated by 'any'
Risk Level
High
Address
Security
Compliance Standards
CBP, CIS Microsoft Azure Foundations
Triage and Remediation
- Remediation
Remediation
Using Console
Below are step‑by‑step instructions to set up alerts for VM power‑off events in Azure using the portal. This uses Activity Log alerts, which are the most reliable way to capture “Power off” operations.
1. Identify the Event You Want to Alert On
Azure records VM power operations in the Activity log with operations like:
Power off virtual machineDeallocate virtual machine- (and their “Succeeded” status)
You’ll create an Activity log alert on these operations.
2. Go to Azure Monitor
- Sign in to the Azure portal.
- In the left-hand menu (or search bar), go to Monitor.
- In Monitor, select Alerts from the left pane.
- Click + Create → Alert rule.
3. Select the Scope (Which VMs / Subscription / RG)
- Under Scope, click Select resource.
- Decide the level:
- To monitor all VMs in a subscription: choose the Subscription.
- To monitor all VMs in a resource group: choose the Resource group.
- To monitor a single VM: change filter to Resource type = Virtual machines, then select the VM.
- Click Done.
4. Choose the Signal Type (Activity Log)
- Under Condition, click Add condition.
- In the “Select a signal” pane:
- Make sure Signal type is set to Activity log (not Metrics).
- Look for Administrative category events such as:
Power off virtual machineDeallocate virtual machine
- If you see multiple relevant operations (depends on your environment), you may need multiple rules:
- One for
Power off virtual machine - One for
Deallocate virtual machine
- One for
- Click the
Power off virtual machine(or the operation you want) signal.
5. Configure the Condition
After selecting Power off virtual machine:
- You’ll see Configure signal logic.
- Under Filter, ensure:
- Operation name is
Power off virtual machine. - Status (if available) is
Succeededso you only alert on completed power-offs.
- Operation name is
- Leave other filters as default unless you need to further narrow by caller, IP, etc.
- Click Done (or Apply) to confirm the condition.
Repeat to create another alert rule for Deallocate virtual machine if you also want alerts when VMs are deallocated.
6. Create or Select an Action Group (Who Gets Notified)
- Under Actions, click Add action groups.
- Either:
- Select an existing Action group, or
- Click Create action group:
- Define:
- Subscription
- Resource group
- Action group name
- Display name
- On the Notifications tab:
- Click + Add notification.
- Choose Email/SMS/Push/Voice (or other methods such as Webhook, Logic App).
- Enter email addresses or phone numbers as needed.
- Review and Create the action group.
- Define:
- Ensure the action group is selected and click Apply.
7. Define Alert Rule Details
- Under Alert rule details:
- Alert rule name: e.g.,
Alert - VM Power Off - <scope description>. - Description: e.g.,
Alert when any VM in this subscription is powered off (Activity log). - Severity: choose (e.g., Sev 2 or Sev 3) based on your policy.
- Alert rule name: e.g.,
- Ensure Enable rule upon creation is checked.
8. Review and Create
- Click Review + create.
- Validate settings, then click Create.
Repeat the same process for Deallocate virtual machine if you want to catch both power-off behaviors.
9. (Optional) Test the Alert
- Go to one of the target VMs.
- In the VM blade, click Stop (this will typically deallocate it; depending on how it’s done you may see
Power offorDeallocatein the Activity log). - Wait a few minutes; verify:
- The event appears under Monitor → Activity log with
Power off virtual machineorDeallocate virtual machineand statusSucceeded. - The configured action (email/SMS/etc.) is received.
- The event appears under Monitor → Activity log with
This fully remediates the “no alerts on power off VM events” misconfiguration for Azure Compute using the Azure portal.
Using CLI
Below is a minimal, end‑to‑end Azure CLI remediation to alert whenever a VM is powered off or deallocated.
1. Set variables
# Set these to your values
SUBSCRIPTION_ID="<your-subscription-id>"
RESOURCE_GROUP="<rg-of-your-vm-or-alert>"
VM_NAME="<your-vm-name>"
LOCATION="<region-of-alert-eg-westeurope>"
ALERT_NAME="vm-poweroff-alert"
ACTION_GROUP_NAME="vm-poweroff-ag"
ACTION_GROUP_SHORT_NAME="vmoffag"
ALERT_EMAIL="<your-email@example.com>"
az account set --subscription "$SUBSCRIPTION_ID"
Get the VM resource ID (optional, for scoping):
VM_ID=$(az vm show \
--resource-group "$RESOURCE_GROUP" \
--name "$VM_NAME" \
--query id -o tsv)
You can scope the alert to the whole subscription, a resource group, or a single VM. Below I show subscription‑scope (recommended) and note how to change it.
2. Create an Action Group (where alerts are sent)
az monitor action-group create \
--resource-group "$RESOURCE_GROUP" \
--name "$ACTION_GROUP_NAME" \
--short-name "$ACTION_GROUP_SHORT_NAME" \
--location "$LOCATION" \
--action email myEmail "$ALERT_EMAIL"
Capture the Action Group ID:
AG_ID=$(az monitor action-group show \
--resource-group "$RESOURCE_GROUP" \
--name "$ACTION_GROUP_NAME" \
--query id -o tsv)
3. Create Activity Log Alert for VM Power Off / Deallocate
These operations appear in the Activity Log as:
Microsoft.Compute/virtualMachines/deallocate/actionMicrosoft.Compute/virtualMachines/powerOff/action
Create an Activity Log alert for both, scoped to the subscription:
az monitor activity-log alert create \
--name "$ALERT_NAME" \
--resource-group "$RESOURCE_GROUP" \
--scope "/subscriptions/$SUBSCRIPTION_ID" \
--condition category=Administrative \
--condition "operationName=Microsoft.Compute/virtualMachines/deallocate/action" \
--condition "operationName=Microsoft.Compute/virtualMachines/powerOff/action" \
--action-group "$AG_ID" \
--location "$LOCATION"
If you want to scope it to a single VM instead:
az monitor activity-log alert create \
--name "$ALERT_NAME" \
--resource-group "$RESOURCE_GROUP" \
--scope "$VM_ID" \
--condition category=Administrative \
--condition "operationName=Microsoft.Compute/virtualMachines/deallocate/action" \
--condition "operationName=Microsoft.Compute/virtualMachines/powerOff/action" \
--action-group "$AG_ID" \
--location "$LOCATION"
4. Verify
List the activity log alerts:
az monitor activity-log alert list \
--resource-group "$RESOURCE_GROUP" \
-o table
Once in place, whenever a VM is powered off or deallocated under the defined scope, you’ll receive an email from the Action Group.
Using Python
Below is a concise, step‑by‑step way to set up Azure alerts when a VM is powered off (deallocated/stopped) using Python and the Azure SDK.
We’ll create an Activity Log Alert that fires when a VM receives a PowerOff or Deallocate operation.
1. Prerequisites
- Python packages
pip install azure-identity azure-mgmt-monitor
- Authentication
Use one of:
az login(for local dev withDefaultAzureCredential)- Managed Identity (if running in Azure)
- Collect:
subscription_idresource_group_name(for the alert resource)- (Optional)
vm_nameor target resource if you want the alert limited to a specific VM.
2. Understand the operations to monitor
For VM power‑off events, the common Activity Log operations are:
Microsoft.Compute/virtualMachines/powerOff/actionMicrosoft.Compute/virtualMachines/deallocate/action
We’ll create an Activity Log Alert that triggers when either of these appears.
3. Python code – Create Activity Log Alert
This example:
- Creates an Activity Log Alert at the subscription level.
- Filters on the two operations above.
- Sends an email via an action group (if you already have one), or you can just create the alert without actions.
Replace placeholders with your values.
from azure.identity import DefaultAzureCredential
from azure.mgmt.monitor import MonitorManagementClient
from azure.mgmt.monitor.models import (
ActivityLogAlertResource,
ActivityLogAlertAllOfCondition,
ActivityLogAlertLeafCondition,
ActivityLogAlertActionGroup,
)
# -------------------------------------------------------------------
# CONFIG – UPDATE THESE
# -------------------------------------------------------------------
subscription_id = "<YOUR_SUBSCRIPTION_ID>"
resource_group_name = "<ALERT_RESOURCE_GROUP_NAME>"
alert_name = "vm-poweroff-deallocate-alert"
# Optional: if you want to target a specific VM, set this:
# Full VM resource ID (example)
# /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Compute/virtualMachines/<vmname>
target_vm_resource_id = "<OPTIONAL_VM_RESOURCE_ID_OR_LEAVE_EMPTY>"
# Optional: existing Action Group resource ID for notifications
# /subscriptions/<sub>/resourceGroups/<rg>/providers/microsoft.insights/actionGroups/<actionGroupName>
action_group_id = "<OPTIONAL_ACTION_GROUP_RESOURCE_ID_OR_LEAVE_EMPTY>"
# -------------------------------------------------------------------
# AUTH & CLIENT
# -------------------------------------------------------------------
credential = DefaultAzureCredential()
monitor_client = MonitorManagementClient(credential, subscription_id)
# -------------------------------------------------------------------
# CONDITIONS – WHAT TO MATCH IN THE ACTIVITY LOG
# -------------------------------------------------------------------
# We use an "allOf" consisting of:
# - category = Administrative
# - (operationName = PowerOff OR operationName = Deallocate)
# - (optional) resourceId = specific VM
conditions = []
# Category: Administrative
conditions.append(
ActivityLogAlertLeafCondition(
field="category",
equals="Administrative"
)
)
# Operations: powerOff or deallocate
# Note: "anyOf" is implemented as multiple leaf conditions with "OR" behavior
operation_conditions = [
ActivityLogAlertLeafCondition(
field="operationName",
equals="Microsoft.Compute/virtualMachines/powerOff/action"
),
ActivityLogAlertLeafCondition(
field="operationName",
equals="Microsoft.Compute/virtualMachines/deallocate/action"
)
]
# If you want a specific VM only:
if target_vm_resource_id and target_vm_resource_id.strip():
conditions.append(
ActivityLogAlertLeafCondition(
field="resourceId",
equals=target_vm_resource_id
)
)
# Build the final allOf condition:
# SDK expects ActivityLogAlertAllOfCondition with "all_of" (list of leaf conditions or nested).
# For OR between operations, you place them in 'any_of' sub-condition or rely on separate alerts.
# Many customers instead create two alerts (one per operation).
# For simplicity, create ONE alert per operation below.
# -------------------------------------------------------------------
# HELPER – CREATE ONE ALERT FOR A SINGLE OPERATION
# -------------------------------------------------------------------
def create_alert_for_operation(operation_name: str, alert_suffix: str):
leaf_conditions = [
ActivityLogAlertLeafCondition(field="category", equals="Administrative"),
ActivityLogAlertLeafCondition(field="operationName", equals=operation_name)
]
if target_vm_resource_id and target_vm_resource_id.strip():
leaf_conditions.append(
ActivityLogAlertLeafCondition(
field="resourceId",
equals=target_vm_resource_id
)
)
all_of_condition = ActivityLogAlertAllOfCondition(
all_of=leaf_conditions
)
actions = []
if action_group_id and action_group_id.strip():
actions.append(
ActivityLogAlertActionGroup(
action_group_id=action_group_id,
webhook_properties={}
)
)
alert = ActivityLogAlertResource(
location="global",
enabled=True,
scopes=[f"/subscriptions/{subscription_id}"],
condition=all_of_condition,
actions=actions,
description=f"Alert when VM receives {operation_name} operation"
)
result = monitor_client.activity_log_alerts.create_or_update(
resource_group_name=resource_group_name,
activity_log_alert_name=f"{alert_name}-{alert_suffix}",
activity_log_alert=alert
)
print(f"Created alert: {result.name}")
# Create two alerts: one for PowerOff, one for Deallocate
create_alert_for_operation(
"Microsoft.Compute/virtualMachines/powerOff/action",
"poweroff"
)
create_alert_for_operation(
"Microsoft.Compute/virtualMachines/deallocate/action",
"deallocate"
)
4. What this remediation achieves
- Any time a VM is powered off or deallocated:
- Azure emits an Activity Log event.
- The Activity Log Alert(s) above match that event.
- Actions are triggered (e.g., notifications via Action Group), enabling you to detect and investigate unexpected VM shutdowns.
If you tell me whether you want:
- Subscription‑wide vs single‑VM monitoring, and
- Email/SMS/Teams/webhook actions,
I can adjust the code to your exact setup.
Using Terraform
resource "azurerm_monitor_action_group" "vm_poweroff_ag" {
name = "VM_POWEROFF_ACTION_GROUP"
resource_group_name = "RESOURCE_GROUP_NAME" # replace with the resource group for the action group
short_name = "vm-pwoff"
email_receiver {
name = "oncall-email"
email_address = "ONCALL_EMAIL_ADDRESS" # replace with email to receive alerts
}
# add other receivers as needed (sms_receiver, webhook_receiver, etc.)
}
resource "azurerm_monitor_activity_log_alert" "vm_poweroff_alert" {
name = "VM_POWEROFF_ALERT"
resource_group_name = "RESOURCE_GROUP_NAME" # replace with the resource group where you want the alert rule
scopes = [AZURE_VM_RESOURCE_ID] # replace with the full resource ID of the VM or its resource group/subscription
description = "Alert on VM power off or deallocate events"
criteria {
category = "Administrative"
operation_name = "Microsoft.Compute/virtualMachines/deallocate/action"
}
criteria {
category = "Administrative"
operation_name = "Microsoft.Compute/virtualMachines/powerOff/action"
}
action {
action_group_id = azurerm_monitor_action_group.vm_poweroff_ag.id
}
enabled = true
}
This adds an Activity Log Alert that fires whenever a VM is powered off or deallocated and sends notifications through the specified action group. No existing resources are forced to be replaced by this change; it only creates new monitoring resources.
To verify, terraform plan should show creation of azurerm_monitor_action_group.vm_poweroff_ag and azurerm_monitor_activity_log_alert.vm_poweroff_alert with the specified criteria and no changes to your existing azurerm_windows_virtual_machine/azurerm_linux_virtual_machine resources.