Azure Powershell (Az module) get public IP address - azure

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.

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
}
}
}

When I create a new VM using Azure Powershell I get no public IP Address. Why?

I just started playing around with Azure Powershell and I'm trying to create a new Azure VM.
Script:
$username = 'demoadmin'
$password = ConvertTo-SecureString 'Password123!##' -AsPlainText -Force
$WindowsCred = New-Object System.Management.Automation.PSCredential ($username, $password)
New-AzVM -ResourceGroup 'psdemo-rg-uksouth' -Name 'psdemo-win-az' -Image 'win2016datacenter' -Size 'Standard_D2ads_v5' -Credential $WindowsCred -OpenPorts 3389
Result: Azure VM is successfully created, but there is no Public IP address assigned.
Looking at the documentation here I can see the description for parameter "PublicIpAddressName": "The name of a new (or existing) public IP address for the created VM to use. If not specified, a name will be generated.".
How can I make it assign a Public IP Address on creation?
When I run the PowerShell commands you provided, yes - it is not provisioned the Public IP address, but it will be assigned the Private IP Address by Azure dynamically.
If you do not pass the PublicIpAddressName parameter, then it will not be created automatically:
Following these MSFT Doc1 & Doc 2, we have to pass the Public IP Address parameter to get assigned to the associated Virtual Machine by Azure.
PowerShell Script I used to get the Public IP Address while VM Creation in Azure:
#Create the Virtual Network
$vnet = #{
Name = 'myVNet'
ResourceGroupName = 'HariTestRg'
Location = 'EastUS'
AddressPrefix = '10.0.0.0/16'
}
$virtualNetwork = New-AzVirtualNetwork #vnet
#Create the Subnet
$subnet = #{
Name = 'default'
VirtualNetwork = $virtualNetwork
AddressPrefix = '10.0.0.0/24'
}
$subnetConfig = Add-AzVirtualNetworkSubnetConfig #subnet
$virtualNetwork | Set-AzVirtualNetwork
#Create the Virtual Machine by passing the Public IP Address parameter
$username = '<your-user-name>'
$password = ConvertTo-SecureString '<your-password>' -AsPlainText -Force
$WindowsCred = New-Object System.Management.Automation.PSCredential ($username, $password)
New-AzVm `
-ResourceGroupName "HariTestRg" `
-Name "psdemo-win-az02" `
-Location "EastUS" `
-VirtualNetworkName "myVnet" `
-SubnetName "default" `
-SecurityGroupName "myNetworkSecurityGroup" `
-PublicIpAddressName "myPublicIpAddress2" `
-ImageName "MicrosoftWindowsServer:WindowsServer:2016-Datacenter-with-Containers:latest" `
-Credential $WindowsCred
Result:

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
}

Azure Powershell - Applying multiple service endpoints to a subnet

I have coded a powershell script to set an existing subnet to function as a service endpoint for multiple services. However, when I run the command line in the script, it doesn't add a new service endpoint, it just changes the existing one.
I am trying to parameterise this through Jenkins as well, which may be an added complication. I think if I can get the base syntax right then that shouldn't be a problem.
Syntax I am using is:
#Get vnet
$virtualnetwork = Get-AzureRmVirtualNetwork -Name $VN -ResourceGroupName $RG
#Configure service endpoint
Add-AzureRmVirtualNetworkSubnetConfig -Name $SN -AddressPrefix $SAP -
VirtualNetwork $virtualnetwork -ServiceEndpoint $EP
#Set configuration
$virtualnetwork | Set-AzureRmVirtualNetwork
You can use something like this to add as many endpoints as required:
$rgname = "amgar-dtl"
$vnName = "Dtlamgar-dtl"
$sname = "Dtlamgar-dtlSubnet"
$subnetPrefix = "10.0.0.0/20"
#Get vnet
$VirtualNetwork = Get-AzureRmVirtualNetwork -ResourceGroupName $rgname -Name $vnName | Get-AzureRmVirtualNetworkSubnetConfig -Name $sname
#Get existing service endpoints
$ServiceEndPoint = New-Object 'System.Collections.Generic.List[String]'
$VirtualNetwork.ServiceEndpoints | ForEach-Object { $ServiceEndPoint.Add($_.service) }
#Add new service endpoint
Get-AzureRmVirtualNetwork -ResourceGroupName $rgname -Name $vnName | Set-AzureRmVirtualNetworkSubnetConfig -Name $sname -AddressPrefix $subnetPrefix -ServiceEndpoint $ServiceEndPoint.Add("Microsoft.KeyVault") | Set-AzureRmVirtualNetwork
Hope this helps!
Successful syntax is:
#Vnet
$VN = "$ENV:VNET_NAME"
#Resource Group
$RG = "$ENV:RESOURCEGROUP_NAME"
#Subnet
$SN = "$ENV:SUBNET_NAME"
#Subnet Address Prexifx
$SAP = "$ENV:ADDRESS_PREFIX"
#ServiceEndpoint
$EP = "$ENV:SERVICE_ENDPOINT"
Write-Host "Importing the AzureRM module into the PowerShell session"
Import-Module AzureRM
Write-Host "Connect service principle account to Azure RM"
Connect-AzureRmAccount -ServicePrincipal -Credential $CREDS -TenantId $TID -Subscription $SID
#Get vnet
$VirtualNetwork = Get-AzureRmVirtualNetwork -ResourceGroupName $RG -Name $VN | Get-AzureRmVirtualNetworkSubnetConfig -Name $SN
#Get existing service endpoints
$ServiceEndPoint = New-Object 'System.Collections.Generic.List[String]'
$VirtualNetwork.ServiceEndpoints | ForEach-Object { $ServiceEndPoint.Add($_.service) }
$ServiceEndPoint.Add($EP)
#Add new service endpoint
Get-AzureRmVirtualNetwork -ResourceGroupName $RG -Name $VN | Set-AzureRmVirtualNetworkSubnetConfig -Name $SN -AddressPrefix $SAP -ServiceEndpoint $ServiceEndPoint | Set-AzureRmVirtualNetwork
Powershell does not appear to support the command $ServiceEndPoint.Add("Microsoft.KeyVault") with “|”. Once it was executed separately, the script worked.
Here is another version for those looking to process multiple subnets and to validate that the subnet doesn't already have the service endpoint enabled because it will error out if the same service is listed twice when modifying the subnet.
$subscription = "Enter Subscription ID here"
$subnets = #('my-subnet-1','my-subnet-2','my-subnet-3')
$vnetName = "MY-VNET"
$vnetRgName = "MY-VNET-RG"
$newEndpoint = "Microsoft.AzureCosmosDB"
Set-AzContext -Subscription $subscription
foreach($snet in $subnets){
Write-Host "Modifying Service Endpoints for subnet: $snet" -fore red -back white
$virtualNetwork = Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $vnetRgName | Get-AzVirtualNetworkSubnetConfig -Name $snet
$addrPrefix = $virtualNetwork.AddressPrefix
#Get existing service endpoints
$ServiceEndPoint = New-Object 'System.Collections.Generic.List[String]'
$virtualNetwork.ServiceEndpoints | ForEach-Object { $ServiceEndPoint.Add($_.service) }
if ($ServiceEndPoint -notcontains $newEndPoint){
$ServiceEndPoint.Add($newEndpoint)
}
#Add new service endpoint
Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $vnetRgName | Set-AzVirtualNetworkSubnetConfig -Name $snet -AddressPrefix $addrPrefix -ServiceEndpoint $ServiceEndPoint | Set-AzVirtualNetwork
}

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

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 :-)

Resources