How to update Azure Application Gateway Path Based Rule UrlPathMap from .NET - azure

On Azure Portal, I am able to setup path-based rules which have some default setting, and a list of sub-rules (UrlPathMap).
Each of those sub-rules has a name, paths, backend pool, and HTTP setting that have to be configured.
As I can see I can update this map easily through Azure Portal.
I want to be able to create such sub-rules dynamically from code as part of the application installation. I would prefer to do this directly from .NET (ASP.NET Core 3.1) application, but Azure CLI or Azure Powershell script should be OK for me as well.
At this point, I tried to use Microsoft.Azure.Management.Fluent library, Azure CLI and Azure Powershell but I do not see the direct option to do what is need.
Will be really glad to get some help here.

According to my test, we can use the following PowerShell script to create a sub-rule.
Connect-AzAccount
$groupName=""
$gatewayName=""
$poolNmae=""
$httpName=""
$pathRuleName=""
# get original sub-rule in your path rule
$appgateway=Get-AzApplicationGateway -Name $gatewayName -ResourceGroupName $groupName
$pathmap=Get-AzApplicationGatewayUrlPathMapConfig -ApplicationGateway $appgateway -Name $pathRuleName
$t =$pathmap.PathRules.ToArray()
# add a new sub-rule to the path rule
# 1. get the require backendpool or backendhttp settings
$pool=Get-AzApplicationGatewayBackendAddressPool -Name $poolNmae -ApplicationGateway $appgateway
$http=Get-AzApplicationGatewayBackendHttpSetting -Name $httpName -ApplicationGateway $appgateway
# 2. create the sub-rule
$r=New-AzApplicationGatewayPathRuleConfig -Name "rule01" -Paths "/path" -BackendAddressPool $pool -BackendHttpSettings $http
$t += $r
# 3. update the path rule to add the new sub rule
Set-AzApplicationGatewayUrlPathMapConfig -ApplicationGateway $appgateway -Name $pathmap.Name -PathRules $t -DefaultBackendAddressPool $pool -DefaultBackendHttpSettings $http
# 4. make the update effective
Set-AzApplicationGateway -ApplicationGateway $appgateway

Related

Mounting Azure File Storage on a Windows Docker container

