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
Related
Hi I'm trying to get vnet peering property using a Powershell script.
But I keep getting these values in teh table below, but when I print to screen they print fine.
These are values I keep getting:
RemoteVirtualNetwork
Microsoft.Azure.Commands.Network.Models.PSResourceId
RemoteVirtualNetworkAddressSpace
Microsoft.Azure.Commands.Network.Models.PSAddressSpace
#Login-AzAccount
$Subs = Get-AzSubscription
foreach ( $Sub in $Subs ) {
Set-AzContext -Subscription $Sub | Out-Null
$SubName = $sub.name
$vnets=get-azvirtualnetwork
foreach ($azvnet in $vnets){
$peer=get-AzVirtualNetworkPeering -VirtualNetworkName $azvnet.name -ResourceGroup $azvnet.ResourceGroupName | select-object ResourceGroupName,VirtualNetworkName,PeeringState,AllowVirtualNetworkAccess,AllowGatewayTransit,UseRemoteGateways,RemoteVirtualNetwork,RemoteVirtualNetworkAddressSpace
ForEach-Object{
New-Object PSObject -Property #{
ResourceGroupName = $peer.ResourceGroupName
VirtualNetworkName= $peer.VirtualNetworkName
PeeringState = $peer.PeeringState
PeeringSyncLevel = $peer.PeeringSyncLevel
AllowVirtualNetworkAccess = $peer.AllowVirtualNetworkAccess
AllowForwardedTraffic = $peer.AllowForwardedTraffic
AllowGatewayTransit = $peer.AllowGatewayTransit
UseRemoteGateways = $peer.UseRemoteGateways
RemoteVirtualNetwork = $peer.RemoteVirtualNetwork.Id.Split("/")[-1]
RemoteGateways = $peer.RemoteGateways
PeeredRemoteAddressSpace = $peer.PeeredRemoteAddressSpace
RemoteVirtualNetworkAddressSpace = $peer.RemoteVirtualNetworkAddressSpace | Select-Object -ExpandProperty AddressPrefixes
}
}
$peer|export-csv -path c:\personal\peers04.csv
}
}
Hi I'm trying to get disk information alongside network information for azure virtual machines.
I'm probably doing something silly, but I thought it would be a case of adding the vm into the network foreach loop.
I've put the script below, can anyone see where I'm going wrong?
$reportName = "sample.csv"
$report = #()
$vms = Get-AzVM
$publicIps = Get-AzPublicIpAddress
$nics = Get-AzNetworkInterface | ?{ $_.VirtualMachine -NE $null}
foreach ($nic in $nics) {
$info = "" | Select VmName, ResourceGroupName, Region, VmSize, VirturalNetwork, Subnet, DnsServers, NicDns, PrivateIpAddress, OsType, OSDisk, DiagDisk, DataDisk, PublicIPAddress, vCPU, Memory
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
foreach($publicIp in $publicIps) {
if($nic.IpConfigurations.id -eq $publicIp.ipconfiguration.Id) {
$info.PublicIPAddress = $publicIp.ipaddress
}
}
#$location = $vm.location
$info.OsType = $vm.StorageProfile.OsDisk.OsType
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.Region = $vm.Location
$info.VmSize = $vm.HardwareProfile.VmSize
$size = $info.VmSize = $vm.HardwareProfile.VmSize
$info.vCPU = (Get-AzVMSize -Location $location | ? {$_.name -eq $size}).NumberOfCores
$info.Memory = (Get-AzVMSize -Location $location | ? {$_.name -eq $size}).MemoryInMB
$info.VirturalNetwork = $nic.IpConfigurations.subnet.Id.Split("/")[-3]
$info.Subnet = $nic.IpConfigurations.subnet.Id.Split("/")[-1]
$info.PrivateIpAddress = $nic.IpConfigurations.PrivateIpAddress
$vm = get-azvm | ? {$_.name -eq $vm}
foreach ($vms in $vm) {
$info.OSDiskSizeGB = $vm.StorageProfile.OsDisk.DiskSizeGB
$info.OSDisk = $vm.StorageProfile.OsDisk.Vhd.uri
$info.DiagDisk = $vm.DiagnosticsProfile.BootDiagnostics.StorageUri
$info.DataDisk = $vm.StorageProfile.DataDisks.vhd.uri -join "**"
}
$report+=$info
}
$report | ft VmName, ResourceGroupName, Region, VmSize, VirturalNetwork, Subnet, DnsServers, NicDns, PrivateIpAddress, OsType, OSDisk, DiagDisk, DataDisk, PublicIPAddress, vCPU, Memory
$report | Export-CSV "c:\temp\$reportName"
Thanks in advance :)
EDIT:
This is the output I get, no disk infor for any VM
VmName ResourceGroupName Region VmSize VirturalNetwork Subnet DnsServers NicDns PrivateIpAddress OsType OSDisk DiagDisk DataDisk PublicIPAddress vCPU Memory
------ ----------------- ------ ------ --------------- ------ ---------- ------ ---------------- ------ ------ -------- -------- --------------- ---- ------
vmr1-sec1 DEPLOYRG1 westeurope Standard_D2_v4 av-vnet av-sub2 172.0.2.4 Windows 2 8192
vmr2-sec1 DEPLOYRG1 westeurope Standard_D2_v4 av-vnet av-sub2 172.0.2.5 Windows 2 8192
cks-cp1 K8S westeurope Standard_B2s K8S-vnet default 10.0.0.4 Linux 20.71.120.71 2 4096
At the moment, Azure uses Azure managed disk in default. Azure managed disks are no longer stored into blob storage by default. For more details, please refer to here and here. if you want to get the vhd URL of Azure managed disk, you need to run the command Grant-AzDiskAccess to get it. But please note that the URL has a life cycle and will expire after a period of time
So I suggest you store your disk name or disk id in your CSV file
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 want to add StorageAccountName and its SKU to my report, this is the code I'm having now:
VMs = Get-AzureRmVM -Status
$vmOutput = $VMs | ForEach-Object {
[PSCustomObject]#{
"VM Name" = $_.name
"Private IP" =""
"VM Type" = $_.StorageProfile.osDisk.osType
"VM Profile" = $_.HardwareProfile.VmSize
"Environment" = $_.Tags.Environment
"Application" = $_.Tags.Application
"Decommission Date" = $_.Tags.Decomission
"OS Disk Size" = $_.StorageProfile.OsDisk.DiskSizeGB
"Data Disks Total Size" = ($_.StorageProfile.DataDisks.DiskSizeGB | Measure -Sum).Sum
"Data Disks Amount" = ($_.StorageProfile.DataDisks | Measure ).Count
"Managed OS Disk" = ($_.StorageProfile.OSDisk.ManagedDisk | Measure).Count
"Managed Data Disks" = ($_.StorageProfile.DataDisks.ManagedDisk | Measure).Count
"Powerstate" = $_.PowerState
}
}
$nics = get-azurermnetworkinterface | where VirtualMachine -NE $null
$ips =#{}
foreach($nic in $nics){
$vm = $VMs | Where-Object -Property id -EQ $nic.VirtualMachine.id
$prv = $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAddress
$ips.Add($vm.Name,$prv)
}
foreach($vm in $vmOutput)
{
if($ips.ContainsKey($vm."VM Name"))
{
$vm."Private IP"=$ips[$vm."VM Name"]
}
}
$vmOutput | sort "Environment", "VM Type", "VM Profile", "Application" | export-csv VMReport.csv -delimiter ";" -force -notypeinformation
I tried to do it more less the same way IP addresses were implemented into this code, but it's much harder than I expected, as Get-AzureRmStorageAccount cmdlet doesn't store VirtualMachine.Id property like Get-AzureRMNetworkInterface cmdlet does.
Any ideas how can I merge it into one table? Is there any key upon which I can join both information? What I want to achieve is to add StorageAccountName and SKUName columns into the $vmOutput table.
Update:
$sat =#{}
$OutFile = "..."
#part1
foreach ($vmdetails in $VMs)
{
$ResourceGroupName=$vmdetails.ResourceGroupName
$VMName=$vmdetails.name
$storage=$vmdetails.StorageProfile.OsDisk.Vhd.Uri
$DataDiks=$vmdetails.StorageProfile.OsDisk.Name
$ss=$storage.split('/')[2]
$OSStorageAccountName=$ss.split('.')[0]
$DiskType="OSDisk"
$StroageAccountLocation=($StroageAccDetail | where {$_.StorageAccountName -eq $OSStorageAccountName }).location
$StorageAccountType=($StroageAccDetail | where {$_.StorageAccountName -eq $OSStorageAccountName }).AccountType
"$sub,$ResourceGroupName,$VMName,$DataDiks,$DiskType,$OSStorageAccountName" | Out-File -FilePath $OutFile -Append
$vmdatadisks=$vmdetails.StorageProfile.DataDisks
if($vmdatadisks -ne $null){
foreach($vmDatadsik in $vmdatadisks)
{
$vmDatadsikss=$vmDatadsik.vhd.uri
$DiskType="DataDisk"
$ss=$vmDatadsikss.split('/')[2]
$DataDiks=$vmDatadsik.Name
$dataStorageAccountName=$ss.split('.')[0]
"$sub,$ResourceGroupName,$VMName,$DataDiks,$DiskType,$OSStorageAccountName" | Out-File -FilePath $OutFile -Append
}
}
}
#part2
$VMs = Get-AzureRmVM -ResourceGroupName "..." -Name "..."
$storageAccountName = $VMs.StorageProfile.OsDisk.Vhd.Uri.Split("/")[2].Split(".")[0]
Get-AzureRmStorageAccount -StorageAccountName $storageAccountName -ResourceGroupName "..."
Please correct me if I'm misunderstanding you.
Assume the sku you refer to the account storage's sku, you can also add placeholders in the $vmOutput for SA Name and SKUName.
$VMs = Get-AzureRmVM -Status
$vmOutput = $VMs | ForEach-Object {
[PSCustomObject]#{
"VM Name" = $_.name
"ResourceGroupName" =$_.ResourceGroupName #you must include this parameter
"storage" = $_.StorageProfile.OsDisk.Vhd.Uri #you must include this parameter
#your other property
#add placeholder for SA Name and SKUName like below
"StorageAccountName" =""
"StorageAccountSKUName" =""
}
}
Then, iterate all the vms in $vmoutput, and find the related storage account and sku, then add value to the $vmoutput:
foreach($v in $vmOutput){
$resourceGroups = $v.ResourceGroupName
$storage=$v.storage
if($storage -ne $null)
{
$ss=$storage.split('/')[2]
$OSStorageAccountName=$ss.split('.')[0]
$s1 = Get-AzureRmStorageAccount -ResourceGroupName $resourceGroups -StorageAccountName $OSStorageAccountName
#add the value to $vmoutput
$v.StorageAccountName =$OSStorageAccountName
$v.StorageAccountSKUName=$s1.Sku.name
}
else
{
$v.StorageAccountName ="no value"
$v.StorageAccountSKUName="no value"
}
}
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
...
}