Posted: Wednesday, January 11, 2023
Word Count: 2749
Reading Time: 12 minutes
The following Azure vWAN deployment includes the following:
Azure VWAN Bicep Code: | Click Here |
Visual Studio Code: | Click Here |
AZ Cli Download: | Click Here |
Resource | Cost per hour |
Virtual Machines x 3 | $0.28 |
Virtual WAN | $0.35 |
Virtual Networks x 3 | $0.02 |
Azure Bastion x 3 | $0.57 |
Azure Firewall | $1.57 |
Bastion hosts can be leveraged to connect to any of the virtual machines by leveraging the password that was set during deployments. The admin account is the <machinename>-Admin. Two network rules have been created for intranet communication: RDP and ICMP. ICMP will not respond until the virtual machine’s local firewall is either adjusted or disabled. RDP should be immediately available.
To deploy, run the command below:
az deployment sub create --name TestDeploy --location eastus --template-file 'main.bicep' --parameters 'parameters.json' --what-if
Note: Remove the –what-if switch to deploy the lab.
Modules | Description |
---|---|
AzureFirewall.bicep | Provisions Azure Firewall to secure the virtual hub |
AzureFirewallPolicy.bicep | Creates a simple application rule that allows outbound http/https communication. |
Compute.bicep | Provisions azure virtual compute resources |
ResourceGroup.bicep | Provisions resource groups to the desired subscription |
virtualnetwork.bicep | Provisions the virtual networks that will support the subnets |
subnet.bicep | deploys subnets within the designated virtual network |
routetable.bicep | basic route table to allow communication between all subnets / vnets |
subnet-nsg.bicep | creates default nsg for provisioned subnets |
virtualhub.bicep | provisions virtual hub within designated virtual WAN |
vhubnetworkconnection.bicep | establishes connections between vhub and vnets |
bastionhost.bicep | deploys bastion host remote capability into the designated spokes |
bastionhostnsg.bicep | NSG rules that are provisioned to the bastionhost subnet. |
The firewall sku ‘AZFW_Hub’ is leveraged to secure a virtual hub.
param location string
@allowed([
'AZFW_Hub'
])
param azfwskuname string
@allowed([
'Basic'
'Premium'
'Standard'
])
param azfwskutier string
param azfwname string
param vhubname string
param azfwpoliyname string
resource azurefirewall 'Microsoft.Network/azureFirewalls@2021-08-01' = {
name: azfwname
location: location
properties:{
sku:{
name: azfwskuname
tier: azfwskutier
}
hubIPAddresses:{
publicIPs:{
count: 1
}
}
virtualHub: {
id: resourceId('Microsoft.Network/virtualHubs',vhubname)
}
firewallPolicy:{
id: resourceId('Microsoft.Network/firewallPolicies', azfwpoliyname)
}
}
}
output ipaddress string = azurefirewall.properties.hubIPAddresses.privateIPAddress
output firewallPIP string = azurefirewall.properties.hubIPAddresses.publicIPs.addresses[0].address
output firewallID string = azurefirewall.id
param azfwpolname string
param location string
param destinationAddresses array
param sourceAddresses array
@allowed([
'Alert'
'Deny'
'Off'
])
param fwpolthreatintelmode string
//param azfwrcgrpname string
param azfwrcgrppriority int
//param azfwrctype string
//param azfwrulename string
//param azfwruleType string
//param azfwsource string
resource azfwpolicy 'Microsoft.Network/firewallPolicies@2021-08-01' = {
name: azfwpolname
location: location
tags:{
}
properties:{
threatIntelMode: fwpolthreatintelmode
}
resource azfwrcs 'ruleCollectionGroups' = {
name: 'DefaultNetworkRuleCollectionGroup'
dependsOn: [
]
properties: {
priority: azfwrcgrppriority
ruleCollections: [
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
action:{
type: 'Allow'
}
name: '${azfwpolname}Internet'
priority:500
rules:[
{
ruleType: 'ApplicationRule'
name: 'InetOutBound'
sourceAddresses: [
'*'
]
protocols: [
{
port: 80
protocolType: 'Http'
}
{
protocolType: 'Https'
port: 443
}
]
targetFqdns: [
'*'
]
}
]
}
{
ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
action: {
type: 'Allow'
}
name: 'RDP'
priority:100
rules: [
{
ruleType: 'NetworkRule'
description: 'RDP Access to Remote PCs'
sourceAddresses: sourceAddresses
destinationAddresses: destinationAddresses
destinationPorts: [
'3389'
]
ipProtocols: [
'TCP'
]
}
{
ruleType: 'NetworkRule'
description:'Pinging the PCs'
sourceAddresses: sourceAddresses
destinationAddresses: destinationAddresses
destinationPorts: [
'*'
]
ipProtocols: [
'ICMP'
]
name:'Pings'
}
]
}
]
}
}
}
This module deploys a bastion host for remote management. A bastion host must be deployed to every vnet where the services are required.
// Parameters
param bastionHostName string = 'Bastionhost'
param ipConfname string = 'bastionIpConf'
param location string
param subnetid string
param domainNameLabel string
param publicIPAddressName string
// Resources
resource StandardStaticPip 'Microsoft.Network/publicIPAddresses@2021-02-01' = {
name: '${publicIPAddressName}-Std'
location: location
sku:{
name: 'Standard'
}
properties: {
publicIPAllocationMethod: 'Static'
dnsSettings: {
domainNameLabel: domainNameLabel
}
}
}
resource bastionHostres 'Microsoft.Network/bastionHosts@2020-07-01' = {
name: bastionHostName
location: location
properties:{
ipConfigurations:[
{
name: ipConfname
properties: {
subnet: {
id: subnetid
}
publicIPAddress: {
id: StandardStaticPip.id
}
}
}
]
}
}
output IPaddress string = StandardStaticPip.properties.ipAddress
Admittedly, I went overboard on the imageOSSku parameter. Outside of that it provisions a virtual machine. In its current state, it will only provision ubuntu and windows servers.
//Some Helpful Commands at the bottom
@description(' Name of the vnet the vmnic will be hosted')
param vNetName string
@description(' Name of the subnet the vmnic will be hosted')
param subnetName string
@description(' Name of the resourcegroup hosting the vnet')
param vnetrgname string
param vmName string
param location string
//virtual Machine Variables
@description('To obtain vmsize run the following command: Get-AzVMSize -Location <replace with desired location>')
@allowed([
'Standard_A3'
'Standard_F4'
'Standard_B2ms'
])
param vmSize string
@allowed([
'MicrosoftWindowsServer'
'Canonical'
])
param imagePublisher string
@allowed([
'WindowsServer'
'UbuntuServer'
])
param imageOffer string
@description('The Windows version for the VM. This will pick a fully patched image of this given Windows version.')
@allowed([
'2008-R2-SP1'
'2008-R2-SP1-smalldisk'
'2012-Datacenter'
'2012-datacenter-gensecond'
'2012-Datacenter-smalldisk'
'2012-datacenter-smalldisk-g2'
'2012-Datacenter-zhcn'
'2012-datacenter-zhcn-g2'
'2012-R2-Datacenter'
'2012-r2-datacenter-gensecond'
'2012-R2-Datacenter-smalldisk'
'2012-r2-datacenter-smalldisk-g2'
'2012-R2-Datacenter-zhcn'
'2012-r2-datacenter-zhcn-g2'
'2016-Datacenter'
'2016-datacenter-gensecond'
'2016-datacenter-gs'
'2016-Datacenter-Server-Core'
'2016-datacenter-server-core-g2'
'2016-Datacenter-Server-Core-smalldisk'
'2016-datacenter-server-core-smalldisk-g2'
'2016-Datacenter-smalldisk'
'2016-datacenter-smalldisk-g2'
'2016-Datacenter-with-Containers'
'2016-datacenter-with-containers-g2'
'2016-datacenter-with-containers-gs'
'2016-Datacenter-zhcn'
'2016-datacenter-zhcn-g2'
'2019-Datacenter'
'2019-Datacenter-Core'
'2019-datacenter-core-g2'
'2019-Datacenter-Core-smalldisk'
'2019-datacenter-core-smalldisk-g2'
'2019-Datacenter-Core-with-Containers'
'2019-datacenter-core-with-containers-g2'
'2019-Datacenter-Core-with-Containers-smalldisk'
'2019-datacenter-core-with-containers-smalldisk-g2'
'2019-datacenter-gensecond'
'2019-datacenter-gs'
'2019-Datacenter-smalldisk'
'2019-datacenter-smalldisk-g2'
'2019-Datacenter-with-Containers'
'2019-datacenter-with-containers-g2'
'2019-datacenter-with-containers-gs'
'2019-Datacenter-with-Containers-smalldisk'
'2019-datacenter-with-containers-smalldisk-g2'
'2019-Datacenter-zhcn'
'2019-datacenter-zhcn-g2'
'2022-datacenter'
'2022-datacenter-azure-edition'
'2022-datacenter-azure-edition-core'
'2022-datacenter-azure-edition-core-smalldisk'
'2022-datacenter-azure-edition-smalldisk'
'2022-datacenter-core'
'2022-datacenter-core-g2'
'2022-datacenter-core-smalldisk'
'2022-datacenter-core-smalldisk-g2'
'2022-datacenter-g2'
'2022-datacenter-smalldisk'
'2022-datacenter-smalldisk-g2'
'UbuntuServer'
])
param imageOSsku string
param imageVersion string
@secure()
param adminPassword string
param adminUsername string = '${vmName}-Admin'
// Storage Account Variables
@allowed([
'Standard_LRS'
'Premium_ZRS'
'Standard_RAGRS'
'Standard_RAGZRS'
'Standard_GRS'
'Standard_GZRS'
'Premium_LRS'
'Standard_ZRS'
])
param storageskuname string
@maxLength(8)
param storageAccountPrefix string
@allowed([
'StorageV2'
'FileStorage'
'BlockBlobStorage'
])
param sakind string
var saname = '${toLower(storageAccountPrefix)}${uniqueString(resourceGroup().id)}'
///////////////////////////
// RESOURCES AND MODULES//
/////////////////////////
resource vmStorage 'Microsoft.Storage/storageAccounts@2021-09-01' = {
name: saname
location: location
sku: {
name: storageskuname
}
kind: sakind
}
resource vmnic 'Microsoft.Network/networkInterfaces@2021-08-01' = {
name: '${vmName}-NIC'
location: location
dependsOn: [
]
properties:{
ipConfigurations:[
{
name: '${vmName}-IPconfig'
properties: {
subnet:{
id: resourceId(vnetrgname,'Microsoft.Network/virtualNetworks/subnets',vNetName, subnetName)
}
}
}
]
}
}
resource vm 'Microsoft.Compute/virtualMachines@2021-11-01' = {
name: vmName
location: location
dependsOn:[
]
properties:{
hardwareProfile:{
vmSize: vmSize
}
osProfile:{
adminPassword: adminPassword
adminUsername: adminUsername
computerName: vmName
}
storageProfile:{
imageReference:{
publisher: imagePublisher
offer: imageOffer
sku: imageOSsku
version: imageVersion
}
osDisk: {
createOption: 'FromImage'
managedDisk: {
storageAccountType: 'StandardSSD_LRS'
}
}
dataDisks: [
{
diskSizeGB: 1023
lun: 0
createOption: 'Empty'
}
]
}
networkProfile:{
networkInterfaces:[
{
id: resourceId('Microsoft.Network/networkInterfaces',vmnic.name)
}
]
}
diagnosticsProfile:{
bootDiagnostics:{
enabled: true
storageUri: vmStorage.properties.primaryEndpoints.blob
}
}
}
}
output ipaddress string = vmnic.properties.ipConfigurations[0].properties.privateIPAddress
output adminUserName string = adminUsername
targetScope = 'subscription'
param resourceGroupName string
param location string
resource ResourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = {
name: resourceGroupName
location: location
}
This is a basic module. The destination is hard-coded to the default route.
param routetTblname string
param vhubname string
param firewallID string
@description('Next hop resource ID (Azure Firewall or VNet Connection')
param destinations array
@allowed([
'CIDR'
'ResourceId'
'Service'
])
param destinationtype string
@allowed([
'CIDR'
'ResourceId'
'Service'
])
param nextHoptype string
resource vhub 'Microsoft.Network/virtualHubs@2021-08-01' existing = {
name: vhubname
}
resource vWANhubRouteTable 'Microsoft.Network/virtualHubs/hubrouteTables@2021-08-01' = {
name: routetTblname
parent: vhub
properties: {
labels: [
'default'
]
routes:[
{
name: 'InternettoFirewall'
nextHop: firewallID
nextHopType: nextHoptype
destinationType: destinationtype
destinations: [
'0.0.0.0/0'
]
}
{
name: 'InternalTraffic'
nextHop: firewallID
nextHopType: nextHoptype
destinationType: destinationtype
destinations: destinations
}
]
}
}
param location string
param vWanname string
param vhubname string
param allowBranchToBranchTraffic bool
param vhubprefix string
resource vhub 'Microsoft.Network/virtualHubs@2021-08-01' = {
name: vhubname
location:location
properties: {
addressPrefix: vhubprefix
allowBranchToBranchTraffic: allowBranchToBranchTraffic
virtualWan:{
id: resourceId('Microsoft.Network/virtualWans',vWanname)
}
}
}
output vhubID string = vhub.id
output addressPrefix string = vhub.properties.addressPrefix
param location string
param vWanname string
param vhubname string
param allowBranchToBranchTraffic bool
param vhubprefix string
resource vhub 'Microsoft.Network/virtualHubs@2021-08-01' = {
name: vhubname
location:location
properties: {
addressPrefix: vhubprefix
allowBranchToBranchTraffic: allowBranchToBranchTraffic
virtualWan:{
id: resourceId('Microsoft.Network/virtualWans',vWanname)
}
}
}
output vhubID string = vhub.id
output addressPrefix string = vhub.properties.addressPrefix
The virtual network module is fairly vanilla and easy to interpret. The code I’ve designed only provisions a single prefix per virtual network.
targetScope = 'resourceGroup'
param location string
param vnetName string
param vnetAddress string
//subnet variables
resource vnet 'Microsoft.Network/virtualNetworks@2021-08-01' = {
name: vnetName
location: location
properties:{
addressSpace: {
addressPrefixes: [
vnetAddress
]
}
}
}
There’s nothing tricky about the virtual WAN module either. The properties in the params are all set to true in the main.bicep file.
param location string
param vWanname string
param allowBranchToBranchTraffic bool
param allowVnetToVnetTraffic bool
param disableVpnEncryption bool
resource vWan 'Microsoft.Network/virtualWans@2021-08-01' = {
name: vWanname
location: location
properties: {
allowBranchToBranchTraffic: allowBranchToBranchTraffic
allowVnetToVnetTraffic: allowVnetToVnetTraffic
disableVpnEncryption: disableVpnEncryption
}
}
Calls all previous modules to build the environment.
targetScope = 'subscription'
param stringData string
var base64String = base64(stringData)
// PARAMETERS
param location string
param Spoke01Name string
param Spoke02Name string
param Spoke03Name string
param NetworkRGName string
param ComputeRGName string
param firewallName string
param Spoke01Address string
param Spoke02Address string
param Spoke03Address string
param vhubAddress string
param Subnet01 string
param Subnet02 string
param BastionSN string
param vHubName string
param vWANname string
param destinationType string
param nextHopType string
param routetTblname string
param vhubConnectionName01 string
param vhubConnectionName02 string
param vhubConnectionName03 string
// Compute Parameters
param imageOffer string
param imageOSsku string
param imagePublisher string
param imageVersion string
param sakind string
param storageAccountPrefix string
param storageskuname string
param vmName string
param vmSize string
@secure()
param adminPassword string
// BastionHost Name
param bastionHostName string
param publicIPAddressName string
// Firewall Parameters
param firewallPolicyName string
param azfwskuname string
param azfwskutier string
// vHubConnections Parameters
param allowHubToRemoteVnetTransit bool = true
param allowRemoteVnetToUseHubVnetGateways bool = true
param enableInternetSecurity bool = true
// Virtual WAN Parameters
param allowBranchToBranchTraffic bool = true
param allowVnetToVnetTraffic bool = true
param disableVpnEncryption bool = false
// VARIABLES
// Vnet Addressing
var Spoke01CIDR = '${Spoke01Address}0.0/16'
var Spoke02CIDR = '${Spoke02Address}0.0/16'
var Spoke03CIDR = '${Spoke03Address}0.0/16'
var vhubCIDR = '${vhubAddress}0.0/16'
// Spoke01 Subnets
var S01Subnet1Prefix = '${Spoke01Address}${Subnet01}'
var S01Subnet2Prefix = '${Spoke01Address}${Subnet02}'
var S01BastionPrefix = '${Spoke01Address}${BastionSN}'
// Spoke02 Subnets
var S02Subnet1Prefix = '${Spoke02Address}${Subnet01}'
var S02Subnet2Prefix = '${Spoke02Address}${Subnet02}'
var S02BastionPrefix = '${Spoke02Address}${BastionSN}'
// Spoke03 Subnets
var S03Subnet1Prefix = '${Spoke03Address}${Subnet01}'
var S03Subnet2Prefix = '${Spoke03Address}${Subnet02}'
var S03BastionPrefix = '${Spoke03Address}${BastionSN}'
// Default Route Table
var destinations = [
S01Subnet1Prefix
S01Subnet2Prefix
S02Subnet1Prefix
S02Subnet2Prefix
S03Subnet1Prefix
S03Subnet2Prefix
]
// Firewall Policies
@allowed([
'Alert'
'Deny'
'Off'
])
param fwpolthreatintelmode string
param azfwrcgrppriority int
var sourceAddresses = [
Spoke01CIDR
Spoke02CIDR
Spoke03CIDR
]
var destinationAddresses = [
Spoke01CIDR
Spoke02CIDR
Spoke03CIDR
]
//Resource Groups
module computeRG 'modules/ResourceGroup.bicep' = {
name: ComputeRGName
scope: subscription()
params: {
location: location
resourceGroupName: ComputeRGName
}
}
module NetworkRG 'modules/ResourceGroup.bicep' = {
name: NetworkRGName
scope: subscription()
params: {
location: location
resourceGroupName: NetworkRGName
}
}
// Spoke01 Virtual Network
module Spoke01 'modules/VirtualNetwork.bicep' = {
name: Spoke01Name
scope: resourceGroup(NetworkRGName)
params: {
location: location
vnetAddress: Spoke01CIDR
vnetName: Spoke01Name
}
dependsOn: [
NetworkRG
]
}
module Spoke01S01 'modules/subnet.bicep' = {
name: '${Spoke01Name}-S01'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S01Subnet1Prefix
subnetname: '${Spoke01Name}/${Spoke01Name}-S01'
}
dependsOn: [
Spoke01
]
}
module Spoke01S02 'modules/subnet.bicep' = {
name: '${Spoke01Name}-S02'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S01Subnet2Prefix
subnetname: '${Spoke01Name}/${Spoke01Name}-S02'
}
dependsOn: [
Spoke01
Spoke01S01
]
}
module spoke01Bastion 'modules/subnet-nsg.bicep' = {
name: '${Spoke01Name}-BastionSN'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S01BastionPrefix
subnetname: '${Spoke01Name}/AzureBastionSubnet'
nsgid: bastionnsg.outputs.bastionHostNSGId
}
dependsOn: [
Spoke01S02
bastionnsg
]
}
// Spoke 2 Virtual Network
module Spoke02 'modules/VirtualNetwork.bicep' = {
name: Spoke02Name
scope: resourceGroup(NetworkRGName)
params: {
location: location
vnetAddress: Spoke02CIDR
vnetName: Spoke02Name
}
dependsOn: [
NetworkRG
]
}
module Spoke02S01 'modules/subnet.bicep' = {
name: '${Spoke02Name}-S01'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S02Subnet1Prefix
subnetname: '${Spoke02Name}/${Spoke02Name}-S01'
}
dependsOn: [
Spoke02
]
}
module Spoke02S02 'modules/subnet.bicep' = {
name: '${Spoke02Name}-S02'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S02Subnet2Prefix
subnetname: '${Spoke02Name}/${Spoke02Name}-S02'
}
dependsOn: [
Spoke02
Spoke02S01
]
}
module spoke02Bastion 'modules/subnet-nsg.bicep' = {
name: '${Spoke02Name}-BastionSN'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S02BastionPrefix
subnetname: '${Spoke02Name}/AzureBastionSubnet'
nsgid: bastionnsg.outputs.bastionHostNSGId
}
dependsOn: [
Spoke02S02
bastionnsg
]
}
// Spoke 3 Virtual Network
module Spoke03 'modules/VirtualNetwork.bicep' = {
name: Spoke03Name
scope: resourceGroup(NetworkRGName)
params: {
location: location
vnetAddress: Spoke03CIDR
vnetName: Spoke03Name
}
dependsOn: [
NetworkRG
]
}
module Spoke03S01 'modules/subnet.bicep' = {
name: '${Spoke03Name}-S01'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S03Subnet1Prefix
subnetname: '${Spoke03Name}/${Spoke03Name}-S01'
}
dependsOn: [
Spoke03
]
}
module Spoke03S02 'modules/subnet.bicep' = {
name: '${Spoke03Name}-S02'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S03Subnet2Prefix
subnetname: '${Spoke03Name}/${Spoke03Name}-S02'
}
dependsOn: [
Spoke03
Spoke03S01
]
}
module bastionnsg 'modules/bastionnsg.bicep' = {
scope: resourceGroup(NetworkRGName)
name: '${Spoke03Name}-BastionNSG'
params: {
bastionHostName: bastionHostName
location: location
}
dependsOn: [
NetworkRG
]
}
module spoke03Bastion 'modules/subnet-nsg.bicep' = {
name: '${Spoke03Name}-BastionSN'
scope: resourceGroup(NetworkRGName)
params: {
addressprefix: S03BastionPrefix
subnetname: '${Spoke03Name}/AzureBastionSubnet'
nsgid: bastionnsg.outputs.bastionHostNSGId
}
dependsOn: [
Spoke03S02
bastionnsg
]
}
module vWAN 'modules/vWAN.bicep' = {
scope: resourceGroup(NetworkRGName)
name: vWANname
params: {
allowBranchToBranchTraffic: allowBranchToBranchTraffic
allowVnetToVnetTraffic: allowVnetToVnetTraffic
disableVpnEncryption: disableVpnEncryption
location: location
vWanname: vWANname
}
dependsOn:[
Spoke02
Spoke01
Spoke03
]
}
module vhub 'modules/virtualhub.bicep' = {
scope: resourceGroup(NetworkRGName)
name: vHubName
params: {
allowBranchToBranchTraffic: allowBranchToBranchTraffic
location: location
vhubname: vHubName
vhubprefix: vhubCIDR
vWanname: vWAN.name
}
dependsOn:[
vWAN
]
}
module firewall 'modules/AzureFirewall.bicep' = {
scope: resourceGroup(NetworkRGName)
name: firewallName
params: {
azfwname: firewallName
azfwpoliyname: FWPolicy01.name
azfwskuname: azfwskuname
azfwskutier: azfwskutier
location: location
vhubname: vhub.name
}
dependsOn: [
vhub
FWPolicy01
]
}
module vWanRouteTable 'modules/routetable.bicep' = {
scope: resourceGroup(NetworkRGName)
name: routetTblname
params: {
firewallID: firewall.outputs.firewallID
destinations: destinations
destinationtype: destinationType
nextHoptype: nextHopType
vhubname: vhub.name
routetTblname: routetTblname
}
dependsOn: [
vhub
firewall
]
}
module vhubConnection01 'modules/vhubnetworkconnection.bicep' = {
scope: resourceGroup(NetworkRGName)
name: vhubConnectionName01
params: {
allowHubToRemoteVnetTransit: allowHubToRemoteVnetTransit
allowRemoteVnetToUseHubVnetGateways: allowRemoteVnetToUseHubVnetGateways
enableInternetSecurity: enableInternetSecurity
labels: Spoke01.name
RouteTableName: vWanRouteTable.name
SpokeName: Spoke01.name
vhubconnectionname: vhubConnectionName01
vhubname: vhub.name
}
dependsOn: [
Spoke01
vhub
vWanRouteTable
]
}
module vhubConnection03 'modules/vhubnetworkconnection.bicep' = {
scope: resourceGroup(NetworkRGName)
name: vhubConnectionName03
params: {
allowHubToRemoteVnetTransit: allowHubToRemoteVnetTransit
allowRemoteVnetToUseHubVnetGateways: allowRemoteVnetToUseHubVnetGateways
enableInternetSecurity: enableInternetSecurity
labels: Spoke03.name
RouteTableName: vWanRouteTable.name
SpokeName: Spoke03.name
vhubconnectionname: vhubConnectionName03
vhubname: vhub.name
}
dependsOn: [
vhubConnection02
]
}
module vhubConnection02 'modules/vhubnetworkconnection.bicep' = {
scope: resourceGroup(NetworkRGName)
name: vhubConnectionName02
params: {
allowHubToRemoteVnetTransit: allowHubToRemoteVnetTransit
allowRemoteVnetToUseHubVnetGateways: allowRemoteVnetToUseHubVnetGateways
enableInternetSecurity: enableInternetSecurity
labels: Spoke02.name
RouteTableName: vWanRouteTable.name
SpokeName: Spoke02.name
vhubconnectionname: vhubConnectionName02
vhubname: vhub.name
}
dependsOn: [
vhubConnection01
]
}
module FWPolicy01 'modules/AzureFirewallPolicy.bicep' = {
scope: resourceGroup(NetworkRGName)
name: firewallPolicyName
params: {
azfwpolname: firewallPolicyName
azfwrcgrppriority: azfwrcgrppriority
fwpolthreatintelmode: fwpolthreatintelmode
location: location
destinationAddresses: destinationAddresses
sourceAddresses: sourceAddresses
}
dependsOn: [
NetworkRG
Desktop3
]
}
module Desktop1 'modules/Compute.bicep' = {
scope: resourceGroup(ComputeRGName)
name: '${vmName}S01S01'
params: {
adminPassword: adminPassword
location: location
imageOffer: imageOffer
imageOSsku: imageOSsku
imagePublisher: imagePublisher
imageVersion: imageVersion
sakind: sakind
storageAccountPrefix: storageAccountPrefix
storageskuname: storageskuname
subnetName: Spoke01S01.name
vmName: '${vmName}S01S01'
vmSize: vmSize
vNetName: Spoke01.name
vnetrgname: NetworkRG.name
}
dependsOn: [
computeRG
Spoke01S01
Spoke01
]
}
module Desktop2 'modules/Compute.bicep' = {
scope: resourceGroup(ComputeRGName)
name: '${vmName}S02S02'
params: {
adminPassword: adminPassword
location: location
imageOffer: imageOffer
imageOSsku: imageOSsku
imagePublisher: imagePublisher
imageVersion: imageVersion
sakind: sakind
storageAccountPrefix: storageAccountPrefix
storageskuname: storageskuname
subnetName: Spoke02S02.name
vmName: '${vmName}S02S02'
vmSize: vmSize
vNetName: Spoke02.name
vnetrgname: NetworkRG.name
}
dependsOn: [
computeRG
Spoke02S02
Spoke02
Desktop1
]
}
module Desktop3 'modules/Compute.bicep' = {
scope: resourceGroup(ComputeRGName)
name: '${vmName}S03S01'
params: {
adminPassword: adminPassword
location: location
imageOffer: imageOffer
imageOSsku: imageOSsku
imagePublisher: imagePublisher
imageVersion: imageVersion
sakind: sakind
storageAccountPrefix: storageAccountPrefix
storageskuname: storageskuname
subnetName: Spoke03S01.name
vmName: '${vmName}S03S01'
vmSize: vmSize
vNetName: Spoke03.name
vnetrgname: NetworkRG.name
}
dependsOn: [
computeRG
Spoke03S01
Spoke03
Desktop2
]
}
module spoke03BastionHost 'modules/bastionhost.bicep' = {
scope: resourceGroup(ComputeRGName)
name: '${bastionHostName}03'
params: {
domainNameLabel: toLower('${bastionHostName}${base64String}03')
publicIPAddressName: '${publicIPAddressName}bh03'
subnetid: spoke03Bastion.outputs.subnetid
location: location
bastionHostName: '${bastionHostName}03'
ipConfname: '${publicIPAddressName}bh03'
}
dependsOn: [
spoke03Bastion
spoke02BastionHost
]
}
module spoke02BastionHost 'modules/bastionhost.bicep' = {
scope: resourceGroup(ComputeRGName)
name: '${bastionHostName}02'
params: {
domainNameLabel: toLower('${bastionHostName}${base64String}02')
publicIPAddressName: '${publicIPAddressName}bh02'
subnetid: spoke02Bastion.outputs.subnetid
location: location
bastionHostName: '${bastionHostName}02'
ipConfname: '${publicIPAddressName}bh02'
}
dependsOn: [
spoke02Bastion
spoke01BastionHost
]
}
module spoke01BastionHost 'modules/bastionhost.bicep' = {
scope: resourceGroup(ComputeRGName)
name: '${bastionHostName}01'
params: {
domainNameLabel: toLower('${bastionHostName}${base64String}01')
publicIPAddressName: '${publicIPAddressName}bh01'
subnetid: spoke01Bastion.outputs.subnetid
location: location
bastionHostName: '${bastionHostName}01'
ipConfname: '${publicIPAddressName}bh01'
}
dependsOn: [
spoke01Bastion
]
}
output firewallpublicIP string = firewall.outputs.ipaddress
output desktop3UserName string = Desktop3.outputs.adminUserName
output desktop2UserName string = Desktop2.outputs.adminUserName
output desktop1UserName string = Desktop1.outputs.adminUserName