Query private IP Address using Azure CLI

You’d probably guess that querying IP address using Azure CLI could not be easier with az vm list-ip-addresses. It should work if the environment is small and you don’t have virtual machine using the same name. In a large environment specially the one with DevOps you couldn’t avoid developers creating virtual machine using the same name.

In this post I’d like to give some clarification around querying IP address in a specific case when you’d like to perform VM audit level.

A paint point

Let’s take a look in az vm list-ip-addresses first. When running its response give you a JSON formatted result to list all VMs including its private IP address, public IP address and resource group.

  {
    "virtualMachine": {
      "name": "vm",
      "network": {
        "privateIpAddresses": [
          "192.168.1.100"
        ],
        "publicIpAddresses": []
      },
      "resourceGroup": "vm-rg"
    }
  }

You might also need to run the following command to see number of virtual machines using the same name

az vm list-ip-addresses --query "[?virtualMachine.name=='vm']".virtualMachine.name -o tsv | wc -l

If the return is greater than 1 you’d have a problem. In my environment there are 120 VM resources whose names are the same with each other. The pain point here is when doing the VM level audit the return may end up with many duplicates in the loop and the execution would never be finished.

Solution

While relying on az vm list-ip-addresses doesn’t help in the case, you would need to figure out the unique key value and another data set to look up. Fortunately you have network interface card (NIC) information with shows up private IP address (ipConfigurations.privateIpAddress) when running
az network nic list . Sample data is as follows:

"ipConfigurations": [
      {
        "applicationGatewayBackendAddressPools": null,
        "applicationSecurityGroups": null,
        "etag": "W/\"12345-23a1-467b-b6e2-b909321212dssaad\"",
        "id": "/subscriptions/XXXXXXX-XXXX-XXXX-XXX-XXXXXXX/resourceGroups/vm-rg/providers/Microsoft.Network/networkInterfaces/vm-nic/ipConfigurations/ipconfig1",
        "loadBalancerBackendAddressPools": null,
        "loadBalancerInboundNatRules": null,
        "name": "ipconfig1",
        "primary": true,
        "privateIpAddress": "192.168.1.100",
        "privateIpAddressVersion": "IPv4",
        "privateIpAllocationMethod": "Dynamic",
        .....
      }
]

The JSON formatted result also gives you VM resource ID which definitely helps to uniquely reference to NIC profile.

    "virtualMachine": {
      "id": "/subscriptions/XXXXXXX-XXXX-XXXX-XXX-XXXXXXX/resourceGroups/vm-rg/providers/Microsoft.Compute/virtualMachines/vm",
      "resourceGroup": "vm-rg"
    }

There is potentially an approach to query all VMs using az vm list then use VM resource ID to look up to NIC list. Ironically during my test, I realized that the result of az vm list handled case-sensitive while az network nic list didn’t. Below is an example from az vm list.

id": "/subscriptions/XXXXXXXX/resourceGroups/VM-RG/providers/Microsoft.Compute/virtualMachines/vm",

..and if I used it to look up to NIC Azure would not be able to find and returned null.

To help improve Azure, I submitted the finding to Azure CLI GitHub public. You can find it here.

While using VM resource ID cannot solve the issue, you still have another option which is VM’s NIC resource ID. Fortunately the NIC resource ID is not case-sensitive which we would highly be confident to use. Below is a sample code snippet to query private IP address without getting duplicates.

az vm list --query "[?location=='${location}' && provisioningState!='Failed']".networkProfile.networkInterfaces[].id -o tsv |
while read -r nicId; do
   privateIp=$(az network nic list --query "[?id=='$nicId']".ipConfigurations[].privateIpAddress -o tsv)
   echo $privateIp
done

With VM Scale Set (VMSS) if you try to cross reference with resource group (after running az group list) you would also encounter the same casing issue. So if you don’t lower the case (not fully guarantee to work) there is another workaround that I’d like to propose:

az resource list --resource-type 'Microsoft.Compute/virtualMachineScaleSets' --query '[].id' -o tsv | 
while read -r id; do
   az vmss list-instances --ids $id --query "[?location=='westus']".id -o tsv |
   while read -r instanceId;do
     pip=$(az vmss nic list-vm-nics --ids $instanceId --query "[*].ipConfigurations[].privateIpAddress" -o tsv)
   echo $pip
done

Conclusion

When doing VM audit level in your local network you would often need a list of host’ s IP (aka private IP address). It would be good to understand that you can name your virtual machine as similar as to another as long as they are not in the same resource group. By that way you’d encounter the above problem when doing the query and you’d need to find a unique lookup value. In the article VM resource ID and NIC resource ID would be the two best candidates. While VM resource ID seems not to be a choice, NIC resource ID is your need.

This entry was posted in Security Operation and tagged , . Bookmark the permalink.

Leave a Reply