Azure Route Table Modification With Powershell - azure

We have over 20 route tables that we need to be able to quickly modify.
We have 2 NVAs that could act as the next hop but we are not able to find the correct solution.
We are stuck at this:
$groupname = Get-AzResourceGroup | Out-GridView –PassThru | Select -ExpandProperty ResourceGroupName
$rt = Get-AzRouteTable -ResourceGroupName $groupname | Out-GridView -PassThru
$oldroutes = Get-AzRouteTable -ResourceGroupName $groupname | Get-AzRouteConfig | Where-Object -Property NextHopIpAddress -Like 1.1.1.1 | Select -ExpandProperty Name
foreach ($oldroutes in $oldroutes)
{
Set-AzRouteConfig -RouteTable $rt -Name $oldroute -NextHopIpAddress 2.2.2.2 | Set-AzRoutetable }
This works to the part that is able to go through all Route Tables and identify all routes that have next hop as 1.1.1.1 and store them in a variable called $oldroutes and only selecting the route Name which is needed by the Set-AZRouteConfig command.
It runs correct up until the Set part. Instead of Modifying it just sets the NextHopIpAddress as 2.2.2.2 and deletes all other values, so when we try to commit the changes we get an error.
Set-AzRoutetable : Address prefix string for resource ...... cannot be null
Has anyone done this or are we missing anything maybe?
Thank you in advance!

I can reproduce your issue, when using Set-AzRouteConfig | Set-AzRoutetable , the parameter -AddressPrefix is needed, if you don't want change it, you could specify it with the original one. And if you want to set -NextHopIpAddress, you need to specify the -NextHopType only with VirtualAppliance. And this part $oldroutes in $oldroutes is also has a mistake, it should be $oldroute in $oldroutes.
So in summary, your script should be like below.
$groupname = Get-AzResourceGroup | Out-GridView –PassThru | Select -ExpandProperty ResourceGroupName
$rt = Get-AzRouteTable -ResourceGroupName $groupname | Out-GridView -PassThru
$oldroutes = Get-AzRouteTable -ResourceGroupName $groupname | Get-AzRouteConfig | Where-Object -Property NextHopIpAddress -Like 1.1.1.1
foreach ($oldroute in $oldroutes)
{
Set-AzRouteConfig -RouteTable $rt -Name $oldroute.Name -AddressPrefix $oldroute.AddressPrefix -NextHopType VirtualAppliance -NextHopIpAddress 2.2.2.2 | Set-AzRoutetable
}

Related

Automate NSG rule creation for NSGs within azure: Type error from Get-AzNetworkSecurityGroup

