Automation Script to update firewall of Azure Analysis Services and WebApp

Hi,

I’m trying to create an Azure Automation job to request Azure IPs (only from “West Europe” and “North Europe”) and update firewall rules on “Azure Analysis Services” (firewall) and “Web App” (Networking > Access Restrictions). The process needs to be done on Azure WebApp and Azure Analisys Services in the same script, at the same time.

To do that manually I use this script:

Azure Analysis Services

Pre-requesits:
[pre]
#Run 2 functions to convert the CIDR address (and find the first and last IP of the network) to use in the next process

Function Get-IPV4NetworkStartIP ($strNetwork)
{
$StrNetworkAddress = ($strNetwork.split("/"))[0]
$NetworkIP = ([System.Net.IPAddress]$StrNetworkAddress).GetAddressBytes()
[Array]::Reverse($NetworkIP)
$NetworkIP = ([System.Net.IPAddress]($NetworkIP -join “.”)).Address
$StartIP = $NetworkIP +1
#Convert To Double
If (($StartIP.Gettype()).Name -ine “double”)
{
$StartIP = [Convert]::ToDouble($StartIP)
}
$StartIP = [System.Net.IPAddress]$StartIP
Return $StartIP
}

#Get-IPV4NetworkEndIP:

Function Get-IPV4NetworkEndIP ($strNetwork)
{
$StrNetworkAddress = ($strNetwork.split("/"))[0]
[int]$NetworkLength = ($strNetwork.split("/"))[1]
$IPLength = 32-$NetworkLength
$NumberOfIPs = ([System.Math]::Pow(2, $IPLength)) -1
$NetworkIP = ([System.Net.IPAddress]$StrNetworkAddress).GetAddressBytes()
[Array]::Reverse($NetworkIP)
$NetworkIP = ([System.Net.IPAddress]($NetworkIP -join “.”)).Address
$EndIP = $NetworkIP + $NumberOfIPs
If (($EndIP.Gettype()).Name -ine “double”)
{
$EndIP = [Convert]::ToDouble($EndIP)
}
$EndIP = [System.Net.IPAddress]$EndIP
Return $EndIP
}

#Variables

#Analisys Services Service
$aasRg = “sg-aasRg” #Name of Resource Group
$aasName = “sg-aasName” #Name of “Azure Analysis Services” service

$aasStartIp = “1.1.1.1” #First IP
$aasEndIp = “1.1.1.2” #Last IP

$aasFirewallRuleName = “Rule01” #Name of the rule (It’s always necessary to increment the number of the rule manually…)

#Update Analisys Services firewall

#New rule configuration
$NewRule1 = New-AzureRmAnalysisServicesFirewallRule -FirewallRuleName $aasFirewallRuleName -RangeStart $aasStartIp -RangeEnd $aasEndIp
$FWConfig = New-AzureRmAnalysisServicesFirewallConfig -EnablePowerBIService -FirewallRule $NewRule1

Set-AzureRmAnalysisServicesServer -Name $aasName -ResourceGroupName $aasRg -FirewallConfig $FWConfig
[/pre] (done…)

Now, for the creation of rules to all Azure NE and WE IPs I need to execute the script:
[pre]
#Get all IPs of North Europe
$allIPsNorthEU = (Get-MicrosoftAzureDatacenterIPRange -AzureRegion “north Europe”).Subnet
#Get all IPs of West Europe
$allIPsWestEU = (Get-MicrosoftAzureDatacenterIPRange -AzureRegion “west Europe”).Subnet

$aasFirewallRuleName = 1 #I’m trying to use numbers but what I want to use is something like “Rule01,Rule02,…”
$allIPs = (Get-MicrosoftAzureDatacenterIPRange -AzureRegion “north Europe”).Subnet #I need to do that process to WE too.