I've got a Windows container that's running in Azure that I'm trying to attach persistent storage to, however, I'm not able to find any documentation on how to do so.
Dockerfile:
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-20190910-windowsservercore-ltsc2016
SHELL ["powershell"]
EXPOSE 443
WORKDIR /CompanyAPP
COPY WebPackage.zip .
RUN Expand-Archive WebPackage.zip . ; `
Rename-Item ./CustomerWebConfigurator ./WebConfigurator; `
Rename-Item ./Customer ./WebRoot; `
Rename-Item ./CustomerWebService ./WebService; `
Rename-Item ./CustomerWCFService ./WCFService; `
rm WebPackage.zip
ARG BUILD
RUN Add-WindowsFeature Net-WCF-HTTP-Activation45;`
Install-PackageProvider -Name Nuget -Force;`
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted;`
Install-Module -Name AWSPowerShell;`
New-WebApplication -Site 'Default Web Site' -Name 'App' -PhysicalPath c:\CompanyAPP\WebRoot; `
New-WebApplication -Site 'Default Web Site' -Name 'AppWebService' -PhysicalPath c:\CompanyAPP\WebService; `
New-WebApplication -Site 'Default Web Site' -Name 'AppWCFService' -PhysicalPath c:\CompanyAPP\WCFService; `
New-WebApplication -Site 'Default Web Site' -Name 'AppWebConfigurator' -PhysicalPath c:\CompanyAPP\WebConfigurator; `
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' -Name ServerPriorityTimeLimit -Value 0 -Type DWord;`
$cert = New-SelfSignedCertificate -Subject self; `
New-WebBinding -Protocol https -port 443 -name 'Default Web Site' -SSLFlags 0; `
$binding = Get-WebBinding -protocol https; `
$binding.AddSslCertificate($cert.Thumbprint, 'my');
RUN Set-WebConfiguration -PSPath 'IIS:\Sites\Default Web Site\App' -Filter '/system.web/customErrors' -Value #{mode='Off'};`
write-host 'got here!'
The storage is configured in an Azure Storage account, and using file storage, I'm attaching it in the configuration via path mappings, and am having no luck.
Hoping that someone can point me in a good direction to get this figured out.
I may be quite late to the party, but I stumbled upon this issue only today (mounting Azure File Volumes in a Windows Container still is not supported even a year later), and I found quite an easy workaround. I will share this here, because this question is one of the top results when searching for the error message.
You can mount your Azure File Volume via SMB. All you need is the UNC, a username and a password, which you can get from the properties of your Azure File Volume
So I created a small startup.cmd
#echo off
net use z: %MNTUNC% %MNTPASS% /user:%MNTUSER%
"c:\program files\myapp\myapp.exe"
and defined that startup.cmd as the entrypoint in the dockerfile
....
COPY ["startup.cmd", "c:/startup.cmd"]
ENTRYPOINT ["c:/startup.cmd"]
Pitfall: Be aware, that a drive mapped with net use (or New-PSDrive if you prefer PowerShell) is only visible to the user account under which the command was executed, so be sure to mount the drive with the same user, which is used to execute the service.
You can set the values for the environment variables during deployment like described here:
https://learn.microsoft.com/en-us/azure/container-instances/container-instances-environment-variables
For instance, when using a YAML file for deployment, you can set the environment variables as follows. Using secureValue makes the value of the environment variable accessible only from within the container and the values won't be shown for instance in the properties of the container on the azure portal.
....
containers:
- name: mycontainer
properties:
environmentVariables:
- name: 'MNTUNC'
secureValue: '\\myaccountname.file.core.windows.net\myvolume'
- name: 'MNTPASS'
secureValue: 'mysupersecretpassword'
- name: 'MNTUSER'
secureValue: 'Azure\myaccountname'
If you use the Azure Container Instance to deploy for Windows container, then the Azure File storage does not support the persistent volume., it's currently restricted to Linux containers. You can get more details about the note here:
Mounting an Azure Files share is currently restricted to Linux
containers.
Update:
With the message that the provided in the comment, you use the web app for the container with the Windows image. In this situation, it supports to mount the Azure File Share to the Windows Container. You can follow the steps in Configure Azure Files in a Windows Container on App Service.

AzureRM application gateway backend pools - is there a way to specify an App Service instead of FQDNs/IPs?

I'm trying to create a new Backend Pool in PowerShell.
In Azure's UI, these Backend Pools can refer to an App Service (e.g. a single container).
The PowerShell cmdlet however doesn't appear to support this, as far as I can see:
$AppGw = Get-AzureRmApplicationGateway -Name "ApplicationGateway01" -ResourceGroupName "ResourceGroup01"
$AppGw = Add -AzureApplicationGatewayBackendAddressPool -ApplicationGateway $ AppGw -Name "Pool02" -BackendIPAddresses "10.10.10.10", "10.10.10.11"
$AppGw = Get-AzureRmApplicationGateway -Name "ApplicationGateway01" -ResourceGroupName "ResourceGroup01"
$AppGw = Add-AzureRmApplicationGatewayBackendAddressPool -ApplicationGateway $AppGw -Name "Pool02" -BackendFqdns "contoso1.com", " contoso1.com"
I was hoping that it would be something along the lines of...
$AppService = Get-AzureRmWebApp -Name 'WebApp01'
$AppGw = Add-AzureRmApplicationGatewayBackendAddressPool -ApplicationGateway $AppGw -Name 'Pool02' -BackendWebApp $AppService
Does anyone know if there's any way around this?
For PowerShell, it seems there no cmdlet can achieve it that you expected:
Add-AzureRmApplicationGatewayBackendAddressPool -ApplicationGateway $AppGw -Name 'Pool02' -BackendWebApp $AppService
In the Azure portal, it is just convenient for people to find the App Service with the type App Services and get the FQDN. But for PowerShell cmdlet, it is more direct to input the FQDN.
By the way, people usually use an FQDN to access Azure Web Service. You can get more details about Configure App Service Web Apps with Application Gateway here.

