Skip to content

Commit 296a6eb

Browse files
committed
network_subnet_design completed and tested
1 parent 28819ff commit 296a6eb

4 files changed

Lines changed: 188 additions & 154 deletions

File tree

infra/main.bicepparam

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,13 @@ using './main.bicep'
22

33
param solutionName = readEnvironmentVariable('AZURE_ENV_NAME')
44
param location = readEnvironmentVariable('AZURE_LOCATION')
5+
6+
//*******************************************************************************
7+
// Uncomment the following lines to enable the WAF-aligned configuration
8+
//*******************************************************************************
9+
10+
param enableMonitoring = true
11+
param enableScaling = true
12+
param enableRedundancy = true
13+
//param secondaryLocation = 'uksouth' // TODO - test this
14+
param enablePrivateNetworking = true

infra/modules/network/virtualNetwork.bicep

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ type subnetType = {
118118
@description('Required. The Name of the subnet resource.')
119119
name: string
120120

121-
@description('Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty.')
122-
addressPrefix: string?
121+
// @description('Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty.')
122+
// addressPrefix: string?
123123

124-
@description('Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty.')
125-
addressPrefixes: string[]?
124+
@description('Required. Prefixes for the subnet.') // Required to ensure at least one prefix is provided
125+
addressPrefixes: string[]
126126

127127
@description('Optional. The delegation to enable on the subnet.')
128128
delegation: string?
Lines changed: 105 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,99 @@
11
// /******************************************************************************************************************/
2-
// This is an example test program to create private networking resources independently with sample inputs
3-
//
2+
// This is an example test program to create private networking resources independently with sample network design.
3+
// It is an illustration of how to use the main.bicep in the infra/modules/network folder, with your own parameters.
4+
// You can independently deploy this module to create a network with subnets, NSGs, Azure Bastion Host, and Jumpbox VM.
5+
// Test them with this test program. Then integrate your design into the modules/network.bicep which is intended for
6+
// a specific network design.
7+
//
8+
// All things in infra/modules/network are designed to be reusable and composable without the need to modify
9+
// any code in the network folder.
10+
//
411
// Please review below modules to understand how things are wired together:
5-
// infra/main.bicep
6-
// infra/modules/network.bicep
7-
// infra/moddules/network/main.bicep
12+
// infra/main.bicep
13+
// infra/modules/network.bicep
14+
// infra/moddules/network/main.bicep
815
//
916
// /******************************************************************************************************************/
1017

1118
@minLength(6)
1219
@maxLength(25)
13-
@description('Default name used for all resources.')
14-
param resourcesName string = 'testNetwork'
20+
@description('Name used for naming all network resources.')
21+
param resourcesName string = 'nettest'
1522

1623
@minLength(3)
1724
@description('Azure region for all services.')
18-
param location string = 'eastus'
25+
param location string = resourceGroup().location
26+
27+
@description('Optional. Enable/Disable usage telemetry for module.')
28+
param enableTelemetry bool = true
1929

2030
@description('Optional. Tags to be applied to the resources.')
2131
param tags object = {}
2232

23-
var vnetName = 'vnet-${resourcesName}'
24-
@description('Networking address prefix for the VNET only')
25-
param addressPrefixes array = ['10.0.0.0/20'] // 4096 addresses (enough for 8 /23 subnets or 16 /24 subnets)
33+
import { bastionHostConfigurationType } from '../modules/network/bastionHost.bicep'
34+
@description('Optional. Configuration for the Azure Bastion Host. Leave null to omit Bastion creation.')
35+
param bastionConfiguration bastionHostConfigurationType = {
36+
name: 'bastion-${resourcesName}'
37+
subnetAddressPrefixes: ['10.0.10.0/23'] // /23 (10.0.10.0 - 10.0.11.255), 512 addresses
38+
}
2639

27-
param enableBastionHost bool = true
28-
var bastionHostName = 'bastionHost-${resourcesName}'
40+
import { jumpBoxConfigurationType } from '../modules/network/jumpbox.bicep'
41+
@description('Optional. Configuration for the Jumpbox VM. Leave null to omit Jumpbox creation.')
42+
param jumpboxConfiguration jumpBoxConfigurationType = {
43+
name: 'vm-jumpbox-${resourcesName}'
44+
size: 'Standard_D2s_v3' // Default size, can be overridden
45+
username: 'JumpboxAdminUser'
46+
password: 'JumpboxAdminP@ssw0rd1234!'
47+
subnet: {
48+
name: 'jumpbox-subnet'
49+
addressPrefixes: ['10.0.12.0/23'] // /23 (10.0.12.0 - 10.0.13.255), 512 addresses
50+
networkSecurityGroup: {
51+
name: 'jumpbox-nsg'
52+
securityRules: [
53+
{
54+
name: 'AllowJumpboxInbound'
55+
properties: {
56+
access: 'Allow'
57+
direction: 'Inbound'
58+
priority: 100
59+
protocol: 'Tcp'
60+
sourcePortRange: '*'
61+
destinationPortRange: '22'
62+
sourceAddressPrefixes: [
63+
'10.0.10.0/23' // Azure Bastion subnet as an example here. You can adjust this as needed by adding more
64+
]
65+
destinationAddressPrefixes: ['10.0.12.0/23']
66+
}
67+
}
68+
]
69+
}
70+
}
71+
}
2972

30-
param jumpboxVM bool = true
31-
param jumpboxAdminUser string = 'JumpboxAdminUser'
32-
@secure()
33-
param jumpboxAdminPassword string = 'JumpboxAdminP@ssw0rd1234!'
34-
param jumpboxVmSize string = 'Standard_D2s_v3'
35-
var jumpboxVmName = 'jumpboxVM-${resourcesName}'
73+
// ====================================================================================================================
74+
// Below paremeters define default the VNET and subnets. You can customize them as needed.
75+
// ====================================================================================================================
76+
@description('Networking address prefix for the VNET.')
77+
param addressPrefixes array = ['10.0.0.0/20'] // 4096 addresses (enough for 8 /23 subnets or 16 /24 subnets)
3678

79+
import { subnetType } from '../modules/network/virtualNetwork.bicep'
3780
@description('Array of subnets to be created within the VNET.')
38-
param subnets array = [
39-
// Only one delegation per subnet is supported by the AVM module as of June 2025.
40-
// For subnets that do not require delegation, leave the array empty.
81+
param subnets subnetType[] = [
4182
{
42-
name: 'web'
83+
name: 'peps'
4384
addressPrefixes: ['10.0.0.0/23'] // /23 (10.0.0.0 - 10.0.1.255), 512 addresses
85+
privateEndpointNetworkPolicies: 'Disabled'
86+
privateLinkServiceNetworkPolicies: 'Disabled'
87+
networkSecurityGroup: {
88+
name: 'peps-nsg'
89+
securityRules: []
90+
}
91+
}
92+
{
93+
name: 'web'
94+
addressPrefixes: ['10.0.2.0/23'] // /23 (10.0.2.0 - 10.0.3.255), 512 addresses
95+
privateEndpointNetworkPolicies: 'Disabled'
96+
privateLinkServiceNetworkPolicies: 'Disabled'
4497
networkSecurityGroup: {
4598
name: 'web-nsg'
4699
securityRules: [
@@ -54,7 +107,7 @@ param subnets array = [
54107
sourcePortRange: '*'
55108
destinationPortRange: '443'
56109
sourceAddressPrefixes: ['0.0.0.0/0']
57-
destinationAddressPrefixes: ['10.0.0.0/23']
110+
destinationAddressPrefixes: ['10.0.2.0/23']
58111
}
59112
}
60113
]
@@ -68,7 +121,9 @@ param subnets array = [
68121
}
69122
{
70123
name: 'app'
71-
addressPrefixes: ['10.0.2.0/23'] // /23 (10.0.2.0 - 10.0.3.255), 512 addresses
124+
addressPrefixes: ['10.0.4.0/23'] // /23 (10.0.4.0 - 10.0.5.255), 512 addresses
125+
privateEndpointNetworkPolicies: 'Disabled'
126+
privateLinkServiceNetworkPolicies: 'Disabled'
72127
networkSecurityGroup: {
73128
name: 'app-nsg'
74129
securityRules: [
@@ -81,8 +136,8 @@ param subnets array = [
81136
protocol: 'Tcp'
82137
sourcePortRange: '*'
83138
destinationPortRange: '*'
84-
sourceAddressPrefixes: ['10.0.0.0/23'] // web subnet
85-
destinationAddressPrefixes: ['10.0.2.0/23']
139+
sourceAddressPrefixes: ['10.0.2.0/23'] // web subnet
140+
destinationAddressPrefixes: ['10.0.4.0/23']
86141
}
87142
}
88143
]
@@ -96,7 +151,9 @@ param subnets array = [
96151
}
97152
{
98153
name: 'ai'
99-
addressPrefixes: ['10.0.4.0/23'] // /23 (10.0.4.0 - 10.0.5.255), 512 addresses
154+
addressPrefixes: ['10.0.6.0/23'] // /23 (10.0.6.0 - 10.0.7.255), 512 addresses
155+
privateEndpointNetworkPolicies: 'Disabled'
156+
privateLinkServiceNetworkPolicies: 'Disabled'
100157
networkSecurityGroup: {
101158
name: 'ai-nsg'
102159
securityRules: [
@@ -110,10 +167,10 @@ param subnets array = [
110167
sourcePortRange: '*'
111168
destinationPortRange: '*'
112169
sourceAddressPrefixes: [
113-
'10.0.0.0/23' // web subnet
114-
'10.0.2.0/23' // app subnet
170+
'10.0.2.0/23' // web subnet
171+
'10.0.4.0/23' // app subnet
115172
]
116-
destinationAddressPrefixes: ['10.0.4.0/23']
173+
destinationAddressPrefixes: ['10.0.6.0/23']
117174
}
118175
}
119176
]
@@ -122,7 +179,9 @@ param subnets array = [
122179
}
123180
{
124181
name: 'data'
125-
addressPrefixes: ['10.0.6.0/23'] // /23 (10.0.6.0 - 10.0.7.255)
182+
addressPrefixes: ['10.0.8.0/23'] // /23 (10.0.8.0 - 10.0.9.255), 512 addresses
183+
privateEndpointNetworkPolicies: 'Disabled'
184+
privateLinkServiceNetworkPolicies: 'Disabled'
126185
networkSecurityGroup: {
127186
name: 'data-nsg'
128187
securityRules: [
@@ -136,36 +195,9 @@ param subnets array = [
136195
sourcePortRange: '*'
137196
destinationPortRange: '*'
138197
sourceAddressPrefixes: [
139-
'10.0.0.0/23' // web subnet
140-
'10.0.2.0/23' // app subnet
141-
'10.0.4.0/23' // ai subnet
142-
]
143-
destinationAddressPrefixes: ['10.0.6.0/23']
144-
}
145-
}
146-
]
147-
}
148-
delegations: [] // No delegation required for this subnet.
149-
}
150-
{
151-
name: 'services'
152-
addressPrefixes: ['10.0.8.0/23'] // /23 (10.0.8.0 - 10.0.9.255), 512 addresses
153-
networkSecurityGroup: {
154-
name: 'services-nsg'
155-
securityRules: [
156-
{
157-
name: 'AllowWebAppAiToServices'
158-
properties: {
159-
access: 'Allow'
160-
direction: 'Inbound'
161-
priority: 100
162-
protocol: 'Tcp'
163-
sourcePortRange: '*'
164-
destinationPortRange: '*'
165-
sourceAddressPrefixes: [
166-
'10.0.0.0/23' // web subnet
167-
'10.0.2.0/23' // app subnet
168-
'10.0.4.0/23' // ai subnet
198+
'10.0.2.0/23' // web subnet
199+
'10.0.4.0/23' // app subnet
200+
'10.0.6.0/23' // ai subnet
169201
]
170202
destinationAddressPrefixes: ['10.0.8.0/23']
171203
}
@@ -176,39 +208,6 @@ param subnets array = [
176208
}
177209
]
178210

179-
// jumpbox parameters
180-
param jumpboxSubnet object = {
181-
name: 'jumpbox'
182-
addressPrefixes: ['10.0.12.0/23'] // /23 (10.0.12.0 - 10.0.13.255), 512 addresses
183-
networkSecurityGroup: {
184-
name: 'jumpbox-nsg'
185-
securityRules: [
186-
{
187-
name: 'AllowJumpboxInbound'
188-
properties: {
189-
access: 'Allow'
190-
direction: 'Inbound'
191-
priority: 100
192-
protocol: 'Tcp'
193-
sourcePortRange: '*'
194-
destinationPortRange: '22'
195-
sourceAddressPrefixes: [
196-
'10.0.7.0/24' // Azure Bastion subnet as an example here. You can adjust this as needed by adding more
197-
]
198-
destinationAddressPrefixes: ['10.0.12.0/23']
199-
}
200-
}
201-
]
202-
}
203-
}
204-
205-
// Azure Bastion Host parameters
206-
param bastionSubnet object = {
207-
addressPrefixes: ['10.0.10.0/23'] // /23 (10.0.10.0 - 10.0.11.255), 512 addresses
208-
networkSecurityGroup: null // Azure Bastion subnet must NOT have custom NSG as it is managed by Azure
209-
}
210-
211-
212211
// /******************************************************************************************************************/
213212
// Create Log Analytics Workspace for monitoring and diagnostics
214213
// /******************************************************************************************************************/
@@ -224,65 +223,21 @@ module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0
224223
}
225224
}
226225

226+
// /******************************************************************************************************************/
227+
// Networking - NSGs, VNET and Subnets. Each subnet has its own NSG
227228
// /******************************************************************************************************************/
228-
// Networking - NSGs, VNET and Subnets. Each subnet has its own NSG
229-
// /******************************************************************************************************************/
230-
module virtualNetwork 'virtualNetwork.bicep' = {
231-
name: '${resourcesName}-virtualNetwork'
232-
params: {
233-
name: vnetName
234-
addressPrefixes: addressPrefixes
235-
subnets: subnets
236-
location: location
237-
tags: tags
238-
logAnalyticsWorkspaceId: logAnalyticsWorkspace.outputs.resourceId
239-
}
240-
}
241229

242-
// /******************************************************************************************************************/
243-
// // Create Azure Bastion Subnet and Azure Bastion Host
244-
// /******************************************************************************************************************/
245-
module bastionHost 'bastionHost.bicep' = if(enableBastionHost && !empty(bastionSubnet)) {
246-
name: '${resourcesName}-bastionHost'
230+
module network '../modules/network/main.bicep' = {
231+
name: take('network-${resourcesName}-create', 64)
247232
params: {
248-
subnet: bastionSubnet
233+
resourcesName: resourcesName
249234
location: location
250-
vnetName: virtualNetwork.outputs.name
251-
vnetId: virtualNetwork.outputs.resourceId
252-
name: bastionHostName
253-
logAnalyticsWorkspaceId: logAnalyticsWorkspace.outputs.resourceId
235+
logAnalyticsWorkSpaceResourceId: logAnalyticsWorkspace.outputs.resourceId
254236
tags: tags
237+
addressPrefixes: addressPrefixes
238+
subnets: subnets
239+
bastionConfiguration: bastionConfiguration
240+
jumpboxConfiguration: jumpboxConfiguration
241+
enableTelemetry: enableTelemetry
255242
}
256243
}
257-
258-
// /******************************************************************************************************************/
259-
// // create Jumpbox NSG and Jumpbox Subnet, then create Jumpbox VM
260-
// /******************************************************************************************************************/
261-
module jumpbox 'jumpbox.bicep' = if (jumpboxVM && !empty(jumpboxSubnet)) {
262-
name: '${resourcesName}-jumpbox'
263-
params: {
264-
vmName: jumpboxVmName
265-
location: location
266-
vnetName: virtualNetwork.outputs.name
267-
jumpboxVmSize: jumpboxVmSize
268-
jumpboxSubnet: jumpboxSubnet
269-
jumpboxAdminUser: jumpboxAdminUser
270-
jumpboxAdminPassword: jumpboxAdminPassword
271-
tags: tags
272-
logAnalyticsWorkspaceId: logAnalyticsWorkspace.outputs.resourceId
273-
}
274-
}
275-
276-
output vnetName string = virtualNetwork.outputs.name
277-
output vnetResourceId string = virtualNetwork.outputs.resourceId
278-
output subnets array = virtualNetwork.outputs.subnets // This one holds critical info for subnets, including NSGs
279-
280-
output bastionSubnetId string = bastionHost.outputs.subnetId
281-
output bastionSubnetName string = bastionHost.outputs.subnetName
282-
output bastionHostId string = bastionHost.outputs.resourceId
283-
output bastionHostName string = bastionHost.outputs.name
284-
285-
output jumpboxSubnetName string = jumpbox.outputs.subnetId
286-
output jumpboxSubnetId string = jumpbox.outputs.subnetId
287-
output jumpboxVmName string = jumpbox.outputs.vmName
288-
output jumpboxVmId string = jumpbox.outputs.vmId

0 commit comments

Comments
 (0)