foreach ($IP in $allIPs)
{
if ($IP)
{
$aasFirewallRuleName++
$Start = Get-IPV4NetworkStartIP $IP
$End = Get-IPV4NetworkEndIP $IP

Write-Host “Add IP Range to Firewall > $IP…”
$a = New-AzureRmAnalysisServicesFirewallRule -FirewallRuleName $aasFirewallRuleName -RangeStart $Start -RangeEnd $End
$FWConfig = New-AzureRmAnalysisServicesFirewallConfig -EnablePowerBIService -FirewallRule $a
}
}

Set-AzureRmAnalysisServicesServer -Name $aasName -ResourceGroupName $aasRg -FirewallConfig $FWConfig
[/pre]

But with this script only the last Rule/IPs are saved on the firewall configuration of Analisys Services Service :frowning:

Azure Web App
For AzureWebApp I can use CIDR!

My script is:
[pre]
#Azure WebApp

#Variables

$webappRg = “sg-webappRg”
$AppServName = “sg-AppServName”

function Add-AzureIpRestrictionRule
{
[CmdletBinding()]
Param
(

Name of the resource group that contains the App Service.

[Parameter(Mandatory=$true, Position=0)]
$ResourceGroupName,

Name of your Web or API App.

[Parameter(Mandatory=$true, Position=1)]
$AppServiceName,

rule to add.

[Parameter(Mandatory=$true, Position=2)]
[PSCustomObject]$rule
)

$ApiVersions = Get-AzureRmResourceProvider -ProviderNamespace Microsoft.Web |
Select-Object -ExpandProperty ResourceTypes |
Where-Object ResourceTypeName -eq ‘sites’ |
Select-Object -ExpandProperty ApiVersions

$LatestApiVersion = $ApiVersions[0]

$WebAppConfig = Get-AzureRmResource -ResourceType ‘Microsoft.Web/sites/config’ -ResourceName $AppServiceName -ResourceGroupName $ResourceGroupName -ApiVersion $LatestApiVersion

$WebAppConfig.Properties.ipSecurityRestrictions = $WebAppConfig.Properties.ipSecurityRestrictions + @($rule) |
Group-Object name |
ForEach-Object { $_.Group | Select-Object -Last 1 }

Set-AzureRmResource -ResourceId $WebAppConfig.ResourceId -Properties $WebAppConfig.Properties -ApiVersion $LatestApiVersion -Force
}

$rule = [PSCustomObject]@{
ipAddress = “191.235.209.0/20”
action = “Allow”
priority = 4 #I need to increment it manually…
name = “Network 191.235.208.0/20 (NE)” #I need to increment it manually…
description = “Range 191.235.208.0/20 of North Europe Datacenter” #When the CIDR is from North Europe
}

Add-AzureIpRestrictionRule -ResourceGroupName $webappRg -AppServiceName $AppServName -Rule $rule
[/pre]

With this script I can add one Network at a time… and I need to add all the IP ranges of the 2 Azure Datacenters.

The process needs to be done on Azure WebApp and Azure Analisys Services in the same script, at the same time :frowning:

And the big problem is that I don’t know when these IPs changes!!

For this reason (automate the process to import/update all the necessary IPs) I need to create a diary schedule… And I need your help to create this “Azure Automation”.

Another requirement that I have is the need to use Variables outside the Automation Script so it can be customizable on other scripts/services.

Can you help me? Thanks for all your availability!

Best regards

Flot

Someone else will probably answer this. But people are more likely to answer, if you could simplify your question.

My main question is about the first point: “Now, for the creation of rules to all Azure NE and WE IPs I need to execute the script:”.

I don’t know how can I make a process (loop) to import all the IPs on the same task to execute the “Add-AzureIpRestrictionRule” cmdlet.

Can you help? Thanks for your help!

Flot

$allIPs = (Get-MicrosoftAzureDatacenterIPRange -AzureRegion "north Europe").Subnet 

