0

Ported from Stackoverflow

I am building a Hub & Spoke network topology - described here - as recommended in the Azure docs

Hub Spoke topology diagram

However when it comes to create the VM in the separate VNet, I get the following when trying to link it to the Application Gateway in the Hub Virtual Network ("...Application Gateway must be in the same virtual network...") ...

error: You must select an application gateway in the same resource group

I have peered the Hub and Spoke virtual networks together using a peering at either end. Am I missing something here?

Brendan
  • 131
  • 5

2 Answers2

0

I would approach it differently, created a listerner in the app gateway for the ip of the vm which you want to protect with a app gateway. And add a public ip to the VM. https://docs.microsoft.com/en-us/azure/application-gateway/configuration-listeners https://docs.microsoft.com/en-us/azure/application-gateway/create-ssl-portal

Also allow the following in the NSG of the VM:

You must allow incoming Internet traffic on TCP ports 65503-65534 for the Application Gateway v1 SKU, and TCP ports 65200-65535 for the v2 SKU with the destination subnet as Any and source as GatewayManager service tag.

  1. Back end server pool: The list of IP addresses of the back end servers. The IP addresses listed should either belong to the VNet subnet, or should be a public IP/VIP.
  2. Back end server pool settings: Every pool has settings like port, protocol, and cookie based affinity. These settings are tied to a pool and are applied to all servers within the pool. Front end Port: This port is the public port opened on the application gateway. Traffic hits this port, and then gets redirected to one of the back end servers.
  3. Listener: The listener has a front end port, a protocol (Http or Https, these are case-sensitive), and the SSL certificate name (if configuring SSL offload).
  4. Rule: The rule binds the listener and the back end server pool and defines which back end server pool the traffic should be directed to when it hits a particular listener. Currently, only the basic rule is supported. The basic rule is round-robin load distribution.
Ace
  • 419
  • 6
  • Hmm, the point of the hub and spoke model is that traffic is not public in the spoke, only public endpoints are in the hub and all traffic is routed through e.g. the hub firewall - assigning a public IP to the VM in the spoke seems to go against this? – Brendan Jul 15 '22 at 08:08
  • Maybe this is helpful: https://rajanieshkaushikk.com/2021/11/16/azure-architecture-best-practice-for-securing-azure-virtual-networks/. – Ace Jul 15 '22 at 08:31
  • Whether placing the AppGW in the hub or the spokes is a design decision (whether the appgw is a central component shared across apps, or more app-specific) – Ace Jul 16 '22 at 22:24
0