Provisioning state blank when creating Backend Address Pool

I am running the following commands to try and create a new Backend Address Pool in Azure's Application Gateway service.
$NewBackendPool = New-AzureRmApplicationGatewayBackendAddressPool -Name "MHA-DEVOPS-TEST-2" -BackendFqdns "test.com"
Write-Host "Provisioning state: $($NewBackendPool.ProvisioningState)" -ForegroundColor Magenta
$NewBackendPool
The output I get is as follows:
I receive no error, but the ProvisioningState value is blank and when I try to attach this to my Application Gateway using the Add-AzureRmApplicationGatewayBackendAddressPool, nothing fails but the Backend Address Pool is definitely not created/attached.
Where am I going wrong?
Try the command below, it will work fine.
$AppGw = Get-AzureRmApplicationGateway -Name "<Your ApplicationGateway Name>" -ResourceGroupName "<ResourceGroupName>"
$AppGw = Add-AzureRmApplicationGatewayBackendAddressPool -ApplicationGateway $AppGw -Name "test11" -BackendFqdns "test11.com"
Set-AzureRmApplicationGateway -ApplicationGateway $AppGw
Result snippet:
Check in the portal:

Azure Application Gateway 502 error

I being working with the Azure application gateway, and stuck at the following error.
Here, my Network Diagram
Here, the powershell script which I had configure
Poweshell Output
PS C:\Users\shabbir.akolawala> Get-AzureApplicationGateway sbr2appgateway
Name : sbr2appgateway
Description :
VnetName : Group Shabs-AppGateway2 sbag2vnet
Subnets : {sbag2subnet1}
InstanceCount : 2
GatewaySize : Small
State : Running
VirtualIPs : {104.41.159.238} <-- Note IP Here
DnsName : 01b9b0e4-4cd2-4437-b641-0b5dc4e3efe7.cloudapp.net
Here, public IP of the application gateway is 104.41.159.238
Now, if I hit for first time you hit the gateway, you get following output
Note, this website doesn't render correctly, as many request (css/images) fail with 502.
Now, when if I hit this second time, I straightway get the 502 error
But, when hit the cloud service IP, I get my website correctly
I had configure the Azure Gateway with following configuration XML
My Questions are,
1] Does one have an idea how how to access logs which are generated in Application Gateway (In theory, Application gateway runs on IIS 8.5 / ARR)
2] Any obvious error, I made in design or configuration?
It is because of timeout.
1, Probe has by default 30 seconds timeout. if you application needs authentication, you will have to set custom probe.
2, Application Gateway has default 30 seconds timeout as well. if your Application Gateway cannot get response from backend virtual machine. it will return HTTP 502. it can be changed via "RequestTimeout" configuration item.
PowerShell:
set-AzureApplicationGatewayConfig -Name <application gateway name> - Configfile "<path to file>"
Config file:
<BackendHttpSettings>
<Name>setting1</Name>
<Port>80</Port>
<Protocol>Http</Protocol>
<CookieBasedAffinity>Enabled</CookieBasedAffinity>
<RequestTimeout>120</RequestTimeout>
<Probe>Probe01</Probe>
For detail : https://azure.microsoft.com/en-us/documentation/articles/application-gateway-create-probe-classic-ps/
Just extending this #Lang's answer for people using the Resource Manager rather than Classic. The following Powershell script will update set a new requested timeout of 120 seconds for every BackendHttpSetting within the target app gateway.
# Variable setup
$agName = "my gateway name"
$rgName = "my resource group name"
$newRequestTimeout = 120
# Retrieve gateway obj
$appGW = Get-AzureRmApplicationGateway -Name $agName -ResourceGroupName $rgName
$allHttpBackendSettings = Get-AzureRmApplicationGatewayBackendHttpSettings `
-ApplicationGateway $appGW
foreach($s in $allHttpBackendSettings)
{
# Retreive existing probe
$probeName = $s.Probe.Id.Split("/") | Select-Object -Last 1;
$probe = Get-AzureRmApplicationGatewayProbeConfig -ApplicationGateway $appGW `
-Name $probeName
# Update http settings
$appGW = Set-AzureRmApplicationGatewayBackendHttpSettings -ApplicationGateway $appGW `
-Name $s.Name -RequestTimeout $newRequestTimeout -Port $s.Port -Protocol $s.Protocol `
-Probe $probe -CookieBasedAffinity Enabled -PickHostNameFromBackendAddress
}
# Persist changes to the App Gateway
Set-AzureRmApplicationGateway -ApplicationGateway $appGW
I created custom healthchecks, but never seen attempts in websever access-log.
So I just set route on backend to serve any domain including IP address and add htpasswd protection to real domains.
Azure application gateway check http://backend_ip:80/ and became happy gateway :)

