Export/Public/New-ApplicationGateway.ps1

function New-ApplicationGateway {
    [CmdletBinding()]
    <#
    .SYNOPSIS
        ...
    .DESCRIPTION
        ...
    #>

    param(        
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceGroupName,
        [Parameter(Mandatory = $true)]
        [string]
        $ResourceLocation,
        [Parameter(Mandatory = $true)]
        [string]
        $ApplicationGatewayName,
        [Parameter(Mandatory = $true)]
        [string]
        $VMScaleSetName,
        [Parameter(Mandatory = $false)]
        [string]
        $FrontEndIpConfigNamePrivate = "$($VMScaleSetName)FrontEnd-private",
        [Parameter(Mandatory = $false)]
        [string]
        $FrontEndIpConfigNamePublic = "$($VMScaleSetName)FrontEnd-public",
        [Parameter(Mandatory = $false)]
        [string]
        $BackendPoolName = "$($VMScaleSetName)BackEnd",
        [Parameter(Mandatory = $true)]
        [string]
        $VirtualNetworkName,
        [Parameter(Mandatory = $false)]
        [string]
        $VirtualNetworkResourceGroupName = $ResourceGroupName,        
        [Parameter(Mandatory = $true)]
        [string]
        $SubnetName,
        [Parameter(Mandatory = $true)]
        [string]
        $SubnetAddressPrefix = "10.0.1.0/24",
        [Parameter(Mandatory = $true)]
        [string]
        $PrivateIpAddress,
        [Parameter(Mandatory = $false)]
        [ValidateSet('IPv4', 'IPv6')]
        [string]
        $PrivateIpAddressVersion = 'IPv4',
        [Parameter(Mandatory = $true)]
        [string]
        $PublicIpAddressName,
        [Parameter(Mandatory = $false)]
        [string]
        $DomainNameLabel,
        [Parameter(Mandatory = $false)]
        [string]
        $ApplicationGatewaySkuName = "Standard_v2",
        [Parameter(Mandatory = $false)]
        [string]
        $ApplicationGatewaySkuTier = "Standard_v2",
        [Parameter(Mandatory = $false)]
        [int]
        $ApplicationGatewaySkuCapacity = 2,
        [Parameter(Mandatory = $false)]
        [bool]
        $UpdateScaleSet = $true,
        [Parameter(Mandatory = $true)]
        [string]
        $StorageAccountName,
        [Parameter(Mandatory = $true)]
        [string]
        $TableNameEnvironments,
        [Parameter(Mandatory = $true)]
        [string]
        $EnvironmentTypeFilter,
        [Parameter(Mandatory = $false)]
        [string]
        $KeyVaultName,
        [HashTable]
        $Tags
    )
    process {        
        if (Get-AzApplicationGateway -ResourceGroupName $ResourceGroupName -Name $ApplicationGatewayName -ErrorAction SilentlyContinue) {
            Write-Verbose "Application Gateway $ApplicationGatewayName already exists."
            return
        }

        # Get environments from Storage; needed to create correct HttpSettings and Probes for Webclients
        $storageAccount = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName
        $storageAccountContext = $storageAccount.Context
        $environments = Get-EnvironmentsFromStorage -StorageAccountContext $storageAccountContext -TableNameEnvironments $TableNameEnvironments -TypeFilter $EnvironmentTypeFilter -EnvironmentsOnly -Verbose:$Verbose

        $params = @{
            ResourceGroupName      = $ResourceGroupName
            ResourceLocation       = $ResourceLocation
            ApplicationGatewayName = $ApplicationGatewayName
            KeyVaultName           = $KeyVaultName
        }
        $SslSetup = Get-ApplicationGatewaySslSetupAndIdentity @params

        <#
        $SslSetup.HandleSSL = $false
        if ($KeyVaultName) {
            $certificate = Get-AzKeyVaultCertificate -VaultName $KeyVaultName -Name "ApplicationGateway" -ErrorAction SilentlyContinue
            if ($certificate) {
                $SslSetup.HandleSSL = $true
            }
        }
        if ($SslSetup.HandleSSL) {
            Write-Verbose "Retrieving certificate from KeyVault"
            $secret = Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name "ApplicationGateway"
            $secretId = $secret.Id.Replace($secret.Version, "") # https://<keyvaultname>.vault.azure.net/secrets/
            $sslCertificate = New-AzApplicationGatewaySslCertificate -Name "$ApplicationGatewayName-certificate01" -KeyVaultSecretId $secretId
 
            # Identity is needed, to be able to read from KeyVault
            Write-Verbose "Generating identity for Application Gateway, to be able to read from KeyVault"
            $Identity = Get-AzUserAssignedIdentity -Name "$ApplicationGatewayName-Identity01" -ResourceGroupName $ResourceGroupName -ErrorAction SilentlyContinue
            if (-not($Identity)) {
                $Identity = New-AzUserAssignedIdentity -Name "$ApplicationGatewayName-Identity01" -ResourceGroupName $ResourceGroupName -Location $ResourceLocation
            }
            Wait-ForNewlyCreatedIdentity -ResourceGroupName $ResourceGroupName -ObjectId $Identity.PrincipalId -Verbose:$Verbose
 
            $AppgwIdentity = New-AzApplicationGatewayIdentity -UserAssignedIdentity $Identity.Id
            Write-Verbose "Updating KeyVault-access policy for new identity"
            Set-AzKeyVaultAccessPolicy -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -ObjectId $Identity.PrincipalId -PermissionsToKeys get -PermissionsToSecrets get -PermissionsToCertificates get
        }
        #>

        Write-Verbose "Setting up Application Gateway-configuration for $ApplicationGatewayName..."
        $params = @{
            VirtualNetworkResourceGroupName = $VirtualNetworkResourceGroupName
            VirtualNetworkName              = $VirtualNetworkName
            SubnetName                      = $SubnetName
            SubnetAddressPrefix             = $SubnetAddressPrefix
        }
        $NetworkSetup = New-ApplicationGatewayNetworkSetup @params -IncludeSsl:$SslSetup.HandleSSL -Verbose:$Verbose

        Write-Verbose "Adding BackendAddressPool..."
        $Pool = New-AzApplicationGatewayBackendAddressPool -Name $BackendPoolName

        $Probes = New-ApplicationGatewayProbeConfigs -Environments $environments -IncludeSsl:$SslSetup.HandleSSL -Verbose:$Verbose
        $HttpSettings = New-ApplicationGatewayHttpSettings  -Environments $environments -Probes $Probes -IncludeSsl:$SslSetup.HandleSSL

        # Create FrontendPorts
        $FrontEndPorts = New-ApplicationGatewayFrontendPorts -IncludeSsl:$SslSetup.HandleSSL -Verbose:$Verbose

        # Create FrontendIPConfigurations (incl. PublicIP if necessary)
        $params = @{
            ResourceGroupName           = $ResourceGroupName 
            ResourceLocation            = $ResourceLocation
            FrontEndIpConfigNamePrivate = $FrontEndIpConfigNamePrivate
            FrontEndIpConfigNamePublic  = $FrontEndIpConfigNamePublic
            PublicIpAddressName         = $PublicIpAddressName
            PrivateIpAddress            = $PrivateIpAddress
            PrivateIpAddressVersion     = $PrivateIpAddressVersion
            Subnet                      = $NetworkSetup.Subnet
        }
        $IpConfiguration = New-ApplicationGatewayIpConfigurations @params -Verbose:$Verbose

        # Create HttpListeners
        $params = @{
            IpConfiguration = $IpConfiguration
            FrontendPorts   = $FrontEndPorts            
        }
        if ($SslSetup.HandleSSL) {
            $params.Add("SslCertificate", $SslSetup.Certificate)
        }        
        $Listeners = New-ApplicationGatewayHttpListeners @params -IncludeSsl:$SslSetup.HandleSSL -Verbose:$Verbose

        # Create RoutingRules
        $Rules = New-ApplicationGatewayRoutingRules -HttpSettings $HttpSettings -Listeners $Listeners -BackendAddressPool $Pool -IncludeSsl:$SslSetup.HandleSSL

        # Create Sku
        $Sku = New-AzApplicationGatewaySku -Name $ApplicationGatewaySkuName -Tier $ApplicationGatewaySkuTier -Capacity $ApplicationGatewaySkuCapacity

        # Create Application Gateway
        $params = @{
            Name                          = $ApplicationGatewayName
            ResourceGroupName             = $ResourceGroupName
            Location                      = $ResourceLocation
            BackendAddressPools           = $Pool
            BackendHttpSettingsCollection = $HttpSettings.Collection
            FrontendIpConfigurations      = $IpConfiguration.Collection
            FrontendPorts                 = $FrontEndPorts.Collection
            Probes                        = $Probes.Collection
            GatewayIpConfigurations       = $NetworkSetup.GatewayIPConfiguration
            HttpListeners                 = $Listeners.Collection
            RequestRoutingRules           = $Rules.Collection
            Sku                           = $Sku            
        }
        if ($SslSetup.Identity) {
            $params.Add("Identity", $SslSetup.Identity)
        }
        if ($SslSetup.Certificate) {
            $params.Add("SslCertificates", $SslSetup.Certificate)
        }
        if ($Rules.RedirectConfiguration) {
            $params.Add("RedirectConfigurations", $Rules.RedirectConfiguration)
        }
        Write-Verbose "Creating ApplicationGateway..."
        $appGateway = New-AzApplicationGateway @params

        # Setup association of gateway with Scale Set
        Set-ApplicationGatewayAssociationForScaleSet -ResourceGroupName $ResourceGroupName -ApplicationGatewayName $ApplicationGatewayName -BackendPoolName $BackendPoolName -ScaleSetName $VMScaleSetName
    }    
}