Here is an ARM template also (gives you a overview)

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "sslCertificateData": {
            "type": "string",
            "metadata": {
                "description": "The base-64 encoded SSL certificate PFX data. Must be supplied via a parameters file references to a Key Vault / Secret Name."
            }
        },
        "sslCertificatePassword": {
            "type": "securestring",
            "metadata": {
                "description": "The SSL certificate password. Must be supplied via a parameters file references to a Key Vault / Secret Name."
            }
        },
        "vNetId": {
            "type": "string",
            "metadata": {
                "description": "The ID of the VNet."
            }
        },
        "subnetName": {
            "type": "string",
            "metadata": {
                "description": "The name of the DMZ Subnet."
            }
        }

    },
    "variables": {
        "networkApiVersion": "2017-04-01",

        "subnetId": "[concat(parameters('vNetId'), '/subnets/', parameters('subnetName'))]",

        "appGatewayPublicIpAddressId": "[resourceId('Microsoft.Network/publicIPAddresses', 'appGatewayPublicIpAddress')]",

        "appGwId": "[resourceId('Microsoft.Network/applicationGateways', 'appGateway')]",

        "appGwSize": "Standard_Small",
        "appGwTier": "Standard",
        "appGwCapacity": 5,
        "appGwFePort": 443,
        "appGwFeProtocol": "Https",
        "appGwBePort": 80,
        "appGwBEProtocol": "Http"
    },
    "resources": [
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "name": "appGatewayPublicIpAddress",
            "location": "[resourceGroup().location]",
            "apiVersion": "[variables('networkApiVersion')]",
            "comments": "This creates a single, dynamically allocated public IP address for use by the Application Gateway.",
            "properties": {
                "publicIPAllocationMethod": "Dynamic"
            }
        },
        {
            "type": "Microsoft.Network/applicationGateways",
            "name": "appGateway",
            "location": "[resourceGroup().location]",
            "apiVersion": "[variables('networkApiVersion')]",
            "comments": "This creates the Application Gateway.",
            "dependsOn": [
                "[concat('Microsoft.Network/publicIPAddresses/', 'appGatewayPublicIpAddress')]"
            ],
            "properties": {
                "sku": {
                    "name": "[variables('appGwSize')]",
                    "tier": "[variables('appGwTier')]",
                    "capacity": "[variables('appGwCapacity')]"
                },
                "gatewayIPConfigurations": [
                    {
                        "name": "gatewayIpCofig",
                        "properties": {
                            "subnet": {
                                "id": "[variables('subnetId')]"
                            }
                        }
                    }
                ],
                "frontendIPConfigurations": [
                    {
                        "name": "frontendIpConfig",
                        "properties": {
                            "PublicIPAddress": {
                                "id": "[variables('appGatewayPublicIpAddressId')]"
                            }
                        }
                    }
                ],
                "frontendPorts": [
                    {
                        "name": "frontendPort",
                        "properties": {
                            "Port": "[variables('appGwFePort')]"
                        }
                    }
                ],
                "sslCertificates": [
                    {
                        "name": "appGwSslCertificate",
                        "properties": {
                            "data": "[parameters('sslCertificateData')]",
                            "password": "[parameters('sslCertificatePassword')]"
                        }
                    }
                ],
                "backendAddressPools": [
                    {
                        "name": "BackendAddressPool"
                    }
                ],
                "backendHttpSettingsCollection": [
                    {
                        "name": "HttpSettings",
                        "properties": {
                            "Port": "[variables('appGwBePort')]",
                            "Protocol": "[variables('appGwBeProtocol')]"
                        }
                    }
                ],
                "httpListeners": [
                    {
                        "name": "HttpListener",
                        "properties": {
                            "FrontendIPConfiguration": {
                                "Id": "[concat(variables('appGwId'), '/frontendIPConfigurations/frontendIpConfig')]"
                            },
                            "FrontendPort": {
                                "Id": "[concat(variables('appGwId'), '/frontendPorts/frontendPort')]"
                            },
                            "Protocol": "[variables('appGwFeProtocol')]",
                            "SslCertificate": {
                                "id": "[concat(variables('appGwId'), '/sslCertificates/appGwSslCertificate')]"
                            }
                        }
                    }
                ],
                "requestRoutingRules": [
                    {
                        "Name": "RoutingRule",
                        "properties": {
                            "RuleType": "Basic",
                            "httpListener": {
                                "id": "[concat(variables('appGwId'), '/httpListeners/HttpListener')]"
                            },
                            "backendAddressPool": {
                                "id": "[concat(variables('appGwId'), '/backendAddressPools/BackendAddressPool')]"
                            },
                            "backendHttpSettings": {
                                "id": "[concat(variables('appGwId'), '/backendHttpSettingsCollection/HttpSettings')]"
                            }
                        }
                    }
                ]
            }
        }
    ]
}
```

### ARM Template Parameter File

*app-gateway-parameters.json*
```
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "sslCertificateData": {
            "reference": {
                "keyVault": {
                    "id": "/subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/KEY_VAULT_NAME"
                },
                "secretName": "CERT_SECRET_NAME"
            }
        },
        "sslCertificatePassword": {
            "reference": {
                "keyVault": {
                    "id": "/subscriptions/SUBSCRIPTION_ID/resourcegroups/RESOURCE_GROUP/providers/Microsoft.KeyVault/vaults/KEY_VAULT_NAME"
                },
                "secretName": "CERT_PASSWORD_SECRET_NAME"
            }
        },
        "vNetId": {
            "value": "/subscriptions/SUBSCRIPTION_ID/resourceGroups/RESOURCE_GROUP/providers/Microsoft.Network/virtualNetworks/VNET_NAME"
        },
        "subnetName": {
            "value": "SUBNET_NAME"
        }
    }
}
Ace
  • 419
  • 6