diff --git a/infra/modules/network.bicep b/infra/modules/network.bicep index 138eb981..55a161fb 100644 --- a/infra/modules/network.bicep +++ b/infra/modules/network.bicep @@ -128,11 +128,75 @@ module network 'network/main.bicep' = { addressPrefixes: ['10.0.2.0/23'] // /23 (10.0.2.0 - 10.0.3.255), 512 addresses privateEndpointNetworkPolicies: 'Disabled' privateLinkServiceNetworkPolicies: 'Disabled' + networkSecurityGroup: { + name: 'nsg-peps' + securityRules: [] + } } ] bastionConfiguration: { name: 'bas-${resourcesName}' - subnetAddressPrefixes: ['10.0.10.0/26'] + subnet: { + name: 'AzureBastionSubnet' + addressPrefixes: ['10.0.10.0/26'] + networkSecurityGroup: { + name: 'nsg-AzureBastionSubnet' + securityRules: [ + { + name: 'AllowGatewayManager' + properties: { + access: 'Allow' + direction: 'Inbound' + priority: 2702 + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'GatewayManager' + destinationAddressPrefix: '*' + } + } + { + name: 'AllowHttpsInBound' + properties: { + access: 'Allow' + direction: 'Inbound' + priority: 2703 + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'Internet' + destinationAddressPrefix: '*' + } + } + { + name: 'AllowSshRdpOutbound' + properties: { + access: 'Allow' + direction: 'Outbound' + priority: 100 + protocol: '*' + sourcePortRange: '*' + destinationPortRanges: ['22', '3389'] + sourceAddressPrefix: '*' + destinationAddressPrefix: 'VirtualNetwork' + } + } + { + name: 'AllowAzureCloudOutbound' + properties: { + access: 'Allow' + direction: 'Outbound' + priority: 110 + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: '*' + destinationAddressPrefix: 'AzureCloud' + } + } + ] + } + } } jumpboxConfiguration: { name: 'vm-jumpbox-${resourcesName}' diff --git a/infra/modules/network/bastionHost.bicep b/infra/modules/network/bastionHost.bicep index f955a486..cc1987e5 100644 --- a/infra/modules/network/bastionHost.bicep +++ b/infra/modules/network/bastionHost.bicep @@ -8,9 +8,6 @@ param name string @description('Azure region to deploy resources.') param location string = resourceGroup().location -@description('Conditional. List of address prefixes for the subnet. Leave empty to skip subnet creation.') -param subnetAddressPrefixes string[]? - @description('Resource ID of the Virtual Network where the Azure Bastion Host will be deployed.') param vnetId string @@ -26,19 +23,38 @@ param tags object = {} @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -// 1. Create Azure Bastion Host using AVM Subnet Module with special config for Azure Bastion Subnet +import { subnetType } from 'virtualNetwork.bicep' +@description('Optional. Subnet configuration for the Jumpbox VM.') +param subnet subnetType? + +// 1. Create AzureBastionSubnet NSG +// using AVM Network Security Group module +// https://github.com/Azure/bicep-registry-modules/tree/main/avm/res/network/network-security-group +module nsg 'br/public:avm/res/network/network-security-group:0.5.1' = if (!empty(subnet)) { + name: '${vnetName}-${subnet.?networkSecurityGroup.name}' + params: { + name: '${subnet.?networkSecurityGroup.name}-${vnetName}' + location: location + securityRules: subnet.?networkSecurityGroup.securityRules + tags: tags + enableTelemetry: enableTelemetry + } +} + +// 2. Create Azure Bastion Host using AVM Subnet Module with special config for Azure Bastion Subnet // https://github.com/Azure/bicep-registry-modules/tree/main/avm/res/network/virtual-network/subnet -module bastionSubnet 'br/public:avm/res/network/virtual-network/subnet:0.1.2' = if (!empty(subnetAddressPrefixes)) { +module bastionSubnet 'br/public:avm/res/network/virtual-network/subnet:0.1.2' = if (!empty(subnet)) { name: take('bastionSubnet-${vnetName}', 64) params: { virtualNetworkName: vnetName name: 'AzureBastionSubnet' // this name required as is for Azure Bastion Host subnet - addressPrefixes: subnetAddressPrefixes + addressPrefixes: subnet.?addressPrefixes + networkSecurityGroupResourceId: nsg.outputs.resourceId enableTelemetry: enableTelemetry } } -// 2. Create Azure Bastion Host in AzureBastionsubnetSubnet using AVM Bastion Host module +// 3. Create Azure Bastion Host in AzureBastionsubnetSubnet using AVM Bastion Host module // https://github.com/Azure/bicep-registry-modules/tree/main/avm/res/network/bastion-host module bastionHost 'br/public:avm/res/network/bastion-host:0.6.1' = { @@ -64,9 +80,12 @@ module bastionHost 'br/public:avm/res/network/bastion-host:0.6.1' = { enableTelemetry: enableTelemetry publicIPAddressObject: { name: 'pip-${name}' - zones:[] + zones: [] } } + dependsOn: [ + bastionSubnet + ] } output resourceId string = bastionHost.outputs.resourceId @@ -80,6 +99,6 @@ type bastionHostConfigurationType = { @description('The name of the Bastion Host resource.') name: string - @description('Optional. List of address prefixes for the subnet.') - subnetAddressPrefixes: string[]? + @description('Optional. Subnet configuration for the Jumpbox VM.') + subnet: subnetType? } diff --git a/infra/modules/network/main.bicep b/infra/modules/network/main.bicep index bf5a4fd9..7e2e8658 100644 --- a/infra/modules/network/main.bicep +++ b/infra/modules/network/main.bicep @@ -60,7 +60,7 @@ module bastionHost 'bastionHost.bicep' = if (!empty(bastionConfiguration)) { vnetName: virtualNetwork.outputs.name location: location logAnalyticsWorkspaceId: logAnalyticsWorkSpaceResourceId - subnetAddressPrefixes: bastionConfiguration.?subnetAddressPrefixes + subnet: bastionConfiguration.?subnet tags: tags enableTelemetry: enableTelemetry } diff --git a/infra/samples/network-subnet-design.bicep b/infra/samples/network-subnet-design.bicep index 0cf7b240..da3edd40 100644 --- a/infra/samples/network-subnet-design.bicep +++ b/infra/samples/network-subnet-design.bicep @@ -43,7 +43,67 @@ import { bastionHostConfigurationType } from '../modules/network/bastionHost.bic @description('Optional. Configuration for the Azure Bastion Host. Leave null to omit Bastion creation.') param bastionConfiguration bastionHostConfigurationType = { name: 'bastion-${resourcesName}' - subnetAddressPrefixes: ['10.0.10.0/23'] // /23 (10.0.10.0 - 10.0.11.255), 512 addresses + subnet: { + name: 'AzureBastionSubnet' + addressPrefixes: ['10.0.10.0/23'] // /23 (10.0.10.0 - 10.0.11.255), 512 addresses + networkSecurityGroup: { + name: 'nsg-AzureBastionSubnet' + securityRules: [ + { + name: 'AllowGatewayManager' + properties: { + access: 'Allow' + direction: 'Inbound' + priority: 2702 + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'GatewayManager' + destinationAddressPrefix: '*' + } + } + { + name: 'AllowHttpsInBound' + properties: { + access: 'Allow' + direction: 'Inbound' + priority: 2703 + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: 'Internet' + destinationAddressPrefix: '*' + } + } + { + name: 'AllowSshRdpOutbound' + properties: { + access: 'Allow' + direction: 'Outbound' + priority: 100 + protocol: '*' + sourcePortRange: '*' + destinationPortRanges: ['22', '3389'] + sourceAddressPrefix: '*' + destinationAddressPrefix: 'VirtualNetwork' + } + } + { + name: 'AllowAzureCloudOutbound' + properties: { + access: 'Allow' + direction: 'Outbound' + priority: 110 + protocol: 'Tcp' + sourcePortRange: '*' + destinationPortRange: '443' + sourceAddressPrefix: '*' + destinationAddressPrefix: 'AzureCloud' + } + } + ] + } + } } import { jumpBoxConfigurationType } from '../modules/network/jumpbox.bicep'