I am trying to write a script to automate creating NSG rules for our production NSGs. I am pretty sure I have something close to working but the issue I run into is that the Get-AZNetworkSecurityGroup command returns a string and so I cant feed it into the Add-AzNetworkSecurityRuleConfig command.
Import-Module Az.network
Connect-AzAccount
$tcpports = #(22,53,80,135,137,161,427,443,515,548,5060,5480,5985,5986,5989,9100,9443)
$udpports = #(53,161,427,515,548)
$solservers = #Server IP here
$file = Import-Csv C:\Users\temp\Downloads\AzureNSGs.csv
foreach ($NSG in $file){
$RGname=$NSG.'RESOURCE GROUP'
$nsgname=$NSG.NAME
$NSGObj = Get-AzNetworkSecurityGroup | Where-Object -Property Name -Like $RGname | Select-Object -Property Name
$name = "AllowSolarWinds"
if($NSGObj){
$name = $name + 1
$NSGObj | Add-AzNetworkSecurityRuleConfig -Name $name -NetworkSecurityGroup $NSGObj -Protocol Icmp -SourceAddressPrefix $solservers -DestinationPortRange "*" -Priority 555
$NSGObj | Set-AzNetworkSecurityGroup
}
}
Whenever I run this I get two kinds of returns. It either looks like it ran successfully with no errors but the rule is never created in azure. Or powershell spits out one of the following errors.
Add-AzNetworkSecurityRuleConfig : Cannot bind argument to parameter 'NetworkSecurityGroup' because it is null.
or
Add-AzNetworkSecurityRuleConfig : Cannot bind parameter 'NetworkSecurityGroup'. Cannot convert the value of type "System.String" to type
"Microsoft.Azure.Commands.Network.Models.PSNetworkSecurityGroup".
I tried to reproduce the same in my environment I got the same error like below:
To resolve the error, try to modify the code like below:
Connect-AzAccount
Import-Module Az.network
$tcpports = #(22,53,80,135,137,161,427,443,515,548,5060,5480,5985,5986,5989,9100,9443)
$udpports = #(53,161,427,515,548)
$solservers = "112.121.61.196"
$file = Import-Csv C:\Users\v-khanimran\Downloads\AzureNSGs.csv
foreach ($NSG in $file){
$RGname=$NSG.RESOURCEGROUPNAME
$nsgname=$NSG.NAME
$NSGObj =Get-AzNetworkSecurityGroup -Name $nsgname -ResourceGroupName $RGname
#Get-AzNetworkSecurityGroup | Where-Object {$_.Name -Like $nsgname} | Select-Object -Property Name
$name = "AllowSolarWinds"
if($NSGObj){
$name = $name + 1
$NSGObj | Add-AzNetworkSecurityRuleConfig -Name $name -Protocol Icmp -SourceAddressPrefix $solservers -DestinationPortRange "*" -SourcePortRange "*" -DestinationAddressPrefix "*" -Priority 555 -Access Allow -Direction Inbound
$NSGObj | Set-AzNetworkSecurityGroup
}
}
Output:
In the portal NSG rule got added successfully like below:

Unable to update Azure Network Security Group using az cli

I am attempting to update a Network Security Group (SourceAddressPrefixes) via the cli. To begin, it appears that the az cmdlet Set-AzNetworkSecurityRuleConfig is broke; the output from the command states that it's succeeded but no change actually occurs to the NSG. Others have complained about this but no fix from MSFT yet.
With that said, I have tried a workaround method which saves the NSG in a variable, sets the SourceAddressPrefixes, and updates the NSG after:
$SaContext = (Get-AzStorageAccount -ResourceGroupName $RGName -Name $SAName).Context
$table = (Get-AzStorageTable -Name $TableName -Context $SaContext).CloudTable
$IPs = (Get-AzTableRow -Table $table).IP
$IPs = '"{0}"' -f ($IPs -join '","') # Updates the IPs to be double-quoted and separated by commas
$NSG = Get-AzNetworkSecurityGroup -ResourceGroupName $MyResourceGroup -Name $NSGName
($nsg.SecurityRules | Where-Object {$_.Name -eq 'HTTPS'}).SourceAddressPrefix = $IPList
$NSG | Set-AzNetworkSecurityGroup | Get-AzNetworkSecurityRuleConfig -Name $RuleName | Format-Table -AutoSize
The issue with the code above is that the cmdlet Set-AzNetworkSecurityGroup will not except value type system.string. It will only accept System.Collections.Generic.List[System.String]. Due to that I perform the following:
$IPList = New-Object System.Collections.Generic.List[string]
$IPList.Add($IPs)
Now, the previous Set-AzNetworkSecurityGroup accepts the array but now the command fails because the array values aren't double-quoted with a comma to separate them. Not sure what to do at this point.
Actual error messages below:
Cannot convert the (ip addresses here) value of type [system.string] to type "Systems.Collections.Generic.IList[System.String]
And once I convert my variable(array) to match that requirement the error is:
nsgRule has invalid Address Prefix. Value Provided (ip addresses here) statuscode:400 which i'm sure is because converting the array removes the double-quotes & commas.
If you want to update the Source Address Prefix of one Network Security Group rule, its value should be like
192.162.0.1
192.162.1.1
...
For example
$nsg= Get-AzNetworkSecurityGroup -Name $NSGName -ResourceGroupName $MyResourceGroup
$IPList = New-Object System.Collections.Generic.List[string]
$IPList.Add("192.162.0.1")
$IPList.Add("192.162.1.1")
($nsg.SecurityRules | Where-Object {$_.Name -eq 'Port_8080'}).SourceAddressPrefix =$IPList
$nsg|Set-AzNetworkSecurityGroup | Get-AzNetworkSecurityRuleConfig -Name "Port_8080" | Format-Table -AutoSize

