Easier way of retrieving an Azure VM's Public IP address - azure

Using the name/resource group of a specific VM, I'm trying to get the VM's public IP address.
This code works but it seems unwieldy in comparison to other AzureRM cmdlets.
$VM = Get-AzureRmVM -ResourceGroupName MyResourceGroup -Name MyVMName
$NIC = $VM.NetworkProfile.NetworkInterfaces[0].Id -replace '.*\/'
$NI = Get-AzureRmNetworkInterface -Name $NIC -ResourceGroupName MyResourceGroup
$NIIC = Get-AzureRmNetworkInterfaceIpConfig -NetworkInterface $NI
$PIP = $NIIC.PublicIpAddress.Id -replace '.*\/'
$PIP = Get-AzureRmPublicIpAddress -Name $PIP -ResourceGroupName MyResourceGroup
$PIP.IpAddress
Is there a quicker/easier/shorter way of accessing this information?

As far as i know, Not Yet for PowerShell. But you can use Azure CLI
az vm list-ip-addresses -n <VMName> -g <ResourceGroup> | grep publicIpAddresses

Try the Azure CLI command:
az vm list-ip-addresses -g groupName -n vmName --query "[].virtualMachine.network.publicIpAddresses[*].ipAddress" -o tsv
Or the PowerShell command just filter with your vm name:
$ipAddress= (Get-AzureRmPublicIpAddress -ResourceGroupName groupName | Where-Object { $_.IpConfiguration.Id -like "*vmName*" }
)
$ipAddress.IpAddress

It's possible. This script will list all VMs PIP in your Azure cloud.
OLD
$VM_int = Get-AzureRmResource -ODataQuery "`$filter=resourcetype 'Microsoft.Compute/virtualMachines'"
foreach($int in $VM_int){
$vmName = $int.Name
$ipAddress= (Get-AzureRmPublicIpAddress -ResourceGroupName $int.ResourceGroupName | Where-Object { $_.IpConfiguration.Id -like "*$vmName*" })
$vmName + ' --- ' + $ipAddress.IpAddress
}
UPDATE
Unfortunately, Get-AzVM doesn't provide the Public IP address of VM, but we can scrape its Network Interface Name and make a wildcard search of it through all assigned Public IPs which NIC name are matched.
It's not fast but will provide with correct results.
$array = #()
foreach ($vm in Get-AzVM) {
$vmNicName = $vm.NetworkProfile.NetworkInterfaces.Id.Split("/")[8]
$ipAddress = Get-AzPublicIpAddress | Where-Object {$_.IpConfiguration.Id -like "*$vmNicName*"}
if ($null -ne $ipAddress) {
$pipInput = New-Object psobject -Property #{
VM = $vm.Name
PublicIP = $ipAddress.IpAddress
}
$array += $pipInput
}
}

The way i got the value for my Linux VM's was using below code.
Get-AzureRmPublicIpAddress -ResourceGroupName <yourRG> -Name <yourVMName> | Select-Object {$_.IpAddress}
This will return something of this sort:
$_.IpAddress
------------
52.170.56.60

This outputs a bit of information however the public IP address is in there.
Get-AzPublicIpAddress -ResourceGroupName MyResourceGroup | Where-Object {$_.name -like "*MyVMName*" }
Or you can do this to just get the IP address:
Get-AzPublicIpAddress -ResourceGroupName MyResourceGroup | Where-Object {$_.name -like "*MyVMName*" } | Select-Object { $_.IpAddress }
Output is like:
$_.IpAddress
--------------
13.255.162.33

You can also match the AzPublicIpAddress IpConfiguration.Id with the VM's NetworkInterfaces.Id:
Get-AzPublicIpAddress | ?{$_.IpConfiguration.Id -match "$((Get-AzVM -Name $computername).NetworkProfile.NetworkInterfaces.Id).*" }

#Get the VM object
$vm = Get-AzVM -Name $vmName -Status
#Get name of network adapter object attached to VM
$NetworkInterfaceName = $vm.NetworkProfile.NetworkInterfaces.Id.Split("/") | Select -Last 1
#Get network adaptor object attached to VM
$NetworkInterfaceObject = Get-AzNetworkInterface -Name $NetworkInterfaceName
#Get public IP Address object name attached to network adaptor object
$ipObjectName = $NetworkInterfaceObject.IpConfigurations.PublicIpAddress.Id.Split("/") | Select -Last 1
#get publivc IP Address attached to public IP Address object
$ipObject = Get-AzPublicIpAddress -ResourceGroupName $resourceGroupName -Name $ipObjectName
Write-Output $ipObject.IpAddress

