Back to Checks
azure

Subscription has an Activity Log alert for Network Security Group delete operations

monitor_alert_delete_nsg
Service: monitorSeverity: high
OfficialBuilt-inVerified
Categories:loggingforensics-ready
Resource Type:microsoft.insights/activitylogalerts

Azure Monitor activity log alerts include the NSG deletion signal (Microsoft.Network/networkSecurityGroups/delete or Microsoft.ClassicNetwork/networkSecurityGroups/delete). The finding indicates whether a subscription has an alert rule configured to trigger when a Network Security Group is deleted.

Risk

Without alerting on NSG deletions, network segmentation can be removed unnoticed, exposing services to broad ingress/egress. Malicious actors or automation may delete NSGs to enable lateral movement and data exfiltration. Missing alerts delay response, impacting confidentiality and availability.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks monitor_alert_delete_nsg

Recommendation

Configure a subscription-wide activity log alert for the NSG delete operation (Microsoft.Network/networkSecurityGroups/delete; include Classic if applicable) and route notifications via action groups. Enforce least privilege for NSG changes, require change control, and integrate with your SIEM for correlation.

Remediation

CLI

az monitor activity-log alert create --name "<activity log rule name>" --resource-group "<resource group name>" --scopes "/subscriptions/<subscription ID>" --condition "category=Administrative and operationName=Microsoft.Network/networkSecurityGroups/delete" --location global

Terraform

# Activity Log alert for NSG delete
resource "azurerm_monitor_activity_log_alert" "example" {
  name                = "<example_resource_name>"
  resource_group_name = "<example_resource_name>"
  scopes              = ["/subscriptions/<example_resource_id>"]

  criteria {
    category       = "Administrative"  # Critical: Activity Log category filter
    operation_name = "Microsoft.Network/networkSecurityGroups/delete"  # Critical: alert on NSG delete
  }
}

NativeIaC

// Activity Log alert for NSG delete
resource activityAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' = {
  name: '<example_resource_name>'
  location: 'Global'
  properties: {
    scopes: ['/subscriptions/<example_resource_id>']
    enabled: true
    condition: {
      allOf: [
        { field: 'category', equals: 'Administrative' } // Critical: filter Activity Log to Administrative category
        { field: 'operationName', equals: 'Microsoft.Network/networkSecurityGroups/delete' } // Critical: triggers on NSG delete
      ]
    }
  }
}

Other

1In Azure Portal, go to Monitor > Alerts > Alert rules
2Click + Create > Alert rule
3Scope: Select the target subscription and click Apply
4Condition: Choose Activity log, select the signal "Delete Network Security Group" (operation Microsoft.Network/networkSecurityGroups/delete); ensure Category is Administrative
5Details: Enter a name; leave other settings as default
6Click Review + create, then Create

Check Code

from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.monitor.lib.monitor_alerts import check_alert_rule
from prowler.providers.azure.services.monitor.monitor_client import monitor_client


class monitor_alert_delete_nsg(Check):
    def execute(self) -> Check_Report_Azure:
        findings = []

        for (
            subscription_id,
            activity_log_alerts,
        ) in monitor_client.alert_rules.items():
            subscription_name = monitor_client.subscriptions.get(
                subscription_id, subscription_id
            )
            for alert_rule in activity_log_alerts:
                if check_alert_rule(
                    alert_rule, "Microsoft.Network/networkSecurityGroups/delete"
                ) or check_alert_rule(
                    alert_rule, "Microsoft.ClassicNetwork/networkSecurityGroups/delete"
                ):
                    report = Check_Report_Azure(
                        metadata=self.metadata(), resource=alert_rule
                    )
                    report.subscription = subscription_id
                    report.status = "PASS"
                    report.status_extended = f"There is an alert configured for deleting Network Security Groups in subscription {subscription_name} ({subscription_id})."
                    break
            else:
                report = Check_Report_Azure(metadata=self.metadata(), resource={})
                report.subscription = subscription_id
                report.resource_name = subscription_id
                report.resource_id = f"/subscriptions/{subscription_id}"
                report.status = "FAIL"
                report.status_extended = f"There is not an alert for deleting Network Security Groups in subscription {subscription_name} ({subscription_id})."

            findings.append(report)

        return findings