Last week a friend asked me if creating or updating a virtual machine where a public IP address was associated with was detectable. This is a very common requirement in cloud security monitoring. Having a workload (aka virtual machine) with Internet exposure is never recommended. Otherwise, that virtual machine plays a security perimeter role.

In this article, let’s see how we can trigger an alert when someone creates or updates a virtual machine that has a public IP address.

Use Case

A virtual machine with Internet exposure is always put at risk. Bad actors can try different vulnerabilities when that virtual machine is accessible from them. Once that virtual machine is compromised bad actors could scan and extract sensitive information on it and try to laterally move across your environment. It would become worse if that virtual machine had its system-assigned managed identity being granted more than just the Reader access in Azure subscription.

As a SecOps analyst you would need to monitor and get notification if someone creates or updates a virtual machine to associate a public IP Address. And this is what this article is about.


The approach is to use either Azure Monitor Alert or Microsoft Sentinel to monitor and trigger an alert. I would highly recommend you to read the following article to understand more

Detect NSG inbound rule updated to allow All

Network Security Group (NSG) is one of the most common features in Azure to help strengthen your network defense. It allows you to filter network traffic to and from Azure resources. Having NSG in place doesn’t always mean your network … Continue reading

The query to use for the detection is as follows:

// Find Network Interface Card (NIC) where a Public Ip address is associated with

let NicResourceIds =


| where OperationNameValue =~ “Microsoft.Network/networkInterfaces/write”

| extend publicIpResourceId = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(Properties).requestbody)).properties)).ipConfigurations))[0].properties)).publicIpAddress)).id)

| where publicIpResourceId != “”

| project _ResourceId;

// Find virtual machines that have Nic associated with


| where CategoryValue == “Administrative”

| extend Action = tostring(parse_json(Authorization).action),

NicResourceId = tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(tostring(parse_json(Properties).responseBody)).properties)).networkProfile)).networkInterfaces))[0].id)

| where Action =~ “Microsoft.Compute/virtualMachines/write” and

ActivityStatusValue =~ ‘Accepted’ and

NicResourceId in~ (NicResourceIds)

| project TimeGenerated,








Below are sample templates:

ARM Template for Azure Monitor Alert

ARM Template for Microsoft Sentinel Analytics Rule

Resource Graph Explorer

The Resource Graph Explorer is another good way to monitor and track virtual machines with Public IP Address. However, it doesn’t give you who created or updated as well as information that Azure Activity Log provides.

If you wish to perform an on-demand assessment, below is the query to find those virtual machines:


| where type =~ ‘microsoft.compute/virtualmachines’

| extend nics=array_length(properties.networkProfile.networkInterfaces)

| mvexpand nic=properties.networkProfile.networkInterfaces

| extend hostName = properties.osProfile.computerName

| where nics == 1 or =~ ‘true’ or isempty(nic)

| project vmId = id,

vmName = name,

nicId = tostring(,


| join kind=leftouter (


| where type =~ ‘’

| extend ipConfigsCount=array_length(properties.ipConfigurations)

| mvexpand ipconfig=properties.ipConfigurations

| extend privateIp =,

publicIpId = tostring(

| where ipConfigsCount == 1 or =~ ‘true’

| project nicId = id,




on nicId

| project-away nicId1

| summarize by vmId, vmName, tostring(hostName), nicId, publicIpId, tostring(privateIp)

| join kind=leftouter (


| where type =~ ‘’

| project publicIpId = id, publicIpAddress = properties.ipAddress)

on publicIpId

| where publicIpAddress != “”

| project-away publicIpId1

Read the full article here:


WordPress Appliance - Powered by TurnKey Linux