Powershell command to set IIS logging settings

I'm creating a powershell script so I can create website hosting with a single command using the IIS Powershell Management Console.
I have the commands I need to create the IIS Site and add bindings for the domain names etc...
The one piece of the puzzle I'm missing though is how to change the default Logging directory from %SystemDrive%\inetpub\logs\LogFiles to my own folder that's not on the boot drive of the server.
After extensive searching I expected to find a command along the lines of the following pseudo powershell
New-ItemProperty IIS:\Sites\MyNewSite -name logging -value #{format='W3C';directory='d:\sites\site\logs';encoding=UTF-8}
Please could you show me with an example how you change the logging folder in the IIS Powershell Management Console
Thanks in advance
Import-Module WebAdministration
Set-WebConfigurationProperty "/system.applicationHost/sites/siteDefaults" -name logfile.directory -value $logdir
While testing the answer from this thread, toggling options via IIS Manager and PowerShell, I stumbled on something that has been hidden to me. In IIS Manager, choosing Configuration Editor and making a change, allows the IIS Manager to generate and display the script for the change in C#, JavaScript, AppCmd.exe and PowerShell. Just click the Generate Script option.
[]
For changing an individual web site's logFile configuration, the original post was nearly correct. Instead of New-ItemProperty, use Set-ItemProperty, like so...
Set-ItemProperty "IIS:\Sites\$SiteName" -name logFile -value #{directory=$LogPath}
For changing the server-wide default settings, see Andy Schneider's answer.
For more information about the options available, see this IIS.net article.
This works as well, using the WebAdministration Module
Import-Module WebAdministration
$site = gi IIS:\Sites\MyNewSite
$site.Logging.format='W3C'
$site.Logging.directory='d:\sites\site\logs'
$site.Logging.encoding=UTF-8
$site | set-item
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")
$iis = new-object Microsoft.Web.Administration.ServerManager
$web = $iis.Sites["test"]
#set new logpath, must be existing
$web.LogFile.Directory = "F:\Logfiles\"
$iis.CommitChanges()
If you host multiple sites on a single server and want them to all log to the same log file, the process is quite different. It took some digging to find clues here and here, so I thought I would leave a description behind for anyone else with this need.
The following two statements will combine logs for all of your websites into a folder e:\log\w3svc.
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter 'system.applicationHost/log' -name CentralLogFileMode -Value 'CentralW3C'
Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter 'system.applicationHost/log' -name centralW3CLogFile.directory -value 'e:\log'

Resources