diff --git a/solutions/secure-hybrid-network/README.md b/solutions/secure-hybrid-network/README.md index fb48bdb0..ad0eea01 100644 --- a/solutions/secure-hybrid-network/README.md +++ b/solutions/secure-hybrid-network/README.md @@ -26,11 +26,11 @@ For detailed information, see the Implement a secure hybrid network: ## Deploy sample -Run the following command to initiate the deployment. When prompted, enter values for an admin user name and password. These values are used to log into the included virtual machines. +Clone this repo and then run the following commands to initiate the deployment. When prompted, enter values for an admin username and password. These values are used to log into the included virtual machines. ```azurecli-interactive -az deployment sub create \ - --template-uri https://raw.githubusercontent.com/mspnp/samples/main/solutions/secure-hybrid-network/azuredeploy.json --location eastus +cd solutions/secure-hybrid-network +az deployment sub create --location eastus --template-file azuredeploy.bicep ``` ## Solution deployment parameters diff --git a/solutions/secure-hybrid-network/azuredeploy.bicep b/solutions/secure-hybrid-network/azuredeploy.bicep new file mode 100644 index 00000000..c66eed21 --- /dev/null +++ b/solutions/secure-hybrid-network/azuredeploy.bicep @@ -0,0 +1,64 @@ +targetScope = 'subscription' +param mocOnPremResourceGroup string = 'site-to-site-mock-prem' +param azureNetworkResourceGroup string = 'site-to-site-azure-network' + +@description('The admin user name for both the Windows and Linux virtual machines.') +param adminUserName string + +@description('The admin password for both the Windows and Linux virtual machines.') +@secure() +param adminPassword string +param resourceGrouplocation string = 'eastus' + +resource mocOnPremResourceGroup_resource 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: mocOnPremResourceGroup + location: resourceGrouplocation +} + +resource azureNetworkResourceGroup_resource 'Microsoft.Resources/resourceGroups@2022-09-01' = { + name: azureNetworkResourceGroup + location: resourceGrouplocation +} + +module onPremMock 'nestedtemplates/mock-onprem-azuredeploy.bicep' = { + name: 'onPremMock' + scope: mocOnPremResourceGroup_resource + params: { + adminUserName: adminUserName + adminPassword: adminPassword + location: resourceGrouplocation + } +} + +module azureNetwork 'nestedtemplates/azure-network-azuredeploy.bicep' = { + name: 'azureNetwork' + scope: azureNetworkResourceGroup_resource + params: { + adminUserName: adminUserName + adminPassword: adminPassword + location: resourceGrouplocation + } +} + +module mockOnPremLocalGateway 'nestedtemplates/mock-onprem-local-gateway.bicep' = { + name: 'mockOnPremLocalGateway' + scope: mocOnPremResourceGroup_resource + params: { + gatewayIpAddress: azureNetwork.outputs.vpnIp + azureCloudVnetPrefix: azureNetwork.outputs.mocOnpremNetwork + spokeNetworkAddressPrefix: azureNetwork.outputs.spokeNetworkAddressPrefix + mocOnpremGatewayName: onPremMock.outputs.mocOnpremGatewayName + location: resourceGrouplocation + } +} + +module azureNetworkLocalGateway 'nestedtemplates/azure-network-local-gateway.bicep' = { + name: 'azureNetworkLocalGateway' + scope: azureNetworkResourceGroup_resource + params: { + azureCloudVnetPrefix: onPremMock.outputs.mocOnpremNetworkPrefix + gatewayIpAddress: onPremMock.outputs.vpnIp + azureNetworkGatewayName: azureNetwork.outputs.azureGatewayName + location: resourceGrouplocation + } +} diff --git a/solutions/secure-hybrid-network/nestedtemplates/azure-network-azuredeploy.bicep b/solutions/secure-hybrid-network/nestedtemplates/azure-network-azuredeploy.bicep new file mode 100644 index 00000000..89bf4a4e --- /dev/null +++ b/solutions/secure-hybrid-network/nestedtemplates/azure-network-azuredeploy.bicep @@ -0,0 +1,744 @@ +param adminUserName string = 'azureadmin' + +@secure() +param adminPassword string + +@description('The count of Windows virtual machines to create.') +param windowsVMCount int = 2 +param vmSize string = 'Standard_A1_v2' +param configureSitetosite bool = true +param hubNetwork object = { + name: 'vnet-hub' + addressPrefix: '10.0.0.0/20' +} +param spokeNetwork object = { + name: 'vnet-spoke' + addressPrefix: '10.100.0.0/16' + subnetName: 'snet-spoke-resources' + subnetPrefix: '10.100.0.0/16' + subnetNsgName: 'nsg-spoke-resources' +} +param vpnGateway object = { + name: 'vpn-azure-network' + subnetName: 'GatewaySubnet' + subnetPrefix: '10.0.2.0/27' + publicIPAddressName: 'pip-vgn-gateway' +} +param bastionHost object = { + name: 'AzureBastionHost' + subnetName: 'AzureBastionSubnet' + subnetPrefix: '10.0.1.0/29' + publicIPAddressName: 'pip-bastion' + nsgName: 'nsg-hub-bastion' +} +param azureFirewall object = { + name: 'AzureFirewall' + subnetName: 'AzureFirewallSubnet' + subnetPrefix: '10.0.3.0/26' + publicIPAddressName: 'pip-firewall' +} +param spokeRoutes object = { + tableName: 'spoke-routes' + routeNameFirewall: 'spoke-to-firewall' +} +param gatewayRoutes object = { + tableName: 'gateway-routes' + routeNameFirewall: 'gateway-to-firewall' +} +param internalLoadBalancer object = { + name: 'lb-internal' + backendName: 'lb-backend' + fontendName: 'lb-frontend' + probeName: 'lb-probe' +} +param location string + +var logAnalyticsWorkspaceName = 'la-${uniqueString(subscription().subscriptionId, resourceGroup().id)}' +var peering_name_hub_to_spoke = 'hub-to-spoke' +var peering_name_spoke_to_hub = 'spoke-to-hub' +var nicNameWebName = 'nic-web-server' +var vmNameWebName = 'vm-web-server' +var windowsOSVersion = '2012-R2-Datacenter' + +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { + name: logAnalyticsWorkspaceName + location: location + properties: { + sku: { + name: 'PerGB2018' + } + features: { + searchVersion: 1 + } + } +} + +resource gatewayRoutes_table 'Microsoft.Network/routeTables@2023-04-01' = { + name: gatewayRoutes.tableName + location: location + properties: { + disableBgpRoutePropagation: false + } +} + +resource spokeRoutes_table 'Microsoft.Network/routeTables@2023-04-01' = { + name: spokeRoutes.tableName + location: location + properties: { + disableBgpRoutePropagation: false + } +} + +resource bastionHost_nsg 'Microsoft.Network/networkSecurityGroups@2023-04-01' = { + name: bastionHost.nsgName + location: location + properties: { + securityRules: [ + { + name: 'bastion-in-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'Internet' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'bastion-control-in-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'GatewayManager' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 120 + direction: 'Inbound' + } + } + { + name: 'bastion-in-host' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRanges: [ + '8080' + '5701' + ] + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 130 + direction: 'Inbound' + } + } + { + name: 'bastion-vnet-out-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'bastion-azure-out-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRange: '443' + destinationAddressPrefix: 'AzureCloud' + access: 'Allow' + priority: 120 + direction: 'Outbound' + } + } + { + name: 'bastion-out-host' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRanges: [ + '8080' + '5701' + ] + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 130 + direction: 'Outbound' + } + } + { + name: 'bastion-out-deny' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: '*' + destinationAddressPrefix: '*' + access: 'Deny' + priority: 1000 + direction: 'Outbound' + } + } + ] + } +} + +resource hubNetworkResource 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: hubNetwork.name + location: location + properties: { + addressSpace: { + addressPrefixes: [ + hubNetwork.addressPrefix + ] + } + subnets: [ + { + name: vpnGateway.subnetName + properties: { + addressPrefix: vpnGateway.subnetPrefix + routeTable: { + id: gatewayRoutes_table.id + } + } + } + { + name: azureFirewall.subnetName + properties: { + addressPrefix: azureFirewall.subnetPrefix + } + } + { + name: bastionHost.subnetName + properties: { + addressPrefix: bastionHost.subnetPrefix + networkSecurityGroup: { + id: bastionHost_nsg.id + } + } + } + ] + } +} + +resource hubNetwork_name_Microsoft_Insights_default_logAnalyticsWorkspace 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: hubNetworkResource + name: logAnalyticsWorkspaceName + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'VMProtectionAlerts' + enabled: true + } + ] + metrics: [ + { + category: 'AllMetrics' + enabled: true + } + ] + } +} + +resource spokeNetwork_subnetNsg 'Microsoft.Network/networkSecurityGroups@2023-04-01' = { + name: spokeNetwork.subnetNsgName + location: location + properties: { + securityRules: [ + { + name: 'allow-http-traffic-from-external' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '80' + sourceAddressPrefix: '*' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'allow-http-traffic-from-vnet' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '80' + sourceAddressPrefix: '10.0.0.0/16' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 110 + direction: 'Inbound' + } + } + ] + } +} + +resource spokeNetworkResource 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: spokeNetwork.name + location: location + properties: { + addressSpace: { + addressPrefixes: [ + spokeNetwork.addressPrefix + ] + } + subnets: [ + { + name: spokeNetwork.subnetName + properties: { + addressPrefix: spokeNetwork.addressPrefix + networkSecurityGroup: { + id: spokeNetwork_subnetNsg.id + } + routeTable: { + id: spokeRoutes_table.id + } + } + } + ] + } +} + +resource bastionHost_nsgName_Microsoft_Insights_default_logAnalyticsWorkspace 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: bastionHost_nsg + name: logAnalyticsWorkspaceName + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'NetworkSecurityGroupEvent' + enabled: true + } + { + category: 'NetworkSecurityGroupRuleCounter' + enabled: true + } + ] + } +} + +resource bastionHost_publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-04-01' = { + name: bastionHost.publicIPAddressName + location: location + sku: { + name: 'Standard' + } + properties: { + publicIPAllocationMethod: 'Static' + } +} + +resource bastionHostResource 'Microsoft.Network/bastionHosts@2023-04-01' = { + name: bastionHost.name + location: location + properties: { + ipConfigurations: [ + { + name: 'IpConf' + properties: { + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', hubNetworkResource.name, bastionHost.subnetName) + } + publicIPAddress: { + id: bastionHost_publicIPAddress.id + } + } + } + ] + } +} + +resource spokeNetwork_name_Microsoft_Insights_default_logAnalyticsWorkspace 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: spokeNetworkResource + name: logAnalyticsWorkspaceName + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'VMProtectionAlerts' + enabled: true + } + ] + metrics: [ + { + category: 'AllMetrics' + enabled: true + } + ] + } +} + +resource vpnGateway_publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-04-01' = if (configureSitetosite) { + name: vpnGateway.publicIPAddressName + location: location + properties: { + publicIPAllocationMethod: 'Dynamic' + } +} + +resource vpnGatewayResource 'Microsoft.Network/virtualNetworkGateways@2023-04-01' = if (configureSitetosite) { + name: vpnGateway.name + location: location + properties: { + ipConfigurations: [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', hubNetworkResource.name, vpnGateway.subnetName) + } + publicIPAddress: { + id: vpnGateway_publicIPAddress.id + } + } + name: 'vnetGatewayConfig' + } + ] + sku: { + name: 'VpnGw2' + tier: 'VpnGw2' + } + gatewayType: 'Vpn' + vpnType: 'RouteBased' + enableBgp: false + bgpSettings: { + asn: 65001 + } + } +} + +resource vpnGatewayResource_Microsoft_Insights_default_logAnalyticsWorkspace 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (configureSitetosite) { + scope: vpnGatewayResource + name: logAnalyticsWorkspaceName + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'GatewayDiagnosticLog' + enabled: true + } + { + category: 'TunnelDiagnosticLog' + enabled: true + } + { + category: 'RouteDiagnosticLog' + enabled: true + } + { + category: 'IKEDiagnosticLog' + enabled: true + } + { + category: 'P2SDiagnosticLog' + enabled: true + } + ] + } +} + +resource azureFirewall_publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-04-01' = { + name: azureFirewall.publicIPAddressName + location: location + sku: { + name: 'Standard' + } + properties: { + publicIPAllocationMethod: 'Static' + } +} + +resource azureFirewallResource 'Microsoft.Network/azureFirewalls@2023-04-01' = { + name: azureFirewall.name + location: location + properties: { + sku: { + name: 'AZFW_VNet' + tier: 'Standard' + } + threatIntelMode: 'Alert' + ipConfigurations: [ + { + name: azureFirewall.name + properties: { + publicIPAddress: { + id: azureFirewall_publicIPAddress.id + } + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', hubNetworkResource.name, azureFirewall.subnetName) + } + } + } + ] + applicationRuleCollections: [ + { + name: 'spoke-outbound' + properties: { + priority: 100 + action: { + type: 'Allow' + } + rules: [ + { + name: 'all-internet' + protocols: [ + { + protocolType: 'Http' + port: 80 + } + { + protocolType: 'Https' + port: 443 + } + ] + targetFqdns: [ + '*' + ] + sourceAddresses: [ + '*' + ] + } + ] + } + } + ] + } +} + +resource azureFirewallResource_Microsoft_Insights_default_logAnalyticsWorkspace 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: azureFirewallResource + name: logAnalyticsWorkspaceName + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'AzureFirewallApplicationRule' + enabled: true + } + { + category: 'AzureFirewallNetworkRule' + enabled: true + } + { + category: 'AzureFirewallDnsProxy' + enabled: true + } + ] + } +} + +resource spokeNetwork_subnetNsgName_Microsoft_Insights_default_logAnalyticsWorkspace 'Microsoft.Network/networkSecurityGroups/providers/diagnosticSettings@2017-05-01-preview' = { + name: '${spokeNetwork.subnetNsgName}/Microsoft.Insights/default${logAnalyticsWorkspaceName}' + properties: { + workspaceId: logAnalyticsWorkspace.id + logs: [ + { + category: 'NetworkSecurityGroupEvent' + enabled: true + } + { + category: 'NetworkSecurityGroupRuleCounter' + enabled: true + } + ] + } + dependsOn: [ + spokeNetwork_subnetNsg + + ] +} + +resource internalLoadBalancerResource 'Microsoft.Network/loadBalancers@2023-04-01' = { + name: internalLoadBalancer.name + location: location + sku: { + name: 'Standard' + } + properties: { + frontendIPConfigurations: [ + { + name: internalLoadBalancer.fontendName + properties: { + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', spokeNetworkResource.name, spokeNetwork.subnetName) + } + privateIPAllocationMethod: 'Dynamic' + } + } + ] + backendAddressPools: [ + { + name: internalLoadBalancer.backendName + } + ] + loadBalancingRules: [ + { + name: internalLoadBalancer.probeName + properties: { + frontendIPConfiguration: { + id: resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', internalLoadBalancer.name, internalLoadBalancer.fontendName) + } + frontendPort: 80 + backendPort: 80 + enableFloatingIP: false + idleTimeoutInMinutes: 4 + protocol: 'Tcp' + enableTcpReset: false + loadDistribution: 'Default' + disableOutboundSnat: false + backendAddressPool: { + id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', internalLoadBalancer.name, internalLoadBalancer.backendName) + } + probe: { + id: '${resourceId('Microsoft.Network/loadBalancers', internalLoadBalancer.name)}/probes/${internalLoadBalancer.probeName}' + } + } + } + ] + probes: [ + { + name: internalLoadBalancer.probeName + properties: { + protocol: 'Http' + port: 80 + requestPath: '/' + intervalInSeconds: 15 + numberOfProbes: 2 + } + } + ] + } +} + +resource internalLoadBalancer_name_Microsoft_Insights_default_logAnalyticsWorkspace 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + scope: internalLoadBalancerResource + name: logAnalyticsWorkspaceName + properties: { + workspaceId: logAnalyticsWorkspace.id + metrics: [ + { + category: 'AllMetrics' + enabled: true + } + ] + } +} + +resource gatewayRoutes_tableName_gatewayRoutes_routeNameFirewall 'Microsoft.Network/routeTables/routes@2023-04-01' = { + parent: gatewayRoutes_table + name: gatewayRoutes.routeNameFirewall + properties: { + addressPrefix: spokeNetwork.addressPrefix + nextHopType: 'VirtualAppliance' + nextHopIpAddress: reference(azureFirewallResource.id, '2020-05-01').ipConfigurations[0].properties.privateIpAddress + } +} + +resource spokeRoutes_tableName_spokeRoutes_routeNameFirewall 'Microsoft.Network/routeTables/routes@2020-07-01' = { + parent: spokeRoutes_table + name: spokeRoutes.routeNameFirewall + properties: { + addressPrefix: '0.0.0.0/0' + nextHopType: 'VirtualAppliance' + nextHopIpAddress: reference(azureFirewallResource.id, '2020-05-01').ipConfigurations[0].properties.privateIpAddress + } +} + +resource nicNameWeb 'Microsoft.Network/networkInterfaces@2023-04-01' = [for i in range(0, windowsVMCount): { + name: '${nicNameWebName}${i}' + location: location + properties: { + ipConfigurations: [ + { + name: 'ipconfig' + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', spokeNetworkResource.name, spokeNetwork.subnetName) + } + loadBalancerBackendAddressPools: [ + { + id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', internalLoadBalancer.name, internalLoadBalancer.backendName) + } + ] + } + } + ] + } + dependsOn:[ + internalLoadBalancerResource] +}] + +resource vmNameWeb 'Microsoft.Compute/virtualMachines@2023-03-01' = [for i in range(0, windowsVMCount): { + name: '${vmNameWebName}${i}' + location: location + properties: { + hardwareProfile: { + vmSize: vmSize + } + osProfile: { + computerName: '${vmNameWebName}${i}' + adminUsername: adminUserName + adminPassword: adminPassword + } + storageProfile: { + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: windowsOSVersion + version: 'latest' + } + osDisk: { + createOption: 'FromImage' + } + } + networkProfile: { + networkInterfaces: [ + { + id: nicNameWeb[i].id + } + ] + } + }}] + +resource vmNameWeb_installIIS 'Microsoft.Compute/virtualMachines/extensions@2023-03-01' = [for i in range(0, windowsVMCount): { + name: '${vmNameWebName}${i}/installIIS' + location: location + properties: { + publisher: 'Microsoft.Compute' + type: 'CustomScriptExtension' + typeHandlerVersion: '1.7' + autoUpgradeMinorVersion: true + settings: { + commandToExecute: 'powershell.exe Install-WindowsFeature -name Web-Server -IncludeManagementTools' + } + } + dependsOn: [ + vmNameWeb[i] + ] +}] + + +output vpnIp string = vpnGatewayResource.properties.bgpSettings.bgpPeeringAddresses[0].tunnelIpAddresses[0] +output mocOnpremNetwork string = hubNetwork.addressPrefix +output spokeNetworkAddressPrefix string = spokeNetwork.addressPrefix +output azureGatewayName string = vpnGateway.name + diff --git a/solutions/secure-hybrid-network/nestedtemplates/azure-network-azuredeploy.json b/solutions/secure-hybrid-network/nestedtemplates/azure-network-azuredeploy.json index a4e2774f..009d0c4b 100644 --- a/solutions/secure-hybrid-network/nestedtemplates/azure-network-azuredeploy.json +++ b/solutions/secure-hybrid-network/nestedtemplates/azure-network-azuredeploy.json @@ -522,12 +522,15 @@ } ], "sku": { - "name": "Basic", - "tier": "Basic" + "name": "VpnGw2", + "tier": "VpnGw2" }, "gatewayType": "Vpn", "vpnType": "RouteBased", - "enableBgp": false + "enableBgp": false, + "bgpSettings":{ + "asn": 60001 + } }, "resources": [ { diff --git a/solutions/secure-hybrid-network/nestedtemplates/azure-network-local-gateway.bicep b/solutions/secure-hybrid-network/nestedtemplates/azure-network-local-gateway.bicep new file mode 100644 index 00000000..421b11c3 --- /dev/null +++ b/solutions/secure-hybrid-network/nestedtemplates/azure-network-local-gateway.bicep @@ -0,0 +1,45 @@ +param connectionName string = 'hub-to-mock-prem' +param gatewayIpAddress string +param azureCloudVnetPrefix string +param azureNetworkGatewayName string +param localNetworkGatewayName string = 'local-gateway-azure-network' +param location string + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2023-04-01' = { + name: localNetworkGatewayName + location: location + properties: { + localNetworkAddressSpace: { + addressPrefixes: [ + azureCloudVnetPrefix + ] + } + gatewayIpAddress: gatewayIpAddress + bgpSettings: { + asn: 40000 + bgpPeeringAddress: gatewayIpAddress + } + } +} + +resource connection 'Microsoft.Network/connections@2023-04-01' = { + name: connectionName + location: location + properties: { + virtualNetworkGateway1: { + id: resourceId('Microsoft.Network/virtualNetworkGateways', azureNetworkGatewayName) + } + localNetworkGateway2: { + id: localNetworkGateway.id + } + connectionType: 'IPsec' + connectionProtocol: 'IKEv2' + routingWeight: 100 + sharedKey: '123secret' + enableBgp: false + useLocalAzureIpAddress: false + usePolicyBasedTrafficSelectors: false + expressRouteGatewayBypass: false + dpdTimeoutSeconds: 0 + } +} diff --git a/solutions/secure-hybrid-network/nestedtemplates/azure-network-local-gateway.json b/solutions/secure-hybrid-network/nestedtemplates/azure-network-local-gateway.json index 05632602..7a7026c9 100644 --- a/solutions/secure-hybrid-network/nestedtemplates/azure-network-local-gateway.json +++ b/solutions/secure-hybrid-network/nestedtemplates/azure-network-local-gateway.json @@ -35,7 +35,11 @@ "[parameters('azureCloudVnetPrefix')]" ] }, - "gatewayIpAddress": "[parameters('gatewayIpAddress')]" + "gatewayIpAddress": "[parameters('gatewayIpAddress')]", + "bgpSettings": { + "asn": 40000, + "bgpPeeringAddress": "[parameters('gatewayIpAddress')]" + } } }, { diff --git a/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-azuredeploy.bicep b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-azuredeploy.bicep new file mode 100644 index 00000000..5b9259a6 --- /dev/null +++ b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-azuredeploy.bicep @@ -0,0 +1,296 @@ +param adminUserName string + +@secure() +param adminPassword string +param mocOnpremNetwork object = { + name: 'vnet-onprem' + addressPrefix: '192.168.0.0/16' + subnetName: 'mgmt' + subnetPrefix: '192.168.1.128/25' +} +param mocOnpremGateway object = { + name: 'vpn-mock-prem' + subnetName: 'GatewaySubnet' + subnetPrefix: '192.168.255.224/27' + publicIPAddressName: 'pip-onprem-vpn-gateway' +} +param bastionHost object = { + name: 'AzureBastionHost' + subnetName: 'AzureBastionSubnet' + subnetPrefix: '192.168.254.0/27' + publicIPAddressName: 'pip-bastion' + nsgName: 'nsg-hub-bastion' +} +param vmSize string = 'Standard_A1_v2' +param configureSitetosite bool = true +param location string + +var nicNameWindowsName = 'nic-windows' +var vmNameWindowsName = 'vm-windows' +var windowsOSVersion = '2016-Datacenter' + +resource mocOnpremNetworkResource 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: mocOnpremNetwork.name + location: location + properties: { + addressSpace: { + addressPrefixes: [ + mocOnpremNetwork.addressPrefix + ] + } + subnets: [ + { + name: mocOnpremNetwork.subnetName + properties: { + addressPrefix: mocOnpremNetwork.subnetPrefix + } + } + { + name: mocOnpremGateway.subnetName + properties: { + addressPrefix: mocOnpremGateway.subnetPrefix + } + } + { + name: bastionHost.subnetName + properties: { + addressPrefix: bastionHost.subnetPrefix + } + } + ] + } +} + +resource mocOnpremGateway_publicIPAddress 'Microsoft.Network/publicIPAddresses@2023-04-01' = if (configureSitetosite) { + name: mocOnpremGateway.publicIPAddressName + location: location + properties: { + publicIPAllocationMethod: 'Dynamic' + } +} + +resource mocOnpremGatewayResource 'Microsoft.Network/virtualNetworkGateways@2023-04-01' = if (configureSitetosite) { + name: mocOnpremGateway.name + location: location + properties: { + ipConfigurations: [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', mocOnpremNetworkResource.name, mocOnpremGateway.subnetName) + } + publicIPAddress: { + id: mocOnpremGateway_publicIPAddress.id + } + } + name: 'vnetGatewayConfig' + } + ] + sku: { + name: 'VpnGw2' + tier: 'VpnGw2' + } + gatewayType: 'Vpn' + vpnType: 'RouteBased' + enableBgp: false + bgpSettings: { + asn: 65001 + } + } +} + +resource bastionHost_publicIPAddress 'Microsoft.Network/publicIpAddresses@2023-04-01' = { + name: bastionHost.publicIPAddressName + location: location + sku: { + name: 'Standard' + } + properties: { + publicIPAllocationMethod: 'Static' + } +} + +resource bastionHost_nsg 'Microsoft.Network/networkSecurityGroups@2023-04-01' = { + name: bastionHost.nsgName + location: location + properties: { + securityRules: [ + { + name: 'bastion-in-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'Internet' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'bastion-control-in-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'GatewayManager' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 120 + direction: 'Inbound' + } + } + { + name: 'bastion-in-host' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRanges: [ + '8080' + '5701' + ] + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 130 + direction: 'Inbound' + } + } + { + name: 'bastion-vnet-out-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'bastion-azure-out-allow' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRange: '443' + destinationAddressPrefix: 'AzureCloud' + access: 'Allow' + priority: 120 + direction: 'Outbound' + } + } + { + name: 'bastion-out-host' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRanges: [ + '8080' + '5701' + ] + sourceAddressPrefix: 'VirtualNetwork' + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 130 + direction: 'Outbound' + } + } + { + name: 'bastion-out-deny' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: '*' + destinationAddressPrefix: '*' + access: 'Deny' + priority: 1000 + direction: 'Outbound' + } + } + ] + } +} + +resource bastionHostResource 'Microsoft.Network/bastionHosts@2023-04-01' = { + name: bastionHost.name + location: location + properties: { + ipConfigurations: [ + { + name: 'IpConf' + properties: { + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', mocOnpremNetworkResource.name, bastionHost.subnetName) + } + publicIPAddress: { + id: bastionHost_publicIPAddress.id + } + } + } + ] + } +} + +resource nicNameWindows 'Microsoft.Network/networkInterfaces@2023-04-01' = { + name: nicNameWindowsName + location: location + properties: { + ipConfigurations: [ + { + name: 'ipconfig' + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: resourceId('Microsoft.Network/virtualNetworks/subnets', mocOnpremNetworkResource.name, mocOnpremNetwork.subnetName) + } + } + } + ] + } +} + +resource vmNameWindows 'Microsoft.Compute/virtualMachines@2023-03-01' = { + name: vmNameWindowsName + location: location + properties: { + hardwareProfile: { + vmSize: vmSize + } + osProfile: { + computerName: vmNameWindowsName + adminUsername: adminUserName + adminPassword: adminPassword + } + storageProfile: { + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: windowsOSVersion + version: 'latest' + } + osDisk: { + createOption: 'FromImage' + } + } + networkProfile: { + networkInterfaces: [ + { + id: nicNameWindows.id + } + ] + } + } +} + +output vpnIp string = mocOnpremGatewayResource.properties.bgpSettings.bgpPeeringAddresses[0].tunnelIpAddresses[0] +output mocOnpremNetworkPrefix string = mocOnpremNetwork.addressPrefix +output mocOnpremGatewayName string = mocOnpremGateway.name diff --git a/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-azuredeploy.json b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-azuredeploy.json index 3400b6f3..5a5ce1f8 100644 --- a/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-azuredeploy.json +++ b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-azuredeploy.json @@ -126,12 +126,15 @@ } ], "sku": { - "name": "Basic", - "tier": "Basic" + "name": "VpnGw2", + "tier": "VpnGw2" }, "gatewayType": "Vpn", "vpnType": "RouteBased", - "enableBgp": false + "enableBgp": false, + "bgpSettings":{ + "asn": 60001 + } } }, { diff --git a/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-local-gateway.bicep b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-local-gateway.bicep new file mode 100644 index 00000000..d12ffc50 --- /dev/null +++ b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-local-gateway.bicep @@ -0,0 +1,47 @@ +param connectionName string = 'mock-prem-to-hub' +param azureCloudVnetPrefix string +param spokeNetworkAddressPrefix string +param gatewayIpAddress string +param mocOnpremGatewayName string +param localNetworkGateway string = 'local-gateway-moc-prem' +param location string + +resource localNetworkGateway_resource 'Microsoft.Network/localNetworkGateways@2023-04-01' = { + name: localNetworkGateway + location: location + properties: { + localNetworkAddressSpace: { + addressPrefixes: [ + azureCloudVnetPrefix + spokeNetworkAddressPrefix + ] + } + gatewayIpAddress: gatewayIpAddress + bgpSettings: { + asn: 40000 + bgpPeeringAddress: gatewayIpAddress + } + } +} + +resource connection 'Microsoft.Network/connections@2023-04-01' = { + name: connectionName + location: location + properties: { + virtualNetworkGateway1: { + id: resourceId('Microsoft.Network/virtualNetworkGateways', mocOnpremGatewayName) + } + localNetworkGateway2: { + id: localNetworkGateway_resource.id + } + connectionType: 'IPsec' + connectionProtocol: 'IKEv2' + routingWeight: 100 + sharedKey: '123secret' + enableBgp: false + useLocalAzureIpAddress: false + usePolicyBasedTrafficSelectors: false + expressRouteGatewayBypass: false + dpdTimeoutSeconds: 0 + } +} diff --git a/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-local-gateway.json b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-local-gateway.json index c1fa8449..9365b96f 100644 --- a/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-local-gateway.json +++ b/solutions/secure-hybrid-network/nestedtemplates/mock-onprem-local-gateway.json @@ -39,7 +39,11 @@ "[parameters('spokeNetworkAddressPrefix')]" ] }, - "gatewayIpAddress": "[parameters('gatewayIpAddress')]" + "gatewayIpAddress": "[parameters('gatewayIpAddress')]", + "bgpSettings": { + "asn": 40000, + "bgpPeeringAddress": "[parameters('gatewayIpAddress')]" + } } }, {