I am pretty much new to PowerShell and we have customer requirement that they will share Azure VM details in Excel sheet with below columns.
we have to get VM Status details from all the subscriptions & ResourceGroup using the Powershell script.
Outuput:
I am able to perform for single RSG and VM values by using the below code
$SubscriptionName = Get-AzSubscription -SubscriptionId $subscriptionId
$RG = "rgp-use2-prd-bioportalbiopeople1"
$RSGName = Get-AzResourceGroup -Name $RG
$VMs = Get-AzVM -Name "vmbppapiv1prd02"
$VMState = (Get-AzVM -Name $VM -ResourceGroupName $RG -Status).Statuses
$vmOutput = $VMs | ForEach-Object {
[PSCustomObject]#{
"Resource Group Name" = $RSGName.ResourceGroupName
"Subscription Name" = $SubscriptionName.Name
"VM Name" = $_.Name
"VM Type" = $_.StorageProfile.osDisk.osType
"VM Statss" = ($VMState | where code -Like 'PowerState/*')[0].DisplayStatus
}
}
$vmOutput | Format-Table -AutoSize
$vmOutput | export-csv C:\Projects\data.csv
I can't test this myself, but you will have to create nested loops to get the details for all subscriptions and resourcegroups.
Something like this:
$subscriptions = Get-AzSubscription -TenantId "aaaa-aaaa-aaaa-aaaa" # enter the tenant ID here
$VMs = Get-AzVM -Name "vmbppapiv1prd02"
$vmOutput = foreach ($vm in $VMs) {
foreach ($subscription in $subscriptions) {
Set-AzContext -SubscriptionId $subscription.Id
(Get-AzResourceGroup).ResourceGroupName | ForEach-Object {
$vmState = (Get-AzVM -Name $vm.Name -ResourceGroupName $_ -Status).Statuses
[PSCustomObject]#{
"Resource Group Name" = $_
"Subscription Name" = $Subscription.Name
"VM Name" = $vm.Name
"VM Type" = $vm.StorageProfile.osDisk.osType
"VM Status" = ($vmState | where code -Like 'PowerState/*')[0].DisplayStatus
}
}
}
}
$vmOutput | Format-Table -AutoSize
$vmOutput | Export-Csv -Path 'C:\Projects\data.csv' -NoTypeInformation
A bit stuck on this one. Going in circles trying to get the NSG Ids listed out for each and every subnet in Azure. It's part of a security control requirement, so we need to list each subnet and then provide the NSG Id with them - to show that each subnet does in fact have an NSG associated with it.
$vnets = (Get-AzVirtualNetwork).Name
$nsgId = (Get-AzVirtualNetwork).Subnets.NetworkSecurityGroup.Id
$snet = (Get-Azvirtualnetwork).Subnets.Name | Out-String
foreach ($vnet in $vnets) {Get-AzVirtualNetworkSubnetConfig -Name $snet -VirtualNetwork $vnets | FL Name,$nsgId}
This is the error I am getting. Just can't get past it.
Get-AzVirtualNetworkSubnetConfig: Cannot convert 'System.Object[]' to the type 'Microsoft.Azure.Commands.Network.Models.PSVirtualNetwork' required by parameter 'VirtualNetwork'. Specified method is not supported.
This should do it.
$vnets = (Get-AzVirtualNetwork)
$objectArr = #()
foreach ($vnet in $vnets) {
foreach ($subnet in $vnet.Subnets) {
if ($subnet.NetworkSecurityGroup -ne $null) {
$NSG = Get-AzResource -ResourceId $subnet.NetworkSecurityGroup.Id
$prop = [ordered]#{
'VNETName' = $vnet.Name
'SubnetName' = $subnet.Name
'NSGName' = $NSG.Name
'Id' = $NSG.Id
}
$obj = New-Object -Type PSCustomObject -Property $prop
$objectArr += $obj
}
}
}
$objectArr | Select-object VNETName, SubnetName, NSGName, Id
I have a script that outputs all of my subscription's VM IPs. The problem I want to solve is getting the subscription name in the output. Currently, the script goes through all subscriptions and returns VM Name, resource group, internal/external IPs, etc. But no matter what I try, I can't get the output to also return the subscription name. I can get the field to populate with the subscription heading, but the fields are blank.
My ultimate goal is to get all VMs with public addresses use to audit NSG rules, but include subscription names as well.
Any ideas?
$reportName = "AzVMIPs.csv"
Get-AzSubscription | Select-AzSubscription | ForEach-Object {$_
$report = #()
$vms = Get-AzVM
$publicIps = Get-AzPublicIpAddress
$nics = Get-AzNetworkInterface | ?{ $_.VirtualMachine -NE $null}
foreach ($nic in $nics) {
$info = "" | Select-Object VmName, ResourceGroupName, Region, VirturalNetwork, Subnet, PrivateIpAddress, OsType, PublicIPAddress
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
foreach($publicIp in $publicIps) {
if($nic.IpConfigurations.id -eq $publicIp.ipconfiguration.Id) {
$info.PublicIPAddress = $publicIp.ipaddress
}
}
$info.OsType = $vm.StorageProfile.OsDisk.OsType
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.Region = $vm.Location
$info.VirturalNetwork = $nic.IpConfigurations.subnet.Id.Split("/")[-3]
$info.Subnet = $nic.IpConfigurations.subnet.Id.Split("/")[-1]
$info.PrivateIpAddress = $nic.IpConfigurations.PrivateIpAddress
$report+=$info
}
$report | Export-CSV "$home\$reportName" -NoTypeInformation -Append
}
Thanks,
If you want to get subscription Name in your report, please refer to the following script
$reportName = "AzVMIPs.csv"
(Get-AzSubscription)|ForEach-Object{
Select-AzSubscription $_
$report = #()
$vms = Get-AzVM
$publicIps = Get-AzPublicIpAddress
$nics = Get-AzNetworkInterface | ?{ $_.VirtualMachine -NE $null}
foreach ($nic in $nics) {
$info = "" | Select-Object VmName, ResourceGroupName, Region, VirturalNetwork, Subnet, PrivateIpAddress, OsType, PublicIPAddress, SubscriptionName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
foreach($publicIp in $publicIps) {
if($nic.IpConfigurations.id -eq $publicIp.ipconfiguration.Id) {
$info.PublicIPAddress = $publicIp.ipaddress
}
}
$info.OsType = $vm.StorageProfile.OsDisk.OsType
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.Region = $vm.Location
$info.VirturalNetwork = $nic.IpConfigurations.subnet.Id.Split("/")[-3]
$info.Subnet = $nic.IpConfigurations.subnet.Id.Split("/")[-1]
$info.PrivateIpAddress = $nic.IpConfigurations.PrivateIpAddress
$info.SubscriptionName=$_.Name
$report+=$info
}
$report | Export-CSV "$home\$reportName" -NoTypeInformation -Append
}
I modified the code a bit and it reports Subscription name also. Please try it yourself
$reportName = "D:\AzVMIPs.csv"
Get-AzSubscription | Select-AzSubscription | ForEach-Object {$_
$report = #()
$vms = Get-AzVM
$publicIps = Get-AzPublicIpAddress
$nics = Get-AzNetworkInterface | ?{ $_.VirtualMachine -NE $null}
foreach ($nic in $nics) {
$info = "" | Select-Object VmName, ResourceGroupName, Region, VirturalNetwork, Subnet, PrivateIpAddress, OsType, PublicIPAddress, SubscriptionName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
foreach($publicIp in $publicIps) {
if($nic.IpConfigurations.id -eq $publicIp.ipconfiguration.Id) {
$info.PublicIPAddress = $publicIp.ipaddress
}
}
$info.OsType = $vm.StorageProfile.OsDisk.OsType
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.Region = $vm.Location
$info.VirturalNetwork = $nic.IpConfigurations.subnet.Id.Split("/")[-3]
$info.Subnet = $nic.IpConfigurations.subnet.Id.Split("/")[-1]
$info.PrivateIpAddress = $nic.IpConfigurations.PrivateIpAddress
$info.SubscriptionName = (Get-AzContext).Name
$report+=$info
}
$report | Export-CSV "D:\1.CSV" -NoTypeInformation -Append
}
Thanks,
Manu
Azure Resource Graph (ARG) can be used as well. Its main advantage is that it will output all the VMs across all subscriptions within a tenant, quite fast. Eg for several thousand VMs across hundreds of subscriptions, it takes a matter of seconds to have the output file.
The script further down will report correctly on multiple vmNics and multiple IP configurations per vmNic. If running from either a local Powershell session or Cloud Shell, make sure you have the Az.ResourceGraph module installed first.
A sample report ran against my test tenant:
The script will only report the first 5,000 VMs in the tenant in its current form. For a version that doesn't have such limitations, including being able to report across more than 1,000 Azure subscriptions, the script here can be used, by just swapping out the ARG query with the one seen below.
As for building a very similar Azure Resource Graph query like the one used in the script - which might look cryptic at first - this is described at length here.
$reportName = "AzVMIPs.csv"
$ARG_query = #"
resourcecontainers
| where type =~ 'microsoft.resources/subscriptions'
| project id, subscriptionId, subscriptionName = name
| join (Resources
| where type =~ 'microsoft.compute/virtualmachines'
| project vmId = tolower(tostring(id)), vmName = name, subscriptionId
| join (Resources
| where type =~ 'microsoft.network/networkinterfaces'
| mv-expand ipconfig=properties.ipConfigurations
| project vmId = tolower(tostring(properties.virtualMachine.id)), privateIp = ipconfig.properties.privateIPAddress, publicIpId = tostring(ipconfig.properties.publicIPAddress.id)
| join kind=leftouter (Resources
| where type =~ 'microsoft.network/publicipaddresses'
| project publicIpId = id, publicIp = properties.ipAddress
) on publicIpId
| project-away publicIpId, publicIpId1
| summarize privateIps = make_list(privateIp), publicIps = make_list(publicIp) by vmId
) on vmId
| project-away vmId1
| sort by vmName asc
) on subscriptionId
| project-away subscriptionId1
"#
$results = Search-AzGraph -Query $ARG_query -First 5000
$results | Select-Object -ExcludeProperty ResourceId | Export-CSV "$home\$reportName" -NoTypeInformation
I wrote a powershell script in Azure DevOps pipeline to get Load Balancer details like FrontendIPConfigurationsName,FrontendIPAddress in to csv file. AM getting those details but FrontendIPConfigurationsNames which starts with same name like "ers-A1,ers-B1,ers-C1,ers-D1" are coming in same row. But I want to get them in different rows.Please suggest
$excel = #()
LBlist = Get-AZLoadBalancer | Where-Oject {$_.ResourceGroupName -clike '$(grp-wildcard)'} | Select-Object
foreach ($LB in LBlist)
$Array =""| Select-Object ResourceGroupName, FrontendIPConfigurationsName,FrontendIPAddress
$Array.ResourceGroupName =$LB.ResourcegroupName
$Array.FrontendIPConfigurationsName = ($LB.FrontendIpConfigurationsName.name -join ',')
$Array.FrontendIPAddress =($LB.FrontendIpConfigurations.PrivateIpAddress -join ',')
}
$excel +=$Array
$excel |Format-Table ResourceGroupName, FrontendIPConfigurationsName,FrontendIPAddress
$excel | Export-Csv -NTI -Path "($Build.ArtifactStagingDirectory)/LBlist.csv
You can do something similar to this to get the objects on separate rows.
$LBlist = Get-AZLoadBalancer | Where-Object { $_.ResourceGroupName -clike '$(grp-wildcard)' }
$LBlist | Export-Csv -NTI -Path "$(Build.ArtifactStagingDirectory)/LBlist.csv"
Mock for Get-AZLoadBalancer (not sure if it's entirely accurate as I've never used Az Powershell)
function Get-AZLoadBalancer() {
$obj = #(
[PSCustomObject] #{
ResourceGroupName = '$(grp-wildcard)'
FrontendIPConfigurationsName = 'ers-A1'
FrontEndIPAddress = '1.2.3.4'
},
[PSCustomObject] #{
ResourceGroupName = '$(grp-wildcard)'
FrontendIPConfigurationsName = 'ers-B1'
FrontEndIPAddress = '1.2.3.5'
}
)
return $obj
}
I have been able to export out VM Names and IP Addresses from within a single azure subscription using the following script.
$report = #()
$vms = get-azvm
$nics = get-aznetworkinterface | ?{ $_.VirtualMachine -NE $null}
foreach($nic in $nics)
{
$info = "" | Select VmName, ResourceGroupName, HostName, IpAddress
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.IpAddress = $nic.IpConfigurations.PrivateIpAddress
$info.HostName = $vm.OSProfile.ComputerName
$report+=$info
}
$report | Export-Csv -Path "c:\Azure\VMIPs.csv"
However I have tried using the below to export the same data from an azure account that has multiple subscriptions but all I get is a blank CSV file.
$report = #()
$vms = get-azvm
$azureSubs = get-azsubscription
$azureSubs.foreach{
Select-AzSubscription $_ # << change active subscription
$nics = get-aznetworkinterface | ?{ $_.VirtualMachine -NE $null}
foreach($nic in $nics)
{
$info = "" | Select VmName, ResourceGroupName, HostName, IpAddress
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.IpAddress = $nic.IpConfigurations.PrivateIpAddress
$info.HostName = $vm.OSProfile.ComputerName
$report+=$info
}
}
$report | Export-Csv -Path "c:\Azure\VMIPs.csv"
Can anyone assist?
I think you need to move Get-AzVm right after the Select-AzSubscription? because right now you only get vms once (in default subscription)
$azureSubs.foreach{
Select-AzSubscription $_ # << change active subscription
$nics = get-aznetworkinterface | ?{ $_.VirtualMachine -NE $null}
$vms = get-azvm
...
}