Get Azure resource using filters

i'm trying to use Powershell to query my Storage Accounts by using name filter
I have tried these commands (and their variants) but have not still managed to get this working.
Get-AzStorageAccount | where -FilterScript {($_.ResourceType -eq "storageAccounts") -and ($_.StorageAccountName -contains "Prod") }
Get-AzResource -ResourceType Microsoft.Storage/storageAccounts | Get-AzResource -Name Prod* | ft
Any tips because I'm a bit lost. My goal would be that command / script would print out e.g all Storage Accounts which contains Prod in their name.
You can use Where-Object and -match to filter here:
Get-AzStorageAccount | Where-Object {$_.StorageAccountName -match 'prod'}
Or using -like:
Get-AzStorageAccount | Where-Object {$_.StorageAccountName -like '*prod*'}
If you really want to use Get-AzResource, then you need to filter by the Microsoft.Storage/storageAccounts resource type:
Get-AzResource -ResourceType "Microsoft.Storage/storageAccounts" | Where-Object {$_.Name -match 'prod'}
You can have a look at Matching Operators from about_comparison_operators for more information.

Optimize Powershell script for Azure NSG

I have a script for finding all inbound, allow rules in Azure NSG which source is any. It is doing his job but it takes just an enormous amount of time to iterate every rule in every available NSG in Azure.
Question is there is any way to optimize it, so it could work faster? Thanks!
function nsg {
# List of default rules which are skipped
$array =
'Default rules'
# Get all RG with NSG
$RGS = (Get-AzureRmResource -ODataQuery "`$filter=resourcetype eq 'Microsoft.Network/networkSecurityGroups'").ResourceGroupName | Sort-Object -Unique
foreach ($RG in $RGS) {
# List of all NSG names
$NSG_Names = (Get-AzureRmNetworkSecurityGroup -ResourceGroupName $RG).Name
# Get NSG rules
foreach ($NSG_Name in $NSG_Names){
$Rules = Get-AzureRmNetworkSecurityGroup -Name $NSG_Name -ResourceGroupName $RG | Get-AzureRmNetworkSecurityRuleConfig | Select-Object -ExpandProperty Name
# Check if rule is not default
foreach ($Rule in $Rules){
if ($array.contains($Rule)){
Write-Verbose "$Rule excluded because it is default!"
}
else {
Write-Verbose "$NSG_Name - $Rule"
#$DestinationAddressPrefix = Get-AzureRmNetworkSecurityGroup -Name $NSG_Name -ResourceGroupName $RG | Get-AzureRmNetworkSecurityRuleConfig -Name $Rule | Select-Object -ExpandProperty DestinationAddressPrefix
$DestinationPortRange = Get-AzureRmNetworkSecurityGroup -Name $NSG_Name -ResourceGroupName $RG | Get-AzureRmNetworkSecurityRuleConfig -Name $Rule | Select-Object -ExpandProperty DestinationPortRange
$SourceAddrPref = Get-AzureRmNetworkSecurityGroup -Name $NSG_Name -ResourceGroupName $RG | Get-AzureRmNetworkSecurityRuleConfig -Name $Rule | Select-Object -ExpandProperty SourceAddressPrefix
$SourcePortRange = Get-AzureRmNetworkSecurityGroup -Name $NSG_Name -ResourceGroupName $RG | Get-AzureRmNetworkSecurityRuleConfig -Name $Rule | Select-Object -ExpandProperty SourcePortRange
$Access = Get-AzureRmNetworkSecurityGroup -Name $NSG_Name -ResourceGroupName $RG | Get-AzureRmNetworkSecurityRuleConfig -Name $Rule | Select-Object -ExpandProperty Access
$Direction = Get-AzureRmNetworkSecurityGroup -Name $NSG_Name -ResourceGroupName $RG | Get-AzureRmNetworkSecurityRuleConfig -Name $Rule | Select-Object -ExpandProperty Direction
# Chek rule for every criterion, access type, etc.
if ($Direction -eq "Inbound" -and $SourceAddrPref -eq "*" -and $Access -eq "Allow"){ #-and $DestinationAddressPrefix -eq "*" -and $DestinationPortRange -eq "*") {
$message = "Warning! RG: $RG; NSG: $NSG_Name has SOURCE ANY Rule: $Rule to Destionation Port: $DestinationPortRange"
$message
}}}}}}
I don't think you need to iterate all that data. All those nested loops + sorting is whats causing the slowdown.
It seems to me that you just want to output all your NSGs with direction Inbound and access is Allow and source address prefix as *. If this is the case, you can do this:
$nsgs = Get-AzureRmNetworkSecurityGroup
foreach ($nsg in $nsgs.SecurityRules)
{
if ($nsg.Direction -eq "Inbound" -and $nsg.Access -eq "Allow" -and $nsg.SourceAddressPrefix -eq "*")
{
$nsg
}
}
Here we just iterate the security rules you have made from $nsgs.SecurityRules. The default ones are in $nsgs.DefaultSecurityRules. You can pipe to Get-Member to find these properties.