Yet another method from within a Linux VM.
First, install the Azure command-line tools in the VM, see Azure docs
Second, execute the following in a shell on the VM:
az network public-ip list --query "[?dnsSettings.domainNameLabel=='MY_VM']"
where MY_VM is (hopefully) the host name of your VM. The command returns a multiline JSON string which is a list. Example is shown below:
[
{
"dnsSettings": {
"domainNameLabel": "MY_VM",
"fqdn": "my_vm.westeurope.cloudapp.azure.com"
},
"etag": "W/\"some_uuid...\"",
...
"ipAddress": "AAA.BBB.CCC.DDD",
},
...
]
How to parse the FQDN and the public IP out of this is left as an exercise to the reader :-)

Related

How delete VM Azure using tags using powershell?

How do I delete a VM using tags? Let's say there is a VM with the tags "Name:Surname". How can I delete this VM without using the VM name or ID. Namely deletion using tags.
I try to use:
get-azvm -ResourceGroupName "ResourceGroup" | Where-Object {$_.Tags -like "[Name, blabla], [Surname, blabla]"}
but it didn't find that VM
I have reproduced in my environment. Firstly, you need to find the Virtual Machine using the below command:
xx- Name of the resource group
hello- tag name
get-azvm -ResourceGroupName "xx" | Where-Object {$_.Tags['hello']}
After getting the VM name you can use the below command to delete the VM:
xx- Name of the resource group
yy- Name of the vm.
Remove-AzVM -ResourceGroupName "xx" -Name "yy"
Then type Y(yes) to delete the VM as below:
References taken from:
https://learn.microsoft.com/en-us/powershell/module/az.compute/remove-azvm?view=azps-8.2.0#example-1-remove-a-virtual-machine
https://learn.microsoft.com/en-us/powershell/module/az.compute/get-azvm?view=azps-8.2.0
Based on this,
You could do something like this:
$Surname= 'Test'
$VMs = Get-AzVM -ResourceGroupName 'myRG'
foreach ($VM in $VMs)
{
[Hashtable]$VMTag = (Get-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name).Tags
foreach ($h in $VMTag.GetEnumerator()) {
if (($h.Name -eq "Name") -and ($h.value -eq $Surname))
{
Write-host "Removing VM" $VM.Name
Remove-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Force -Confirm:$false
}
}
}

Get Azure VM details by filtering using tags in powershell

I will like to use the Get-AzVm command to get list of VMs having a specific tag.
I have tried Get-AzVM | Where-Object {$_.Tags['Resource'] -eq "test"}
Still does not return VMS with the tag "Resource:test"
The output of get-azvm doesn't produce Tags for VM. But, Get-AzVM -ResourceGroupName ResourceGroupName -Name VMName does that.
So you need to loop through VMs, store the VM tag in a hashtable and then enumerate through the hastable to check your desired tag with value is there. Here goes the code-
$VMs = get-azvm
foreach ($VM in $VMs)
{
[Hashtable]$VMTag = (Get-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name).Tags
foreach ($h in $VMTag.GetEnumerator()) {
if (($h.Name -eq "Resource") -and ($h.value -eq "test"))
{
Write-host "VM with tags Resource:test are" $VM.Name
}
}
}

How to create an Azure Network Security Group Flow log with Azure PowerShell