$i = 0 
$FirewallRuleList = foreach ($IP in $allIPs) {
    $aasFirewallRuleName = "Rule$(([string]$i++).PadLeft(2,'0'))" # "Rule01,Rule02,...."
    $Start = Get-IPV4NetworkStartIP $IP
    $End   = Get-IPV4NetworkEndIP $IP

    Write-Host "Adding IP Range to Firewall > $IP..."
    New-AzureRmAnalysisServicesFirewallRule -FirewallRuleName $aasFirewallRuleName -RangeStart $Start -RangeEnd $End
}
$FWConfig = New-AzureRmAnalysisServicesFirewallConfig -EnablePowerBIService -FirewallRule $FirewallRuleList
Set-AzureRmAnalysisServicesServer -Name $aasName -ResourceGroupName $aasRg -FirewallConfig $FWConfig

The if statement is not required.
To make rule names as Rule01, Rule02, … use the PadLeft method of the String class as shown.
As example 1 shows here, you need to build up the rule list (the $FirewallRuleList array in the code above) before you create the FW config

The process doesn’t work :frowning:

[pre]

Set-AzureRmAnalysisServicesServer : The IP range System.Byte[]-System.Byte[] is invalid because the range start is greater than range end.
At line:13 char:1

  • Set-AzureRmAnalysisServicesServer -Name $aasName -ResourceGroupName $ …
  • CategoryInfo : CloseError: (:slight_smile: [Set-AzAnalysisServicesServer], CloudException
  • FullyQualifiedErrorId : Microsoft.Azure.Commands.AnalysisServices.SetAzureAnalysisServicesServer

[/pre]

Maybe I need to remove all the IPs first (or verify if it already exist) and add it after that.

With the Sam Boutros tip (thanks!!!), now I have the second problem solved (creation of new IP rules on WebApp firewall)

My solution:

[pre]

#Variables

$webappRg = “rg”
$AppServName = “app”

function Add-AzureIpRestrictionRule
{
[CmdletBinding()]
Param
(

Name of the resource group that contains the App Service.

[Parameter(Mandatory=$true, Position=0)]
$ResourceGroupName,

Name of your Web or API App.

[Parameter(Mandatory=$true, Position=1)]
$AppServiceName,

rule to add.

[Parameter(Mandatory=$true, Position=2)]
[PSCustomObject]$rule
)

$ApiVersions = Get-AzureRmResourceProvider -ProviderNamespace Microsoft.Web |
Select-Object -ExpandProperty ResourceTypes |
Where-Object ResourceTypeName -eq ‘sites’ |
Select-Object -ExpandProperty ApiVersions

$LatestApiVersion = $ApiVersions[0]

$WebAppConfig = Get-AzureRmResource -ResourceType ‘Microsoft.Web/sites/config’ -ResourceName $AppServiceName -ResourceGroupName $ResourceGroupName -ApiVersion $LatestApiVersion

$WebAppConfig.Properties.ipSecurityRestrictions = $WebAppConfig.Properties.ipSecurityRestrictions + @($rule) |
Group-Object name |
ForEach-Object { $_.Group | Select-Object -Last 1 }

Set-AzureRmResource -ResourceId $WebAppConfig.ResourceId -Properties $WebAppConfig.Properties -ApiVersion $LatestApiVersion -Force
}

$allIPs = (Get-MicrosoftAzureDatacenterIPRange -AzureRegion “north Europe”).Subnet

$i = 100
$FirewallRuleList = foreach ($Range in $allIPs) {
$rule = [PSCustomObject]@{
ipAddress = $Range
action = “Allow”
priority = $(([string]$i++).PadLeft(2,‘0’)) # “101,102,…”
name = “Network $Range (NE)”
description = “Range $IP of North Europe Datacenter” #When the CIDR is from North Europe
}
Add-AzureIpRestrictionRule -ResourceGroupName $webappRg -AppServiceName $AppServName -Rule $rule
}

[/pre]

But It only have a problem, it’s very slow (because it add one by one)!! Any idea how to perform it? Maybe this is an Azure service issue on Web App service…

Unfortunately the problem with Azure Analysis Services persist… can anyone help, please?

Thanks!