Azure Powershell - Script to obtain VM info across subscriptions

Trying to run a script that will connect to each subscription, and pull the
$azureSubs = Get-AzureRMSubscription
$azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM | select resourcegroupname, name, licensetype -WarningAction SilentlyContinue}
This works, BUT I'd like to add two more pieces of information: the "OSType" and "VMSize"
If I do a GET-AZURERMVM, in the table for that subscription that the command is run in, the two pieces of information I need are there: VmSize and OsType
However, when I try to add them to the query, the columns are blank.
I believe the VmSize is in the HardwareProfile, and OsType is in the OsProfile, as if I run a "Get-AzureRMVM -name (name) -resourcegroupname (RGname)", then it shows "Hardware Profile: VMSize" and "OSProfile: ComputerName, AdminUsername windowsConfiguration, Secrets"
Ultimate goal is to get the script that will, for each subscription, print results like:
ResourceGroupName | Name | License Type | VMSize | OS Type
TEST_RG | Test_VM | Windows_Server | DS3_v2 | Windows
Test_RG | Test_VM2 | | DS3_v2 | Linux
etc.
Thankful for any help; sorry for such a noob question. Have spent so much time trying to figure this out...
Something like the following would work.
What you were missing mainly was calculated properties.
This is what allow you to perform a select of custom property.
Some notes:
In your code, you used -WarningAction SilentlyContinue on the Select statement. You need to put it on the Get-AzureRMVM CmdLet instead.
This is my opinion but unless you are writing one-liners on purposes, try aerating your code more. It will make it way easier to read, debug and maintain.
This is the code you wrote, modified to include the calculated properties and with the WarningAction parameter set to Get-AzureRMVM instead of the Select statement.
$azureSubs = Get-AzureRMSubscription
$Vms = $azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM -WarningAction SilentlyContinue | select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}}
$Vms | ft
The same thing, with some progress indication without forcing everything on one line.
$azureSubs = Get-AzureRMSubscription
$Vms = New-Object 'System.Collections.Generic.List[PSObject]'
ForEach ($sub in $azureSubs) {
Select-AzureRMSubscription $sub | Out-Null
Write-Host "Processing Subscription $($sub.Name)".PadRight(50,' ') -ForegroundColor Cyan -NoNewline
[PsObject[]]$items = Get-AzureRMVM -WarningAction SilentlyContinue |
select resourcegroupname,
name,
licensetype,
#{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},
#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}
Write-Host "($($items.count) retrieved)"
if ($items -ne $null) {
$vms.AddRange($items)
}
}
$vms | Format-Table
You are looking for something like this on the select side
select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}}, #{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}

Resources