I want to create a NSG flow log for the network security group of a given Virtual Machine and link to a given Storage Account with PowerShell.
How can I achieve this?
This can be achieved with this sequence of operations:
determine the NSG linked to a Virtual Machine
get or create a `NetworkWatcher for the location of the NSG
find a suitable storage account
set a Flow Log configuration, if there is none existing
param(
# RegEx pattern to find your first VM in your current subscription
[Parameter(Mandatory = $true, Position = 1)]
[string]$vmNamePattern,
# RegEx pattern to find a storage account in your current subscription
[Parameter(Mandatory = $true, Position = 2)]
[string]$storageNamePattern
)
$vm = Get-AzVM | Where-Object { $_.Name -match $vmNamePattern } | Select-Object -First 1
$nic = Get-AzNetworkInterface -ResourceId $vm.NetworkProfile.NetworkInterfaces[0].Id
$sn = Get-AzVirtualNetworkSubnetConfig -ResourceId $nic.IpConfigurations[0].Subnet.Id
$nsgRes = Get-AzResource -ResourceId $sn.NetworkSecurityGroup.Id
$nsg = Get-AzNetworkSecurityGroup -ResourceGroupName $nsgRes.ResourceGroupName -Name $nsgRes.ResourceName
# create or get NetworkWatcher
$nw = Get-AzNetworkWatcher -ResourceGroupName NetworkWatcherRg | ? { $_.Location -eq $nsg.Location }
if (!$nw) {
New-AzNetworkWatcher -ResourceGroupName NetworkWatcherRg -Location $nsg.Location -Name $("NetworkWatcher_" + $nsg.Location)
$nw = Get-AzNetworkWatcher -ResourceGroupName NetworkWatcherRg | ? { $_.Location -eq $nsg.Location }
}
# detect first viable storage account
$storageAccount = Get-AzStorageAccount | Where-Object { $_.StorageAccountName -match $storageNamePattern -and $_.PrimaryEndpoints.Blob -match "^http" } | Select-Object -First 1
# get or set NSG flow log if not yet established
$fl = Get-AzNetworkWatcherFlowLogStatus -NetworkWatcher $nw -TargetResourceId $nsg.Id
if (!$fl) {
# https://learn.microsoft.com/de-de/azure/network-watcher/network-watcher-nsg-flow-logging-powershell
Set-AzNetworkWatcherConfigFlowLog -NetworkWatcher $nw -TargetResourceId $nsg.Id -StorageAccountId $storageAccount.Id -EnableFlowLog $true -FormatType Json -FormatVersion 2
}

How to connect multiple Azure VMs to log analytics workspace using ARM template?

I can able to connect the Azure VM to the log analytics workspace using the ARM template(https://learn.microsoft.com/en-us/azure/azure-monitor/agents/resource-manager-agent) but I want to connect the multiple VMs at a time in one subscription and different resource groups to the log analytics workspace.
Is there any way to work around this?
If you want to add a bunch of VMs in a subscription to a log analytics workspace in Azure, we can use PowerShell command Set-AzVMExtension to implement it.
For example
# all windows VMs in the subscription (which you set via Set-AzContext)
$PublicSettings = #{ "workspaceId" = "" }
$ProtectedSettings = #{ "workspaceKey" = "" }
# Using -Status switch to get the status too
Get-AzVM -Status | Where-Object{ $_.Powerstate -eq "VM running" -and $_.StorageProfile.OsDisk.OsType -eq "Windows" } | ForEach-Object {
$VMName = $_.Name
$ResourceGroupName = $_.ResourceGroupName
$Location = $_.Location
Write-Host "Processing $VMName"
Set-AzVMExtension -ExtensionName "MicrosoftMonitoringAgent" `
-ResourceGroupName "$ResourceGroupName" `
-VMName "$VMName" `
-Publisher "Microsoft.EnterpriseCloud.Monitoring" `
-ExtensionType "MicrosoftMonitoringAgent" `
-TypeHandlerVersion 1.0 `
-Settings $PublicSettings `
-ProtectedSettings $ProtectedSettings `
-Location "$Location"
}
For more details, please refer to here and here.

Azure Powershell (Az module) get public IP address

With the new Az module for Azure, does anyone have the syntax for getting the public IP address of an Azure VM using the name?
The commandlet Get-AzPublicIpAddress has no argument for the VM name, only the IP object name
This works, but I'm not using the machine name here, it's the name of the IP object itself:
$CurrentIp = (Get-AzPublicIpAddress -ResourceGroupName 'RG1' -Name 'MyVMname-ip').IpAddress
I can't figure out how to just get it from the VM object i.e. this doesn't work:
Get-AzVM -ResourceGroupName 'RG1' -Name 'MyVMname' | Get-AzPublicIpAddress
As I know, it's impossible to get the VM public IP through just one PowerShell Get-AzPublicIpAddress with the VM name. And the public IP in Azure is an individual resource associated with the network interface, not the VM.
As you see, there no parameter for VM name to get the public IP in that document. But you can get the public IP through a PowerShell script just with the VM name and resource group name. The script shows below:
$vm = Get-AzureRmVM -ResourceGroupName yourRG -Name vmNamme
$nic = $vm.NetworkProfile.NetworkInterfaces[0].Id.Split('/') | select -Last 1
$publicIpName = (Get-AzureRmNetworkInterface -ResourceGroupName yourRG -Name $nic).IpConfigurations.PublicIpAddress.Id.Split('/') | select -Last 1
$publicIpAddress = (Get-AzureRmPublicIpAddress -ResourceGroupName yourRG -Name $publicIpName).IpAddress
Write-Output $vmName $publicIpAddress
Or just one CLI command to get the public IP like this:
az vm show -d -g yourRG -n vmName --query publicIps
I think this is a more thorough answer, as this uses PowerShell Az as the original question intended to use. In addition, it leverages Generic.List[psobject] which is useful for later playing with the data.
$rg = 'RgName'
$Ips = Get-AzNetworkInterface -ResourceGroupName $rg
$vmDetails = New-Object "System.Collections.Generic.List[psobject]"
foreach ($instance in $Ips){
$Vm = ($instance.VirtualMachine).Id.Split('/') | select -Last 1
$PrivateIp = $instance.IpConfigurations.PrivateIpAddress
$PublicIp = (Get-AzPublicIpAddress -ResourceGroupName $rg -Name ($instance.IpConfigurations.publicIpAddress.Id.Split('/') | select -Last 1)).IpAddress
$obj = New-Object psobject -Property #{
ResourceGroupName = $rg
VmName = $vm
PrivateIp = $PrivateIp
PublicIp = $PublicIp
}
$vmDetails.Add($obj)
}
Write-Output $vmDetails
This isn't as straight forward as Az CLI unfortunately but a good script to have regardless for Az modules.
Here's my take on Andrew Harris' answer, it filters out network interfaces not attached to machines and accounts for VMs that don't have a public IP:
function Get-VmIP {
<#
.SYNOPSIS
Returns the IP addresses for all VMs in the current subscription.
#>
[cmdletbinding()]
param()
$Interfaces = Get-AzNetworkInterface
foreach ($Interface in $Interfaces) {
if ($Interface.VirtualMachine) {
$VMName = $Interface.VirtualMachine.Id.split('/')[-1]
$PrivateIP = $Interface.IpConfigurations.PrivateIpAddress
$PublicIP = if ($Interface.IpConfigurations.publicIpAddress) {
Get-AzPublicIpAddress -Name ($instance.IpConfigurations.publicIpAddress.Id.Split('/')[-1]).IpAddress
}
[PSCustomObject]#{
VMName = $VMName
RGName = $Interface.ResourceGroupName
PrivateIP = $PrivateIP
PublicIP = $PublicIP
}
}
}
}
This is a corrected version of the Mark Wragg's script earlier in this thread:
function Get-VmIP {
<#
.SYNOPSIS
Returns the IP addresses for all VMs in the current subscription.
#>
[cmdletbinding()]
param()
$Interfaces = Get-AzNetworkInterface
foreach ($Interface in $Interfaces) {
if ($Interface.VirtualMachine) {
$VMName = $Interface.VirtualMachine.Id.split('/')[-1]
$PrivateIP = $Interface.IpConfigurations.PrivateIpAddress
$PublicIpAddressConfig = $Interface.IpConfigurations.publicIpAddress
$PublicIP = $null
$pconfigname = $null
if ($PublicIpAddressConfig) {
$pconfigname = $PublicIpAddressConfig.Id.Split('/')[-1]
$PublicIP = (Get-AzPublicIpAddress -Name $pconfigname).IpAddress
}
[PSCustomObject]#{
VMName = $VMName
RGName = $Interface.ResourceGroupName
PrivateIP = $PrivateIP
PublicIP = $PublicIP
}
}
}
}
The accepted answer uses AzureRM PowerShell module which is now obsoleted by Az module:
$VM = Get-AzVM -ResourceGroupName $ResourceGroupName -VMName $VMName
$NetworkInterfaceName = $VM.NetworkProfile.NetworkInterfaces[0].Id.Split('/')[-1]
$NetworkInterface = Get-AzNetworkInterface -ResourceGroupName $VM.ResourceGroupName -Name $NetworkInterfaceName
$PublicIpAddressName = $NetworkInterface.IpConfigurations.PublicIpAddress.Id.Split('/')[-1]
$PublicIpAddress = Get-AzPublicIpAddress -ResourceGroupName $VM.ResourceGroupName -Name $PublicIpAddressName
Write-Host "IP: $($PublicIpAddress.IpAddress), FQDN: $($PublicIpAddress.DnsSettings.Fqdn)"
Scope of the script is within an Azure subscription.
Below is the one-liner script which returns Name, PublicIpAllocaitonMethod(It's basically the type of the IP address whether it's a Static or Public IP) and the IpAddress properties of all the Network interfaces in a subscription.
(Get-AzNetworkInterface ).IpConfigurations.PublicIpAddress.Id | Foreach-Object -Process {$_.Split('/')| select -Last 1} | Foreach-Object -Process {Get-AzPublicIpAddress -Name $_} | Format-List Name, PublicIpAllocationMethod,IpAddress
If we remove the last statement Format-List it will display all the properties of the network interfaces that are having public IP addresses.

Resources