Output of Azure subnets with links to attached VNet, route table and NSG - azure

I'm currently working on a script that gives me the output of every Subnet in an Azure Subscription, with links to the VNet, NSG, and the Route Table. The Route Table Name is currently missing in the script, but I want to focus on fixing the NSG right now.
This is what my Script looks like:
$VNets = Get-AzVirtualNetwork
$NSG = Get-AzNetworkSecurityGroup
$VNets | ForEach-Object {
$VNettemp = $_
$result = $_.Subnets | Select-Object #{Label="Subnet Name";Expression={$_.Name}},#{Label="Subnet";Expression={$_.AddressPrefix}}
$_ | ForEach-Object {
$result | Add-Member -Name "VNet Name" -Value $_.Name -MemberType NoteProperty
}
if ($_.Subnets.NetworksecurityGroup -ne "null"){
$NSG | ForEach-Object{
if ($VNettemp.Subnets.Id -contains $_.Subnets.Id ){
$result | Add-Member -Name "NSG Name" -Value $_.name -MemberType NoteProperty -Force
}
}
}
return $result
}
The output looks like this:
Subnet Name Subnet VNet Name NSG Name
----------- ------ --------- --------
default-subnet 10.10.10.0/28 vnet-ine-test test-nsg
vnet-ine-test-snet-test 10.10.0.0/24 vnet-ine-test test-nsg
default 10.0.0.0/24 vnet-chn-docker vnet-chn-docker-nsg
vnet-test-subnet 10.0.1.0/24 vnet-chn-docker vnet-chn-docker-nsg
The desired output would look like this because 'default-subnet' and 'vnet-test-subnet' have no NSG attached:
Subnet Name Subnet VNet Name NSG Name
----------- ------ --------- --------
default-subnet 10.10.10.0/28 vnet-ine-test
vnet-ine-test-snet-test 10.10.0.0/24 vnet-ine-test test-nsg
default 10.0.0.0/24 vnet-chn-docker vnet-chn-docker-nsg
vnet-test-subnet 10.0.1.0/24 vnet-chn-docker
Does anybody know how to fix the output? I tried it with an else statement that fills in an empty value for "NSG Name" but then the name gets canceled entirely for the whole VNet.
Thanks for the Help!

Regarding the issue, please refer to the following script
$VNets = Get-AzVirtualNetwork
$NSG = Get-AzNetworkSecurityGroup
$resports=#()
$info = #{ "Subnet Name"=""; "Subnet"=""; "VNet Name"="" ; "NSG Name"=""}
foreach($VNet in $VNets){
$info.'VNet Name'=$VNet.Name
$info.'NSG Name'=$null
Foreach($sub in $VNet.Subnets){
$info.'Subnet Name' =$sub.Name
$info.Subnet=$sub.AddressPrefix
if($sub.NetworkSecurityGroup -ne $null){
$NSG | ForEach-Object{
if ($VNet.Subnets.Id -contains $_.Subnets.Id ){
$info.'NSG Name'=$_.Name
}
}
}
$obj=New-Object PSObject -Property $info
$resports +=$obj
}
}

Related

How to find and Delete orphan public ip in azure using powershell

How to list and remove unused (orphanip) public ip address "such as search if the ip is not associated to any Vm or Networkinterface card find and then delete" in azure using powershell azure automation runbook.
Getting this error "Method 'get_SerializationSettings' in type 'Microsoft.Azure.Management.Internal.Resources.ResourceManagementClient' from assembly 'Microsoft.Azure.Commands.ResourceManager.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' does not have an implementation."
Run Login-AzureRmAccount to login.
[CmdletBinding(SupportsShouldProcess=$true,
   ConfirmImpact="High")]
Param
(
# Specifies the name of the resource group from which Public IP Addresses are to be retrieved.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string]$ResourceGroup,
# Only lists Azure Network Interfaces that are not linked to an existing Azure Virtual Machine
[switch]$ListOnly
)
Begin
{
If (AzureRmResourceGroup -Name $ResourceGroup -ErrorAction SilentlyContinue )
{
$az_publicipaddress = Get-AzureRmPublicIpAddress -ResourceGroupName $ResourceGroup
$RemAzPublicIP = $az_publicipaddress | Where-Object {$_.IpConfiguration -eq $null}
}
Else
{
Write-Error "Provided resource group does not exist: $ResourceGroup"
Throw
}
}
Process
{
$removed = #()
If ($PSBoundParameters.ContainsKey("ListOnly"))
{
$RemAzPublicIP | Select-Object Name,ResourceGuid
}
Else
{
ForEach($pi in $RemAzPublicIP)
{
if ($pscmdlet.ShouldProcess("Deleting NetworkInterface $($pi.Name)"))
{
Write-Output "Removing Public IP Address without Virtual Machine association: $($pi.Name)"
  Remove-AzureRmPublicIpAddress -Name "$($pi.name)" -ResourceGroupName $ResourceGroup
$object = New-Object -TypeName PSObject
$object | Add-Member -MemberType NoteProperty -Name Name -Value $($pi.Name)
$object | Add-Member -MemberType NoteProperty -Name ResourceGuid -Value $($pi.ResourceGuid)
$removed += $object
}
}
}
}
End
{
# List the removed objects
$removed
}
You can utilise Get-AzNetworkInterface to return all NICs within your current context.
You would have to filter the results to see which were not attached to a virtual machine.
# This will return NICs which aren't associated to a VM
$orphanedNics = Get-AzNetworkInterface | Where-Object VirtualMachine -eq $null
If you have a lot of resources to check then you could use Search-AzGraph from the Az.ResourceGraph module to perform the search.
$query = '
Resources
| where type has "microsoft.network/networkinterfaces"
| where properties !has "virtualmachine"'
$orphanedNics = Search-AzGraph -Query $query
Once you have those results and validated it's correct you can then use Remove-AzNetworkInterface to delete.

List Azure NSGs on Every Azure Subnet

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

Azure / Powershell / Get VM IPs with subscription names

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

Merge Storage Account Name and SKU with VM Name in Powershell

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

How to export Virtual Machine Names and IP Addresses from within multiple azure subscriptions

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

Resources