From bfe6deffad36672b76bb41d3a28697038a0950d5 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:11:11 +0000 Subject: [PATCH 01/14] accelerator files --- .../.config/ALZ-Powershell-Auto.config.json | 80 ------------------- .../.config/ALZ-Powershell.config.json | 40 ---------- 2 files changed, 120 deletions(-) diff --git a/accelerator/.config/ALZ-Powershell-Auto.config.json b/accelerator/.config/ALZ-Powershell-Auto.config.json index c0671faae..9e37da45a 100644 --- a/accelerator/.config/ALZ-Powershell-Auto.config.json +++ b/accelerator/.config/ALZ-Powershell-Auto.config.json @@ -603,16 +603,6 @@ } ] }, - "AK8sPrivateLink": { - "source": "calculated", - "pattern": "privatelink.{%Location%}.azmk8s.io", - "targets": [ - { - "Name": "parPrivateDnsZones.value[0]", - "Destination": "Parameters" - } - ] - }, "parAzBastionName": { "source": "calculated", "pattern": "alz-bastion-{%Location%}", @@ -693,76 +683,6 @@ } ] }, - "AK8sPrivateLinkSecondary": { - "source": "calculated", - "pattern": "privatelink.{%SecondaryLocation%}.azmk8s.io", - "targets": [ - { - "Name": "parPrivateDnsZonesSecondaryLocation.value[0]", - "Destination": "Parameters" - } - ] - }, - "BatchPrivateLink": { - "source": "calculated", - "pattern": "privatelink.{%Location%}.batch.azure.com", - "targets": [ - { - "Name": "parPrivateDnsZones.value[1]", - "Destination": "Parameters" - } - ] - }, - "BatchPrivateLinkSecondary": { - "source": "calculated", - "pattern": "privatelink.{%SecondaryLocation%}.batch.azure.com", - "targets": [ - { - "Name": "parPrivateDnsZonesSecondaryLocation.value[1]", - "Destination": "Parameters" - } - ] - }, - "KustoPrivateLink": { - "source": "calculated", - "pattern": "privatelink.{%Location%}.kusto.windows.net", - "targets": [ - { - "Name": "parPrivateDnsZones.value[2]", - "Destination": "Parameters" - } - ] - }, - "KustoPrivateLinkSecondary": { - "source": "calculated", - "pattern": "privatelink.{%SecondaryLocation%}.kusto.windows.net", - "targets": [ - { - "Name": "parPrivateDnsZonesSecondaryLocation.value[2]", - "Destination": "Parameters" - } - ] - }, - "BackupPrivateLink": { - "source": "calculated", - "pattern": "privatelink.{%Location%}.backup.windowsazure.com", - "targets": [ - { - "Name": "parPrivateDnsZones.value[3]", - "Destination": "Parameters" - } - ] - }, - "BackupPrivateLinkSecondary": { - "source": "calculated", - "pattern": "privatelink.{%SecondaryLocation%}.backup.windowsazure.com", - "targets": [ - { - "Name": "parPrivateDnsZonesSecondaryLocation.value[3]", - "Destination": "Parameters" - } - ] - }, "ConnectivityResourceGroupName": { "source": "calculated", "pattern": "rg-{%Prefix%}-connectivity", diff --git a/accelerator/.config/ALZ-Powershell.config.json b/accelerator/.config/ALZ-Powershell.config.json index 190d35579..42354ecb4 100644 --- a/accelerator/.config/ALZ-Powershell.config.json +++ b/accelerator/.config/ALZ-Powershell.config.json @@ -603,46 +603,6 @@ } ] }, - "AK8sPrivateLink": { - "Type": "Computed", - "Value": "privatelink.{%Location%}.azmk8s.io", - "Targets": [ - { - "Name": "parPrivateDnsZones.value.[0]", - "Destination": "Parameters" - } - ] - }, - "BatchPrivateLink": { - "Type": "Computed", - "Value": "privatelink.{%Location%}.batch.azure.com", - "Targets": [ - { - "Name": "parPrivateDnsZones.value.[1]", - "Destination": "Parameters" - } - ] - }, - "KustoPrivateLink": { - "Type": "Computed", - "Value": "privatelink.{%Location%}.kusto.windows.net", - "Targets": [ - { - "Name": "parPrivateDnsZones.value.[2]", - "Destination": "Parameters" - } - ] - }, - "BackupPrivateLink": { - "Type": "Computed", - "Value": "privatelink.{%Location%}.backup.windowsazure.com", - "Targets": [ - { - "Name": "parPrivateDnsZones.value.[3]", - "Destination": "Parameters" - } - ] - }, "UpstreamReleaseVersion": { "Type": "Computed", "Value": "{REPLACED_BY_ALZ_POWERSHELL_MODULE}", From 8ae5044ccbd8bb2d3b66c62dc6c8f832d53a2e5b Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Mon, 28 Oct 2024 19:16:15 +0000 Subject: [PATCH 02/14] updates to v0.2.0 of ptn --- .../modules/hubNetworking/hubNetworking.bicep | 642 +++++++++--------- 1 file changed, 312 insertions(+), 330 deletions(-) diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index be79a84da..6eee4ba0a 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -49,7 +49,6 @@ param parGlobalResourceLock lockType = { notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' } - @sys.description('The IP address range for Hub Network.') param parHubNetworkAddressPrefix string = '10.10.0.0/16' @@ -173,12 +172,10 @@ param parAzFirewallPoliciesAutoLearn string = 'Disabled' 'Disabled' 'Enabled' ]) - @description('Private IP addresses/IP ranges to which traffic will not be SNAT.') param parAzFirewallPoliciesPrivateRanges array = [] @sys.description('Private IP addresses/IP ranges to which traffic will not be SNAT.') - @sys.description('Azure Firewall Tier associated with the Firewall to deploy.') @allowed([ 'Basic' @@ -262,83 +259,15 @@ param parPrivateDnsZonesEnabled bool = true @sys.description('Resource Group Name for Private DNS Zones.') param parPrivateDnsZonesResourceGroup string = resourceGroup().name -@sys.description('Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones') -param parPrivateDnsZones array = [ - 'privatelink.${toLower(parLocation)}.azmk8s.io' - 'privatelink.${toLower(parLocation)}.batch.azure.com' - 'privatelink.${toLower(parLocation)}.kusto.windows.net' - 'privatelink.adf.azure.com' - 'privatelink.afs.azure.net' - 'privatelink.agentsvc.azure-automation.net' - 'privatelink.analysis.windows.net' - 'privatelink.api.azureml.ms' - 'privatelink.azconfig.io' - 'privatelink.azure-api.net' - 'privatelink.azure-automation.net' - 'privatelink.azurecr.io' - 'privatelink.azure-devices.net' - 'privatelink.azure-devices-provisioning.net' - 'privatelink.azuredatabricks.net' - 'privatelink.azurehdinsight.net' - 'privatelink.azurehealthcareapis.com' - 'privatelink.azurestaticapps.net' - 'privatelink.azuresynapse.net' - 'privatelink.azurewebsites.net' - 'privatelink.batch.azure.com' - 'privatelink.blob.core.windows.net' - 'privatelink.cassandra.cosmos.azure.com' - 'privatelink.cognitiveservices.azure.com' - 'privatelink.database.windows.net' - 'privatelink.datafactory.azure.net' - 'privatelink.dev.azuresynapse.net' - 'privatelink.dfs.core.windows.net' - 'privatelink.dicom.azurehealthcareapis.com' - 'privatelink.digitaltwins.azure.net' - 'privatelink.directline.botframework.com' - 'privatelink.documents.azure.com' - 'privatelink.eventgrid.azure.net' - 'privatelink.file.core.windows.net' - 'privatelink.gremlin.cosmos.azure.com' - 'privatelink.guestconfiguration.azure.com' - 'privatelink.his.arc.azure.com' - 'privatelink.dp.kubernetesconfiguration.azure.com' - 'privatelink.managedhsm.azure.net' - 'privatelink.mariadb.database.azure.com' - 'privatelink.media.azure.net' - 'privatelink.mongo.cosmos.azure.com' - 'privatelink.monitor.azure.com' - 'privatelink.mysql.database.azure.com' - 'privatelink.notebooks.azure.net' - 'privatelink.ods.opinsights.azure.com' - 'privatelink.oms.opinsights.azure.com' - 'privatelink.pbidedicated.windows.net' - 'privatelink.postgres.database.azure.com' - 'privatelink.prod.migration.windowsazure.com' - 'privatelink.purview.azure.com' - 'privatelink.purviewstudio.azure.com' - 'privatelink.queue.core.windows.net' - 'privatelink.redis.cache.windows.net' - 'privatelink.redisenterprise.cache.azure.net' - 'privatelink.search.windows.net' - 'privatelink.service.signalr.net' - 'privatelink.servicebus.windows.net' - 'privatelink.siterecovery.windowsazure.com' - 'privatelink.sql.azuresynapse.net' - 'privatelink.table.core.windows.net' - 'privatelink.table.cosmos.azure.com' - 'privatelink.tip1.powerquery.microsoft.com' - 'privatelink.token.botframework.com' - 'privatelink.vaultcore.azure.net' - 'privatelink.web.core.windows.net' - 'privatelink.webpubsub.azure.com' -] - -@sys.description('Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup.') -param parPrivateDnsZoneAutoMergeAzureBackupZone bool = true +@sys.description('Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones') +param parPrivateDnsZones array = [] @sys.description('Resource ID of Failover VNet for Private DNS Zone VNet Failover Links') param parVirtualNetworkIdToLinkFailover string = '' +@sys.description('Array of Resource IDs of VNets to link to Private DNS Zones. Hub VNet is automatically included by module.') +param parVirtualNetworkResourceIdsToLinkTo array = [] + @sys.description('''Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. @@ -414,45 +343,59 @@ param parTags object = {} param parTelemetryOptOut bool = false @sys.description('Define outbound destination ports or ranges for SSH or RDP that you want to access from Azure Bastion.') -param parBastionOutboundSshRdpPorts array = [ '22', '3389' ] +param parBastionOutboundSshRdpPorts array = ['22', '3389'] var varSubnetMap = map(range(0, length(parSubnets)), i => { - name: parSubnets[i].name - ipAddressRange: parSubnets[i].ipAddressRange - networkSecurityGroupId: parSubnets[i].?networkSecurityGroupId ?? '' - routeTableId: parSubnets[i].?routeTableId ?? '' - delegation: parSubnets[i].?delegation ?? '' - }) - -var varSubnetProperties = [for subnet in varSubnetMap: { - name: subnet.name - properties: { - addressPrefix: subnet.ipAddressRange - - delegations: (empty(subnet.delegation)) ? null : [ - { - name: subnet.delegation - properties: { - serviceName: subnet.delegation - } - } - ] - - networkSecurityGroup: (subnet.name == 'AzureBastionSubnet' && parAzBastionEnabled) ? { - id: '${resourceGroup().id}/providers/Microsoft.Network/networkSecurityGroups/${parAzBastionNsgName}' - } : (empty(subnet.networkSecurityGroupId)) ? null : { - id: subnet.networkSecurityGroupId - } + name: parSubnets[i].name + ipAddressRange: parSubnets[i].ipAddressRange + networkSecurityGroupId: parSubnets[i].?networkSecurityGroupId ?? '' + routeTableId: parSubnets[i].?routeTableId ?? '' + delegation: parSubnets[i].?delegation ?? '' +}) + +var varSubnetProperties = [ + for subnet in varSubnetMap: { + name: subnet.name + properties: { + addressPrefix: subnet.ipAddressRange + + delegations: (empty(subnet.delegation)) + ? null + : [ + { + name: subnet.delegation + properties: { + serviceName: subnet.delegation + } + } + ] - routeTable: (empty(subnet.routeTableId)) ? null : { - id: subnet.routeTableId + networkSecurityGroup: (subnet.name == 'AzureBastionSubnet' && parAzBastionEnabled) + ? { + id: '${resourceGroup().id}/providers/Microsoft.Network/networkSecurityGroups/${parAzBastionNsgName}' + } + : (empty(subnet.networkSecurityGroupId)) + ? null + : { + id: subnet.networkSecurityGroupId + } + + routeTable: (empty(subnet.routeTableId)) + ? null + : { + id: subnet.routeTableId + } } } -}] +] -var varVpnGwConfig = ((parVpnGatewayEnabled) && (!empty(parVpnGatewayConfig)) ? parVpnGatewayConfig : json('{"name": "noconfigVpn"}')) +var varVpnGwConfig = ((parVpnGatewayEnabled) && (!empty(parVpnGatewayConfig)) + ? parVpnGatewayConfig + : json('{"name": "noconfigVpn"}')) -var varErGwConfig = ((parExpressRouteGatewayEnabled) && !empty(parExpressRouteGatewayConfig) ? parExpressRouteGatewayConfig : json('{"name": "noconfigEr"}')) +var varErGwConfig = ((parExpressRouteGatewayEnabled) && !empty(parExpressRouteGatewayConfig) + ? parExpressRouteGatewayConfig + : json('{"name": "noconfigEr"}')) var varGwConfig = [ varVpnGwConfig @@ -503,9 +446,11 @@ resource resHubVnet 'Microsoft.Network/virtualNetworks@2023-02-01' = { } subnets: varSubnetProperties enableDdosProtection: parDdosEnabled - ddosProtectionPlan: (parDdosEnabled) ? { - id: resDdosProtectionPlan.id - } : null + ddosProtectionPlan: (parDdosEnabled) + ? { + id: resDdosProtectionPlan.id + } + : null } } @@ -740,132 +685,154 @@ resource resBastionLock 'Microsoft.Authorization/locks@2020-05-01' = if (parAzBa } } -resource resGatewaySubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parVpnGatewayEnabled || parExpressRouteGatewayEnabled ) { +resource resGatewaySubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parVpnGatewayEnabled || parExpressRouteGatewayEnabled) { parent: resHubVnet name: 'GatewaySubnet' } -module modGatewayPublicIp '../publicIp/publicIp.bicep' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { - name: 'deploy-Gateway-Public-IP-${i}' - params: { - parLocation: parLocation - parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' ? parAzErGatewayAvailabilityZones : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] - parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}' - parPublicIpProperties: { - publicIpAddressVersion: 'IPv4' - publicIpAllocationMethod: 'Static' - } - parPublicIpSku: { - name: parPublicIpSku +module modGatewayPublicIp '../publicIp/publicIp.bicep' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { + name: 'deploy-Gateway-Public-IP-${i}' + params: { + parLocation: parLocation + parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' + ? parAzErGatewayAvailabilityZones + : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] + parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}' + parPublicIpProperties: { + publicIpAddressVersion: 'IPv4' + publicIpAllocationMethod: 'Static' + } + parPublicIpSku: { + name: parPublicIpSku + } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') + ? parGlobalResourceLock + : parVirtualNetworkGatewayLock + parTags: parTags + parTelemetryOptOut: parTelemetryOptOut } - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock - parTags: parTags - parTelemetryOptOut: parTelemetryOptOut } -}] +] // If the gateway is active-active, create a second public IP -module modGatewayPublicIpActiveActive '../publicIp/publicIp.bicep' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && gateway.activeActive) { - name: 'deploy-Gateway-Public-IP-ActiveActive-${i}' - params: { - parLocation: parLocation - parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' ? parAzErGatewayAvailabilityZones : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] - parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}-aa' - parPublicIpProperties: { - publicIpAddressVersion: 'IPv4' - publicIpAllocationMethod: 'Static' - } - parPublicIpSku: { - name: parPublicIpSku +module modGatewayPublicIpActiveActive '../publicIp/publicIp.bicep' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && gateway.activeActive) { + name: 'deploy-Gateway-Public-IP-ActiveActive-${i}' + params: { + parLocation: parLocation + parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' + ? parAzErGatewayAvailabilityZones + : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] + parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}-aa' + parPublicIpProperties: { + publicIpAddressVersion: 'IPv4' + publicIpAllocationMethod: 'Static' + } + parPublicIpSku: { + name: parPublicIpSku + } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') + ? parGlobalResourceLock + : parVirtualNetworkGatewayLock + parTags: parTags + parTelemetryOptOut: parTelemetryOptOut } - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock - parTags: parTags - parTelemetryOptOut: parTelemetryOptOut } -}] +] //Minumum subnet size is /27 supporting documentation https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub -resource resGateway 'Microsoft.Network/virtualNetworkGateways@2024-01-01' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { - name: gateway.name - location: parLocation - tags: parTags - properties: { - activeActive: gateway.activeActive - enableBgp: gateway.enableBgp - enableBgpRouteTranslationForNat: gateway.enableBgpRouteTranslationForNat - enableDnsForwarding: gateway.enableDnsForwarding - bgpSettings: (gateway.enableBgp) ? gateway.bgpSettings : null - gatewayType: gateway.gatewayType - vpnGatewayGeneration: (toLower(gateway.gatewayType) == 'vpn') ? gateway.generation : 'None' - vpnType: gateway.vpnType - sku: { - name: gateway.sku - tier: gateway.sku - } - vpnClientConfiguration: (toLower(gateway.gatewayType) == 'vpn') ? { - vpnClientAddressPool: gateway.vpnClientConfiguration.?vpnClientAddressPool ?? '' - vpnClientProtocols: gateway.vpnClientConfiguration.?vpnClientProtocols ?? '' - vpnAuthenticationTypes: gateway.vpnClientConfiguration.?vpnAuthenticationTypes ?? '' - aadTenant: gateway.vpnClientConfiguration.?aadTenant ?? '' - aadAudience: gateway.vpnClientConfiguration.?aadAudience ?? '' - aadIssuer: gateway.vpnClientConfiguration.?aadIssuer ?? '' - vpnClientRootCertificates: gateway.vpnClientConfiguration.?vpnClientRootCertificates ?? '' - radiusServerAddress: gateway.vpnClientConfiguration.?radiusServerAddress ?? '' - radiusServerSecret: gateway.vpnClientConfiguration.?radiusServerSecret ?? '' - } : null - - ipConfigurations: concat( - // Primary IP configuration - [ - { - id: resHubVnet.id - name: 'vnetGatewayConfig1' - properties: { - publicIPAddress: { - id: modGatewayPublicIp[i].outputs.outPublicIpId // Primary Public IP - } - subnet: { - id: resGatewaySubnetRef.id - } +resource resGateway 'Microsoft.Network/virtualNetworkGateways@2024-01-01' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { + name: gateway.name + location: parLocation + tags: parTags + properties: { + activeActive: gateway.activeActive + enableBgp: gateway.enableBgp + enableBgpRouteTranslationForNat: gateway.enableBgpRouteTranslationForNat + enableDnsForwarding: gateway.enableDnsForwarding + bgpSettings: (gateway.enableBgp) ? gateway.bgpSettings : null + gatewayType: gateway.gatewayType + vpnGatewayGeneration: (toLower(gateway.gatewayType) == 'vpn') ? gateway.generation : 'None' + vpnType: gateway.vpnType + sku: { + name: gateway.sku + tier: gateway.sku + } + vpnClientConfiguration: (toLower(gateway.gatewayType) == 'vpn') + ? { + vpnClientAddressPool: gateway.vpnClientConfiguration.?vpnClientAddressPool ?? '' + vpnClientProtocols: gateway.vpnClientConfiguration.?vpnClientProtocols ?? '' + vpnAuthenticationTypes: gateway.vpnClientConfiguration.?vpnAuthenticationTypes ?? '' + aadTenant: gateway.vpnClientConfiguration.?aadTenant ?? '' + aadAudience: gateway.vpnClientConfiguration.?aadAudience ?? '' + aadIssuer: gateway.vpnClientConfiguration.?aadIssuer ?? '' + vpnClientRootCertificates: gateway.vpnClientConfiguration.?vpnClientRootCertificates ?? '' + radiusServerAddress: gateway.vpnClientConfiguration.?radiusServerAddress ?? '' + radiusServerSecret: gateway.vpnClientConfiguration.?radiusServerSecret ?? '' } - } - ], - // Add second IP configuration if activeActive is true - gateway.activeActive ? [ - { - id: resHubVnet.id - name: 'vnetGatewayConfig2' - properties: { - publicIPAddress: { - id: modGatewayPublicIpActiveActive[i].outputs.outPublicIpId // Secondary Public IP - } - subnet: { - id: resGatewaySubnetRef.id + : null + + ipConfigurations: concat( + // Primary IP configuration + [ + { + id: resHubVnet.id + name: 'vnetGatewayConfig1' + properties: { + publicIPAddress: { + id: modGatewayPublicIp[i].outputs.outPublicIpId // Primary Public IP + } + subnet: { + id: resGatewaySubnetRef.id + } } } - } - ] : [] - ) + ], + // Add second IP configuration if activeActive is true + gateway.activeActive + ? [ + { + id: resHubVnet.id + name: 'vnetGatewayConfig2' + properties: { + publicIPAddress: { + id: modGatewayPublicIpActiveActive[i].outputs.outPublicIpId // Secondary Public IP + } + subnet: { + id: resGatewaySubnetRef.id + } + } + } + ] + : [] + ) + } } -}] - +] // Create a Virtual Network Gateway resource lock if gateway.name is not equal to noconfigVpn or noconfigEr and parGlobalResourceLock.kind != 'None' or if parVirtualNetworkGatewayLock.kind != 'None' -resource resVirtualNetworkGatewayLock 'Microsoft.Authorization/locks@2020-05-01' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && (parVirtualNetworkGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { - scope: resGateway[i] - name: parVirtualNetworkGatewayLock.?name ?? '${resGateway[i].name}-lock' - properties: { - level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkGatewayLock.kind - notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkGatewayLock.?notes +resource resVirtualNetworkGatewayLock 'Microsoft.Authorization/locks@2020-05-01' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && (parVirtualNetworkGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resGateway[i] + name: parVirtualNetworkGatewayLock.?name ?? '${resGateway[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkGatewayLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkGatewayLock.?notes + } } -}] +] resource resAzureFirewallSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabled) { parent: resHubVnet name: 'AzureFirewallSubnet' } -resource resAzureFirewallMgmtSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabled && (contains(map(parSubnets, subnets => subnets.name), 'AzureFirewallManagementSubnet'))) { +resource resAzureFirewallMgmtSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabled && (contains( + map(parSubnets, subnets => subnets.name), + 'AzureFirewallManagementSubnet' +))) { parent: resHubVnet name: 'AzureFirewallManagementSubnet' } @@ -889,7 +856,10 @@ module modAzureFirewallPublicIp '../publicIp/publicIp.bicep' = if (parAzFirewall } } -module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFirewallEnabled && (contains(map(parSubnets, subnets => subnets.name), 'AzureFirewallManagementSubnet'))) { +module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFirewallEnabled && (contains( + map(parSubnets, subnets => subnets.name), + 'AzureFirewallManagementSubnet' +))) { name: 'deploy-Firewall-mgmt-Public-IP' params: { parLocation: parLocation @@ -912,27 +882,29 @@ resource resFirewallPolicies 'Microsoft.Network/firewallPolicies@2024-01-01' = i name: parAzFirewallPoliciesName location: parLocation tags: parTags - properties: (parAzFirewallTier == 'Basic') ? { - sku: { - tier: parAzFirewallTier - } - snat: !empty(parAzFirewallPoliciesPrivateRanges) + properties: (parAzFirewallTier == 'Basic') ? { - autoLearnPrivateRanges: parAzFirewallPoliciesAutoLearn - privateRanges: parAzFirewallPoliciesPrivateRanges + sku: { + tier: parAzFirewallTier + } + snat: !empty(parAzFirewallPoliciesPrivateRanges) + ? { + autoLearnPrivateRanges: parAzFirewallPoliciesAutoLearn + privateRanges: parAzFirewallPoliciesPrivateRanges + } + : null + threatIntelMode: 'Alert' + } + : { + dnsSettings: { + enableProxy: parAzFirewallDnsProxyEnabled + servers: parAzFirewallDnsServers + } + sku: { + tier: parAzFirewallTier + } + threatIntelMode: parAzFirewallIntelMode } - : null - threatIntelMode: 'Alert' - } : { - dnsSettings: { - enableProxy: parAzFirewallDnsProxyEnabled - servers: parAzFirewallDnsServers - } - sku: { - tier: parAzFirewallTier - } - threatIntelMode: parAzFirewallIntelMode - } } // Create Azure Firewall Policy resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' @@ -955,98 +927,98 @@ resource resAzureFirewall 'Microsoft.Network/azureFirewalls@2024-01-01' = if (pa location: parLocation tags: parTags zones: (!empty(parAzFirewallAvailabilityZones) ? parAzFirewallAvailabilityZones : []) - properties: parAzFirewallTier == 'Basic' ? { - ipConfigurations: varAzFirewallUseCustomPublicIps - ? map(parAzFirewallCustomPublicIps, ip => - { - name: 'ipconfig${uniqueString(ip)}' - properties: ip == parAzFirewallCustomPublicIps[0] - ? { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } - } - : { - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } - } - }) - : [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' + properties: parAzFirewallTier == 'Basic' + ? { + ipConfigurations: varAzFirewallUseCustomPublicIps + ? map(parAzFirewallCustomPublicIps, ip => { + name: 'ipconfig${uniqueString(ip)}' + properties: ip == parAzFirewallCustomPublicIps[0] + ? { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + : { + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + }) + : [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' + } + } + } + ] + managementIpConfiguration: { + name: 'mgmtIpConfig' + properties: { + publicIPAddress: { + id: parAzFirewallEnabled ? modAzureFirewallMgmtPublicIp.outputs.outPublicIpId : '' + } + subnet: { + id: resAzureFirewallMgmtSubnetRef.id + } } } - } - ] - managementIpConfiguration: { - name: 'mgmtIpConfig' - properties: { - publicIPAddress: { - id: parAzFirewallEnabled ? modAzureFirewallMgmtPublicIp.outputs.outPublicIpId : '' + sku: { + name: 'AZFW_VNet' + tier: parAzFirewallTier } - subnet: { - id: resAzureFirewallMgmtSubnetRef.id + firewallPolicy: { + id: resFirewallPolicies.id } } - } - sku: { - name: 'AZFW_VNet' - tier: parAzFirewallTier - } - firewallPolicy: { - id: resFirewallPolicies.id - } - } : { - ipConfigurations: varAzFirewallUseCustomPublicIps - ? map(parAzFirewallCustomPublicIps, ip => - { - name: 'ipconfig${uniqueString(ip)}' - properties: ip == parAzFirewallCustomPublicIps[0] - ? { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } + : { + ipConfigurations: varAzFirewallUseCustomPublicIps + ? map(parAzFirewallCustomPublicIps, ip => { + name: 'ipconfig${uniqueString(ip)}' + properties: ip == parAzFirewallCustomPublicIps[0] + ? { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + : { + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + }) + : [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' + } + } + } + ] + sku: { + name: 'AZFW_VNet' + tier: parAzFirewallTier } - : { - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } - } - }) - : [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' - } + firewallPolicy: { + id: resFirewallPolicies.id } } - ] - sku: { - name: 'AZFW_VNet' - tier: parAzFirewallTier - } - firewallPolicy: { - id: resFirewallPolicies.id - } - } } // Create Azure Firewall resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' @@ -1071,7 +1043,9 @@ resource resHubRouteTable 'Microsoft.Network/routeTables@2024-01-01' = if (parAz properties: { addressPrefix: '0.0.0.0/0' nextHopType: 'VirtualAppliance' - nextHopIpAddress: parAzFirewallEnabled ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : '' + nextHopIpAddress: parAzFirewallEnabled + ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + : '' } } ] @@ -1089,18 +1063,23 @@ resource resHubRouteTableLock 'Microsoft.Authorization/locks@2020-05-01' = if (p } } -module modPrivateDnsZones '../privateDnsZones/privateDnsZones.bicep' = if (parPrivateDnsZonesEnabled) { - name: 'deploy-Private-DNS-Zones' +module modPrivateDnsZonesAVM 'br/public:avm/ptn/network/private-link-private-dns-zones:0.2.0' = if (parPrivateDnsZonesEnabled) { + name: 'deploy-Private-DNS-Zones-AVM' scope: resourceGroup(parPrivateDnsZonesResourceGroup) params: { - parLocation: parLocation - parTags: parTags - parVirtualNetworkIdToLink: resHubVnet.id - parVirtualNetworkIdToLinkFailover: parVirtualNetworkIdToLinkFailover - parPrivateDnsZones: parPrivateDnsZones - parPrivateDnsZoneAutoMergeAzureBackupZone: parPrivateDnsZoneAutoMergeAzureBackupZone - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parPrivateDNSZonesLock - parTelemetryOptOut: parTelemetryOptOut + location: parLocation + privateLinkPrivateDnsZones: empty(parPrivateDnsZones) ? null : parPrivateDnsZones + virtualNetworkResourceIdsToLinkTo: union( + [resHubVnet.id], + !empty(parVirtualNetworkIdToLinkFailover) ? [parVirtualNetworkIdToLinkFailover] : [], + parVirtualNetworkResourceIdsToLinkTo + ) + enableTelemetry: parTelemetryOptOut ? false : true + tags: parTags + lock: { + name: parPrivateDNSZonesLock.?name ?? 'pl-pdns-zone-lock' + kind: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parPrivateDNSZonesLock.kind + } } } @@ -1118,13 +1097,16 @@ module modCustomerUsageAttributionZtnP1 '../../CRML/customerUsageAttribution/cua } //If Azure Firewall is enabled we will deploy a RouteTable to redirect Traffic to the Firewall. -output outAzFirewallPrivateIp string = parAzFirewallEnabled ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : '' +output outAzFirewallPrivateIp string = parAzFirewallEnabled + ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + : '' //If Azure Firewall is enabled we will deploy a RouteTable to redirect Traffic to the Firewall. output outAzFirewallName string = parAzFirewallEnabled ? parAzFirewallName : '' -output outPrivateDnsZones array = (parPrivateDnsZonesEnabled ? modPrivateDnsZones.outputs.outPrivateDnsZones : []) -output outPrivateDnsZonesNames array = (parPrivateDnsZonesEnabled ? modPrivateDnsZones.outputs.outPrivateDnsZonesNames : []) +output outPrivateDnsZones array = (parPrivateDnsZonesEnabled + ? modPrivateDnsZonesAVM.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink + : []) output outDdosPlanResourceId string = parDdosEnabled ? resDdosProtectionPlan.id : '' output outHubVirtualNetworkName string = resHubVnet.name From 2f936bf0c544fb8d536d3a5bca4138fb1ab9b027 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:06:28 +0000 Subject: [PATCH 03/14] docs update --- .../generateddocs/hubNetworking.bicep.md | 95 +++---------------- 1 file changed, 11 insertions(+), 84 deletions(-) diff --git a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md index 845ee0c05..e5bf19cd9 100644 --- a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md +++ b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md @@ -46,9 +46,9 @@ parDisableBgpRoutePropagation | No | Switch to enable/disable BGP Propagat parHubRouteTableLock | No | Resource Lock Configuration for Hub Route Table. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPrivateDnsZonesEnabled | No | Switch to enable/disable Private DNS Zones deployment. parPrivateDnsZonesResourceGroup | No | Resource Group Name for Private DNS Zones. -parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones -parPrivateDnsZoneAutoMergeAzureBackupZone | No | Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. +parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones parVirtualNetworkIdToLinkFailover | No | Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +parVirtualNetworkResourceIdsToLinkTo | No | Array of Resource IDs of VNets to link to Private DNS Zones. Hub VNet is automatically included by module. parPrivateDNSZonesLock | No | Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parVpnGatewayEnabled | No | Switch to enable/disable VPN virtual network gateway deployment. parVpnGatewayConfig | No | Configuration for VPN virtual network gateway to be deployed. @@ -413,23 +413,19 @@ Resource Group Name for Private DNS Zones. ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones +Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones -- Default value: `[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))] [format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))] [format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))] privatelink.adf.azure.com privatelink.afs.azure.net privatelink.agentsvc.azure-automation.net privatelink.analysis.windows.net privatelink.api.azureml.ms privatelink.azconfig.io privatelink.azure-api.net privatelink.azure-automation.net privatelink.azurecr.io privatelink.azure-devices.net privatelink.azure-devices-provisioning.net privatelink.azuredatabricks.net privatelink.azurehdinsight.net privatelink.azurehealthcareapis.com privatelink.azurestaticapps.net privatelink.azuresynapse.net privatelink.azurewebsites.net privatelink.batch.azure.com privatelink.blob.core.windows.net privatelink.cassandra.cosmos.azure.com privatelink.cognitiveservices.azure.com privatelink.database.windows.net privatelink.datafactory.azure.net privatelink.dev.azuresynapse.net privatelink.dfs.core.windows.net privatelink.dicom.azurehealthcareapis.com privatelink.digitaltwins.azure.net privatelink.directline.botframework.com privatelink.documents.azure.com privatelink.eventgrid.azure.net privatelink.file.core.windows.net privatelink.gremlin.cosmos.azure.com privatelink.guestconfiguration.azure.com privatelink.his.arc.azure.com privatelink.dp.kubernetesconfiguration.azure.com privatelink.managedhsm.azure.net privatelink.mariadb.database.azure.com privatelink.media.azure.net privatelink.mongo.cosmos.azure.com privatelink.monitor.azure.com privatelink.mysql.database.azure.com privatelink.notebooks.azure.net privatelink.ods.opinsights.azure.com privatelink.oms.opinsights.azure.com privatelink.pbidedicated.windows.net privatelink.postgres.database.azure.com privatelink.prod.migration.windowsazure.com privatelink.purview.azure.com privatelink.purviewstudio.azure.com privatelink.queue.core.windows.net privatelink.redis.cache.windows.net privatelink.redisenterprise.cache.azure.net privatelink.search.windows.net privatelink.service.signalr.net privatelink.servicebus.windows.net privatelink.siterecovery.windowsazure.com privatelink.sql.azuresynapse.net privatelink.table.core.windows.net privatelink.table.cosmos.azure.com privatelink.tip1.powerquery.microsoft.com privatelink.token.botframework.com privatelink.vaultcore.azure.net privatelink.web.core.windows.net privatelink.webpubsub.azure.com` - -### parPrivateDnsZoneAutoMergeAzureBackupZone +### parVirtualNetworkIdToLinkFailover ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. - -- Default value: `True` +Resource ID of Failover VNet for Private DNS Zone VNet Failover Links -### parVirtualNetworkIdToLinkFailover +### parVirtualNetworkResourceIdsToLinkTo ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +Array of Resource IDs of VNets to link to Private DNS Zones. Hub VNet is automatically included by module. ### parPrivateDNSZonesLock @@ -518,7 +514,6 @@ Name | Type | Description outAzFirewallPrivateIp | string | outAzFirewallName | string | outPrivateDnsZones | array | -outPrivateDnsZonesNames | array | outDdosPlanResourceId | string | outHubVirtualNetworkName | string | outHubVirtualNetworkId | string | @@ -703,82 +698,14 @@ outBastionNsgName | string | "value": "[resourceGroup().name]" }, "parPrivateDnsZones": { - "value": [ - "[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))]", - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] - }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true + "value": [] }, "parVirtualNetworkIdToLinkFailover": { "value": "" }, + "parVirtualNetworkResourceIdsToLinkTo": { + "value": [] + }, "parPrivateDNSZonesLock": { "value": { "kind": "None", From 08cdec4de393910b0c54218e5bcce453b5e8ab20 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:07:32 +0000 Subject: [PATCH 04/14] add output for names --- .../modules/hubNetworking/generateddocs/hubNetworking.bicep.md | 1 + infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep | 3 +++ 2 files changed, 4 insertions(+) diff --git a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md index e5bf19cd9..c5ad326fd 100644 --- a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md +++ b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md @@ -514,6 +514,7 @@ Name | Type | Description outAzFirewallPrivateIp | string | outAzFirewallName | string | outPrivateDnsZones | array | +outPrivateDnsZonesNames | array | outDdosPlanResourceId | string | outHubVirtualNetworkName | string | outHubVirtualNetworkId | string | diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index 6eee4ba0a..e996fe72f 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -1107,6 +1107,9 @@ output outAzFirewallName string = parAzFirewallEnabled ? parAzFirewallName : '' output outPrivateDnsZones array = (parPrivateDnsZonesEnabled ? modPrivateDnsZonesAVM.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink : []) +output outPrivateDnsZonesNames array = (parPrivateDnsZonesEnabled + ? map(modPrivateDnsZonesAVM.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink, zone => zone.pdnsZoneName) + : []) output outDdosPlanResourceId string = parDdosEnabled ? resDdosProtectionPlan.id : '' output outHubVirtualNetworkName string = resHubVnet.name From 51484f7dd74dee50b2f516c70b13d29ca6b3c220 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:09:34 +0000 Subject: [PATCH 05/14] fmt --- .../bicep/modules/hubNetworking/hubNetworking.bicep | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index e996fe72f..fabe71858 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -1108,7 +1108,10 @@ output outPrivateDnsZones array = (parPrivateDnsZonesEnabled ? modPrivateDnsZonesAVM.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink : []) output outPrivateDnsZonesNames array = (parPrivateDnsZonesEnabled - ? map(modPrivateDnsZonesAVM.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink, zone => zone.pdnsZoneName) + ? map( + modPrivateDnsZonesAVM.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink, + zone => zone.pdnsZoneName + ) : []) output outDdosPlanResourceId string = parDdosEnabled ? resDdosProtectionPlan.id : '' From 1649b532f97bf9774b1b513a39b639ba912409b0 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Wed, 30 Oct 2024 20:30:09 +0000 Subject: [PATCH 06/14] bump to pdns 0.2.1 --- infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index fabe71858..1171e2791 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -1063,8 +1063,8 @@ resource resHubRouteTableLock 'Microsoft.Authorization/locks@2020-05-01' = if (p } } -module modPrivateDnsZonesAVM 'br/public:avm/ptn/network/private-link-private-dns-zones:0.2.0' = if (parPrivateDnsZonesEnabled) { - name: 'deploy-Private-DNS-Zones-AVM' +module modPrivateDnsZonesAVM 'br/public:avm/ptn/network/private-link-private-dns-zones:0.2.1' = if (parPrivateDnsZonesEnabled) { + name: 'deploy-Private-DNS-Zones-AVM-Single' scope: resourceGroup(parPrivateDnsZonesResourceGroup) params: { location: parLocation From 175bfaca149222bccb4da8f8591f8fc8ee312730 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:06:01 +0000 Subject: [PATCH 07/14] hub MR changes --- .../hubNetworking-multiRegion.bicep | 1229 +++++++++-------- .../modules/hubNetworking/hubNetworking.bicep | 2 +- 2 files changed, 657 insertions(+), 574 deletions(-) diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking-multiRegion.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking-multiRegion.bicep index 543f6efe6..270b0d8b3 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking-multiRegion.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking-multiRegion.bicep @@ -120,7 +120,7 @@ param parSubnetsSecondaryLocation subnetOptionsType = [ @sys.description('Array of DNS Server IP addresses for VNet.') param parDnsServerIps array = [] - @sys.description('Array of DNS Server IP addresses for VNet in the secondary location.') +@sys.description('Array of DNS Server IP addresses for VNet in the secondary location.') param parDnsServerIpsSecondaryLocation array = [] @sys.description('''Resource Lock Configuration for Virtual Network. @@ -259,14 +259,12 @@ param parAzFirewallPoliciesAutoLearn string = 'Disabled' 'Disabled' 'Enabled' ]) - @description('The operation mode for automatically learning private ranges to not be SNAT in the secondary location.') -param parAzFirewallPoliciesAutoLearnSecondaryLocation string = 'Disabled' +param parAzFirewallPoliciesAutoLearnSecondaryLocation string = 'Disabled' @allowed([ 'Disabled' 'Enabled' ]) - @description('Private IP addresses/IP ranges to which traffic will not be SNAT.') param parAzFirewallPoliciesPrivateRanges array = [] @@ -411,84 +409,15 @@ param parPrivateDnsZonesEnabled bool = true @sys.description('Resource Group Name for Private DNS Zones.') param parPrivateDnsZonesResourceGroup string = resourceGroup().name -@sys.description('Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones') -param parPrivateDnsZones array = [ - 'privatelink.${toLower(parLocation)}.azmk8s.io' - 'privatelink.${toLower(parLocation)}.batch.azure.com' - 'privatelink.${toLower(parLocation)}.kusto.windows.net' - 'privatelink.${toLower(parLocation)}.backup.windowsazure.com' - 'privatelink.adf.azure.com' - 'privatelink.afs.azure.net' - 'privatelink.agentsvc.azure-automation.net' - 'privatelink.analysis.windows.net' - 'privatelink.api.azureml.ms' - 'privatelink.azconfig.io' - 'privatelink.azure-api.net' - 'privatelink.azure-automation.net' - 'privatelink.azurecr.io' - 'privatelink.azure-devices.net' - 'privatelink.azure-devices-provisioning.net' - 'privatelink.azuredatabricks.net' - 'privatelink.azurehdinsight.net' - 'privatelink.azurehealthcareapis.com' - 'privatelink.azurestaticapps.net' - 'privatelink.azuresynapse.net' - 'privatelink.azurewebsites.net' - 'privatelink.batch.azure.com' - 'privatelink.blob.core.windows.net' - 'privatelink.cassandra.cosmos.azure.com' - 'privatelink.cognitiveservices.azure.com' - 'privatelink.database.windows.net' - 'privatelink.datafactory.azure.net' - 'privatelink.dev.azuresynapse.net' - 'privatelink.dfs.core.windows.net' - 'privatelink.dicom.azurehealthcareapis.com' - 'privatelink.digitaltwins.azure.net' - 'privatelink.directline.botframework.com' - 'privatelink.documents.azure.com' - 'privatelink.eventgrid.azure.net' - 'privatelink.file.core.windows.net' - 'privatelink.gremlin.cosmos.azure.com' - 'privatelink.guestconfiguration.azure.com' - 'privatelink.his.arc.azure.com' - 'privatelink.dp.kubernetesconfiguration.azure.com' - 'privatelink.managedhsm.azure.net' - 'privatelink.mariadb.database.azure.com' - 'privatelink.media.azure.net' - 'privatelink.mongo.cosmos.azure.com' - 'privatelink.monitor.azure.com' - 'privatelink.mysql.database.azure.com' - 'privatelink.notebooks.azure.net' - 'privatelink.ods.opinsights.azure.com' - 'privatelink.oms.opinsights.azure.com' - 'privatelink.pbidedicated.windows.net' - 'privatelink.postgres.database.azure.com' - 'privatelink.prod.migration.windowsazure.com' - 'privatelink.purview.azure.com' - 'privatelink.purviewstudio.azure.com' - 'privatelink.queue.core.windows.net' - 'privatelink.redis.cache.windows.net' - 'privatelink.redisenterprise.cache.azure.net' - 'privatelink.search.windows.net' - 'privatelink.service.signalr.net' - 'privatelink.servicebus.windows.net' - 'privatelink.siterecovery.windowsazure.com' - 'privatelink.sql.azuresynapse.net' - 'privatelink.table.core.windows.net' - 'privatelink.table.cosmos.azure.com' - 'privatelink.tip1.powerquery.microsoft.com' - 'privatelink.token.botframework.com' - 'privatelink.vaultcore.azure.net' - 'privatelink.web.core.windows.net' - 'privatelink.webpubsub.azure.com' -] - -@sys.description('Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup.') -param parPrivateDnsZoneAutoMergeAzureBackupZone bool = true +@sys.description('Array of DNS Zones to provision and link to Hub Virtual Networks. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones') +param parPrivateDnsZones array = [] @sys.description('Resource ID of Failover VNet for Private DNS Zone VNet Failover Links') param parVirtualNetworkIdToLinkFailover string = '' +@sys.description('Array of Resource IDs of VNets to link to Private DNS Zones. Hub VNets are automatically included by module.') +param parVirtualNetworkResourceIdsToLinkTo array = [] + @sys.description('''Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. @@ -610,18 +539,18 @@ param parTags object = {} param parTelemetryOptOut bool = false @sys.description('Define outbound destination ports or ranges for SSH or RDP that you want to access from Azure Bastion.') -param parBastionOutboundSshRdpPorts array = [ '22', '3389' ] +param parBastionOutboundSshRdpPorts array = ['22', '3389'] @sys.description('Define outbound destination ports or ranges for SSH or RDP that you want to access from Azure Bastion in secondary location.') -param parBastionOutboundSshRdpPortsSecondaryLocation array = [ '22', '3389' ] +param parBastionOutboundSshRdpPortsSecondaryLocation array = ['22', '3389'] var varSubnetMap = map(range(0, length(parSubnets)), i => { - name: parSubnets[i].name - ipAddressRange: parSubnets[i].ipAddressRange - networkSecurityGroupId: parSubnets[i].?networkSecurityGroupId ?? '' - routeTableId: parSubnets[i].?routeTableId ?? '' - delegation: parSubnets[i].?delegation ?? '' - }) + name: parSubnets[i].name + ipAddressRange: parSubnets[i].ipAddressRange + networkSecurityGroupId: parSubnets[i].?networkSecurityGroupId ?? '' + routeTableId: parSubnets[i].?routeTableId ?? '' + delegation: parSubnets[i].?delegation ?? '' +}) var varSubnetMapSecondaryLocation = map(range(0, length(parSubnetsSecondaryLocation)), i => { name: parSubnetsSecondaryLocation[i].name @@ -631,65 +560,93 @@ var varSubnetMapSecondaryLocation = map(range(0, length(parSubnetsSecondaryLocat delegation: parSubnetsSecondaryLocation[i].?delegation ?? '' }) -var varSubnetProperties = [for subnet in varSubnetMap: { - name: subnet.name - properties: { - addressPrefix: subnet.ipAddressRange - - delegations: (empty(subnet.delegation)) ? null : [ - { - name: subnet.delegation - properties: { - serviceName: subnet.delegation - } - } - ] - - networkSecurityGroup: (subnet.name == 'AzureBastionSubnet' && parAzBastionEnabled) ? { - id: '${resourceGroup().id}/providers/Microsoft.Network/networkSecurityGroups/${parAzBastionNsgName}' - } : (empty(subnet.networkSecurityGroupId)) ? null : { - id: subnet.networkSecurityGroupId - } +var varSubnetProperties = [ + for subnet in varSubnetMap: { + name: subnet.name + properties: { + addressPrefix: subnet.ipAddressRange + + delegations: (empty(subnet.delegation)) + ? null + : [ + { + name: subnet.delegation + properties: { + serviceName: subnet.delegation + } + } + ] - routeTable: (empty(subnet.routeTableId)) ? null : { - id: subnet.routeTableId + networkSecurityGroup: (subnet.name == 'AzureBastionSubnet' && parAzBastionEnabled) + ? { + id: '${resourceGroup().id}/providers/Microsoft.Network/networkSecurityGroups/${parAzBastionNsgName}' + } + : (empty(subnet.networkSecurityGroupId)) + ? null + : { + id: subnet.networkSecurityGroupId + } + + routeTable: (empty(subnet.routeTableId)) + ? null + : { + id: subnet.routeTableId + } } } -}] - -var varSubnetPropertiesSecondaryLocation = [for subnet in varSubnetMapSecondaryLocation: { - name: subnet.name - properties: { - addressPrefix: subnet.ipAddressRange - - delegations: (empty(subnet.delegation)) ? null : [ - { - name: subnet.delegation - properties: { - serviceName: subnet.delegation - } - } - ] +] - networkSecurityGroup: (subnet.name == 'AzureBastionSubnet' && parAzBastionEnabledSecondaryLocation) ? { - id: '${resourceGroup().id}/providers/Microsoft.Network/networkSecurityGroups/${parAzBastionNsgNameSecondaryLocation}' - } : (empty(subnet.networkSecurityGroupId)) ? null : { - id: subnet.networkSecurityGroupId - } +var varSubnetPropertiesSecondaryLocation = [ + for subnet in varSubnetMapSecondaryLocation: { + name: subnet.name + properties: { + addressPrefix: subnet.ipAddressRange + + delegations: (empty(subnet.delegation)) + ? null + : [ + { + name: subnet.delegation + properties: { + serviceName: subnet.delegation + } + } + ] - routeTable: (empty(subnet.routeTableId)) ? null : { - id: subnet.routeTableId + networkSecurityGroup: (subnet.name == 'AzureBastionSubnet' && parAzBastionEnabledSecondaryLocation) + ? { + id: '${resourceGroup().id}/providers/Microsoft.Network/networkSecurityGroups/${parAzBastionNsgNameSecondaryLocation}' + } + : (empty(subnet.networkSecurityGroupId)) + ? null + : { + id: subnet.networkSecurityGroupId + } + + routeTable: (empty(subnet.routeTableId)) + ? null + : { + id: subnet.routeTableId + } } } -}] +] -var varVpnGwConfig = ((parVpnGatewayEnabled) && (!empty(parVpnGatewayConfig)) ? parVpnGatewayConfig : json('{"name": "noconfigVpn"}')) +var varVpnGwConfig = ((parVpnGatewayEnabled) && (!empty(parVpnGatewayConfig)) + ? parVpnGatewayConfig + : json('{"name": "noconfigVpn"}')) -var varVpnGwConfigSecondaryLocation = ((parVpnGatewayEnabledSecondaryLocation) && (!empty(parVpnGatewayConfigSecondaryLocation)) ? parVpnGatewayConfigSecondaryLocation : json('{"name": "noconfigVpn"}')) +var varVpnGwConfigSecondaryLocation = ((parVpnGatewayEnabledSecondaryLocation) && (!empty(parVpnGatewayConfigSecondaryLocation)) + ? parVpnGatewayConfigSecondaryLocation + : json('{"name": "noconfigVpn"}')) -var varErGwConfig = ((parExpressRouteGatewayEnabled) && !empty(parExpressRouteGatewayConfig) ? parExpressRouteGatewayConfig : json('{"name": "noconfigEr"}')) +var varErGwConfig = ((parExpressRouteGatewayEnabled) && !empty(parExpressRouteGatewayConfig) + ? parExpressRouteGatewayConfig + : json('{"name": "noconfigEr"}')) -var varErGwConfigSecondaryLocation = ((parExpressRouteGatewayEnabledSecondaryLocation) && !empty(parExpressRouteGatewayConfigSecondaryLocation) ? parExpressRouteGatewayConfigSecondaryLocation : json('{"name": "noconfigEr"}')) +var varErGwConfigSecondaryLocation = ((parExpressRouteGatewayEnabledSecondaryLocation) && !empty(parExpressRouteGatewayConfigSecondaryLocation) + ? parExpressRouteGatewayConfigSecondaryLocation + : json('{"name": "noconfigEr"}')) var varGwConfig = [ varVpnGwConfig @@ -708,7 +665,9 @@ var varCuaid = '2686e846-5fdc-4d4f-b533-16dcb09d6e6c' var varZtnP1CuaId = '3ab23b1e-c5c5-42d4-b163-1402384ba2db' var varZtnP1Trigger = (parDdosEnabled && parAzFirewallEnabled && (parAzFirewallTier == 'Premium')) ? true : false -var varZtnP1TriggerSecondaryLocation = (parDdosEnabledSecondaryLocation && parAzFirewallEnabledSecondaryLocation && (parAzFirewallTierSecondaryLocation == 'Premium')) ? true : false +var varZtnP1TriggerSecondaryLocation = (parDdosEnabledSecondaryLocation && parAzFirewallEnabledSecondaryLocation && (parAzFirewallTierSecondaryLocation == 'Premium')) + ? true + : false var varAzFirewallUseCustomPublicIps = length(parAzFirewallCustomPublicIps) > 0 @@ -766,9 +725,11 @@ resource resHubVnet 'Microsoft.Network/virtualNetworks@2024-01-01' = { } subnets: varSubnetProperties enableDdosProtection: parDdosEnabled - ddosProtectionPlan: (parDdosEnabled) ? { - id: resDdosProtectionPlan.id - } : null + ddosProtectionPlan: (parDdosEnabled) + ? { + id: resDdosProtectionPlan.id + } + : null } } @@ -790,9 +751,11 @@ resource resHubVnetSecondaryLocation 'Microsoft.Network/virtualNetworks@2024-01- } subnets: varSubnetPropertiesSecondaryLocation enableDdosProtection: parDdosEnabledSecondaryLocation - ddosProtectionPlan: (parDdosEnabledSecondaryLocation) ? { - id: resDdosProtectionPlanSecondaryLocation.id - } : null + ddosProtectionPlan: (parDdosEnabledSecondaryLocation) + ? { + id: resDdosProtectionPlanSecondaryLocation.id + } + : null } } @@ -1206,7 +1169,6 @@ resource resBastionNsgLockSecondaryLocation 'Microsoft.Authorization/locks@2020- } } - // AzureBastionSubnet is required to deploy Bastion service. This subnet must exist in the parsubnets array if you enable Bastion Service. // There is a minimum subnet requirement of /27 prefix. // If you are deploying standard this needs to be larger. https://docs.microsoft.com/en-us/azure/bastion/configuration-settings#subnet @@ -1248,7 +1210,9 @@ resource resBastionSecondaryLocation 'Microsoft.Network/bastionHosts@2024-01-01' } properties: { dnsName: uniqueString(resourceGroup().id) - enableTunneling: (parAzBastionSkuSecondaryLocation == 'Standard' && parAzBastionTunnelingSecondaryLocation) ? parAzBastionTunnelingSecondaryLocation : false + enableTunneling: (parAzBastionSkuSecondaryLocation == 'Standard' && parAzBastionTunnelingSecondaryLocation) + ? parAzBastionTunnelingSecondaryLocation + : false ipConfigurations: [ { name: 'IpConf' @@ -1285,241 +1249,281 @@ resource resBastionLockSecondaryLocation 'Microsoft.Authorization/locks@2020-05- } } -resource resGatewaySubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parVpnGatewayEnabled || parExpressRouteGatewayEnabled ) { +resource resGatewaySubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parVpnGatewayEnabled || parExpressRouteGatewayEnabled) { parent: resHubVnet name: 'GatewaySubnet' } -resource resGatewaySubnetRefSecondaryLocation 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parVpnGatewayEnabledSecondaryLocation || parExpressRouteGatewayEnabledSecondaryLocation ) { +resource resGatewaySubnetRefSecondaryLocation 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parVpnGatewayEnabledSecondaryLocation || parExpressRouteGatewayEnabledSecondaryLocation) { parent: resHubVnetSecondaryLocation name: 'GatewaySubnet' } -module modGatewayPublicIp '../publicIp/publicIp.bicep' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { - name: 'deploy-Gateway-Public-IP-${i}' - params: { - parLocation: parLocation - parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' ? parAzErGatewayAvailabilityZones : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] - parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}' - parPublicIpProperties: { - publicIpAddressVersion: 'IPv4' - publicIpAllocationMethod: 'Static' - } - parPublicIpSku: { - name: parPublicIpSku +module modGatewayPublicIp '../publicIp/publicIp.bicep' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { + name: 'deploy-Gateway-Public-IP-${i}' + params: { + parLocation: parLocation + parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' + ? parAzErGatewayAvailabilityZones + : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] + parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}' + parPublicIpProperties: { + publicIpAddressVersion: 'IPv4' + publicIpAllocationMethod: 'Static' + } + parPublicIpSku: { + name: parPublicIpSku + } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') + ? parGlobalResourceLock + : parVirtualNetworkGatewayLock + parTags: parTags + parTelemetryOptOut: parTelemetryOptOut } - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock - parTags: parTags - parTelemetryOptOut: parTelemetryOptOut } -}] +] // If the gateway is active-active, create a second public IP -module modGatewayPublicIpActiveActive '../publicIp/publicIp.bicep' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && gateway.activeActive) { - name: 'deploy-Gateway-Public-IP-ActiveActive-${i}' - params: { - parLocation: parLocation - parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' ? parAzErGatewayAvailabilityZones : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] - parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}-aa' - parPublicIpProperties: { - publicIpAddressVersion: 'IPv4' - publicIpAllocationMethod: 'Static' - } - parPublicIpSku: { - name: parPublicIpSku +module modGatewayPublicIpActiveActive '../publicIp/publicIp.bicep' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && gateway.activeActive) { + name: 'deploy-Gateway-Public-IP-ActiveActive-${i}' + params: { + parLocation: parLocation + parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' + ? parAzErGatewayAvailabilityZones + : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] + parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}-aa' + parPublicIpProperties: { + publicIpAddressVersion: 'IPv4' + publicIpAllocationMethod: 'Static' + } + parPublicIpSku: { + name: parPublicIpSku + } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') + ? parGlobalResourceLock + : parVirtualNetworkGatewayLock + parTags: parTags + parTelemetryOptOut: parTelemetryOptOut } - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock - parTags: parTags - parTelemetryOptOut: parTelemetryOptOut } -}] +] -module modGatewayPublicIpSecondaryLocation '../publicIp/publicIp.bicep' = [for (gateway, i) in varGwConfigSecondaryLocation: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { - name: 'deploy-Gateway-Public-IP-Secondary-Location-${i}' - params: { - parLocation: parSecondaryLocation - parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' ? parAzErGatewayAvailabilityZonesSecondaryLocation : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZonesSecondaryLocation : [] - parPublicIpName: '${parPublicIpPrefixSecondaryLocation}${gateway.name}${parPublicIpSuffix}' - parPublicIpProperties: { - publicIpAddressVersion: 'IPv4' - publicIpAllocationMethod: 'Static' - } - parPublicIpSku: { - name: parPublicIpSkuSecondaryLocation +module modGatewayPublicIpSecondaryLocation '../publicIp/publicIp.bicep' = [ + for (gateway, i) in varGwConfigSecondaryLocation: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { + name: 'deploy-Gateway-Public-IP-Secondary-Location-${i}' + params: { + parLocation: parSecondaryLocation + parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' + ? parAzErGatewayAvailabilityZonesSecondaryLocation + : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZonesSecondaryLocation : [] + parPublicIpName: '${parPublicIpPrefixSecondaryLocation}${gateway.name}${parPublicIpSuffix}' + parPublicIpProperties: { + publicIpAddressVersion: 'IPv4' + publicIpAllocationMethod: 'Static' + } + parPublicIpSku: { + name: parPublicIpSkuSecondaryLocation + } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') + ? parGlobalResourceLock + : parVirtualNetworkGatewayLock + parTags: parTags + parTelemetryOptOut: parTelemetryOptOut } - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock - parTags: parTags - parTelemetryOptOut: parTelemetryOptOut } -}] +] // If the gateway is active-active, create a second public IP -module modGatewayPublicIpActiveActiveSecondaryLocation '../publicIp/publicIp.bicep' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && gateway.activeActive) { - name: 'deploy-Gateway-Public-IP-ActiveActive-${i}' - params: { - parLocation: parLocation - parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' ? parAzErGatewayAvailabilityZones : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] - parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}-aa' - parPublicIpProperties: { - publicIpAddressVersion: 'IPv4' - publicIpAllocationMethod: 'Static' - } - parPublicIpSku: { - name: parPublicIpSku +module modGatewayPublicIpActiveActiveSecondaryLocation '../publicIp/publicIp.bicep' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && gateway.activeActive) { + name: 'deploy-Gateway-Public-IP-ActiveActive-${i}' + params: { + parLocation: parLocation + parAvailabilityZones: toLower(gateway.gatewayType) == 'expressroute' + ? parAzErGatewayAvailabilityZones + : toLower(gateway.gatewayType) == 'vpn' ? parAzVpnGatewayAvailabilityZones : [] + parPublicIpName: '${parPublicIpPrefix}${gateway.name}${parPublicIpSuffix}-aa' + parPublicIpProperties: { + publicIpAddressVersion: 'IPv4' + publicIpAllocationMethod: 'Static' + } + parPublicIpSku: { + name: parPublicIpSku + } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') + ? parGlobalResourceLock + : parVirtualNetworkGatewayLock + parTags: parTags + parTelemetryOptOut: parTelemetryOptOut } - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock - parTags: parTags - parTelemetryOptOut: parTelemetryOptOut } -}] +] //Minumum subnet size is /27 supporting documentation https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub -resource resGateway 'Microsoft.Network/virtualNetworkGateways@2024-01-01' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { - name: gateway.name - location: parLocation - tags: parTags - properties: { - activeActive: gateway.activeActive - enableBgp: gateway.enableBgp - enableBgpRouteTranslationForNat: gateway.enableBgpRouteTranslationForNat - enableDnsForwarding: gateway.enableDnsForwarding - bgpSettings: (gateway.enableBgp) ? gateway.bgpSettings : null - gatewayType: gateway.gatewayType - vpnGatewayGeneration: (toLower(gateway.gatewayType) == 'vpn') ? gateway.generation : 'None' - vpnType: gateway.vpnType - sku: { - name: gateway.sku - tier: gateway.sku - } - vpnClientConfiguration: (toLower(gateway.gatewayType) == 'vpn') ? { - vpnClientAddressPool: gateway.vpnClientConfiguration.?vpnClientAddressPool ?? '' - vpnClientProtocols: gateway.vpnClientConfiguration.?vpnClientProtocols ?? '' - vpnAuthenticationTypes: gateway.vpnClientConfiguration.?vpnAuthenticationTypes ?? '' - aadTenant: gateway.vpnClientConfiguration.?aadTenant ?? '' - aadAudience: gateway.vpnClientConfiguration.?aadAudience ?? '' - aadIssuer: gateway.vpnClientConfiguration.?aadIssuer ?? '' - vpnClientRootCertificates: gateway.vpnClientConfiguration.?vpnClientRootCertificates ?? '' - radiusServerAddress: gateway.vpnClientConfiguration.?radiusServerAddress ?? '' - radiusServerSecret: gateway.vpnClientConfiguration.?radiusServerSecret ?? '' - } : null - ipConfigurations: concat( - // Primary IP configuration - [ - { - id: resHubVnet.id - name: 'vnetGatewayConfig1' - properties: { - publicIPAddress: { - id: modGatewayPublicIp[i].outputs.outPublicIpId // Primary Public IP - } - subnet: { - id: resGatewaySubnetRef.id - } +resource resGateway 'Microsoft.Network/virtualNetworkGateways@2024-01-01' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { + name: gateway.name + location: parLocation + tags: parTags + properties: { + activeActive: gateway.activeActive + enableBgp: gateway.enableBgp + enableBgpRouteTranslationForNat: gateway.enableBgpRouteTranslationForNat + enableDnsForwarding: gateway.enableDnsForwarding + bgpSettings: (gateway.enableBgp) ? gateway.bgpSettings : null + gatewayType: gateway.gatewayType + vpnGatewayGeneration: (toLower(gateway.gatewayType) == 'vpn') ? gateway.generation : 'None' + vpnType: gateway.vpnType + sku: { + name: gateway.sku + tier: gateway.sku + } + vpnClientConfiguration: (toLower(gateway.gatewayType) == 'vpn') + ? { + vpnClientAddressPool: gateway.vpnClientConfiguration.?vpnClientAddressPool ?? '' + vpnClientProtocols: gateway.vpnClientConfiguration.?vpnClientProtocols ?? '' + vpnAuthenticationTypes: gateway.vpnClientConfiguration.?vpnAuthenticationTypes ?? '' + aadTenant: gateway.vpnClientConfiguration.?aadTenant ?? '' + aadAudience: gateway.vpnClientConfiguration.?aadAudience ?? '' + aadIssuer: gateway.vpnClientConfiguration.?aadIssuer ?? '' + vpnClientRootCertificates: gateway.vpnClientConfiguration.?vpnClientRootCertificates ?? '' + radiusServerAddress: gateway.vpnClientConfiguration.?radiusServerAddress ?? '' + radiusServerSecret: gateway.vpnClientConfiguration.?radiusServerSecret ?? '' } - } - ], - // Add second IP configuration if activeActive is true - gateway.activeActive ? [ - { - id: resHubVnet.id - name: 'vnetGatewayConfig2' - properties: { - publicIPAddress: { - id: modGatewayPublicIpActiveActive[i].outputs.outPublicIpId // Secondary Public IP - } - subnet: { - id: resGatewaySubnetRefSecondaryLocation.id + : null + ipConfigurations: concat( + // Primary IP configuration + [ + { + id: resHubVnet.id + name: 'vnetGatewayConfig1' + properties: { + publicIPAddress: { + id: modGatewayPublicIp[i].outputs.outPublicIpId // Primary Public IP + } + subnet: { + id: resGatewaySubnetRef.id + } } } - } - ] : [] - ) + ], + // Add second IP configuration if activeActive is true + gateway.activeActive + ? [ + { + id: resHubVnet.id + name: 'vnetGatewayConfig2' + properties: { + publicIPAddress: { + id: modGatewayPublicIpActiveActive[i].outputs.outPublicIpId // Secondary Public IP + } + subnet: { + id: resGatewaySubnetRefSecondaryLocation.id + } + } + } + ] + : [] + ) + } } -}] +] //Minumum subnet size is /27 supporting documentation https://docs.microsoft.com/en-us/azure/vpn-gateway/vpn-gateway-about-vpn-gateway-settings#gwsub -resource resGatewaySecondaryLocation 'Microsoft.Network/virtualNetworkGateways@2024-01-01' = [for (gateway, i) in varGwConfigSecondaryLocation: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { - name: gateway.name - location: parSecondaryLocation - tags: parTags - properties: { - activeActive: gateway.activeActive - enableBgp: gateway.enableBgp - enableBgpRouteTranslationForNat: gateway.enableBgpRouteTranslationForNat - enableDnsForwarding: gateway.enableDnsForwarding - bgpSettings: (gateway.enableBgp) ? gateway.bgpSettings : null - gatewayType: gateway.gatewayType - vpnGatewayGeneration: (toLower(gateway.gatewayType) == 'vpn') ? gateway.generation : 'None' - vpnType: gateway.vpnType - sku: { - name: gateway.sku - tier: gateway.sku - } - vpnClientConfiguration: (toLower(gateway.gatewayType) == 'vpn') ? { - vpnClientAddressPool: gateway.vpnClientConfiguration.?vpnClientAddressPool ?? '' - vpnClientProtocols: gateway.vpnClientConfiguration.?vpnClientProtocols ?? '' - vpnAuthenticationTypes: gateway.vpnClientConfiguration.?vpnAuthenticationTypes ?? '' - aadTenant: gateway.vpnClientConfiguration.?aadTenant ?? '' - aadAudience: gateway.vpnClientConfiguration.?aadAudience ?? '' - aadIssuer: gateway.vpnClientConfiguration.?aadIssuer ?? '' - vpnClientRootCertificates: gateway.vpnClientConfiguration.?vpnClientRootCertificates ?? '' - radiusServerAddress: gateway.vpnClientConfiguration.?radiusServerAddress ?? '' - radiusServerSecret: gateway.vpnClientConfiguration.?radiusServerSecret ?? '' - } : null - ipConfigurations: concat( - // Primary IP configuration - [ - { - id: resHubVnetSecondaryLocation.id - name: 'vnetGatewayConfig1' - properties: { - publicIPAddress: { - id: modGatewayPublicIpSecondaryLocation[i].outputs.outPublicIpId // Primary Public IP - } - subnet: { - id: resGatewaySubnetRefSecondaryLocation.id - } +resource resGatewaySecondaryLocation 'Microsoft.Network/virtualNetworkGateways@2024-01-01' = [ + for (gateway, i) in varGwConfigSecondaryLocation: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr')) { + name: gateway.name + location: parSecondaryLocation + tags: parTags + properties: { + activeActive: gateway.activeActive + enableBgp: gateway.enableBgp + enableBgpRouteTranslationForNat: gateway.enableBgpRouteTranslationForNat + enableDnsForwarding: gateway.enableDnsForwarding + bgpSettings: (gateway.enableBgp) ? gateway.bgpSettings : null + gatewayType: gateway.gatewayType + vpnGatewayGeneration: (toLower(gateway.gatewayType) == 'vpn') ? gateway.generation : 'None' + vpnType: gateway.vpnType + sku: { + name: gateway.sku + tier: gateway.sku + } + vpnClientConfiguration: (toLower(gateway.gatewayType) == 'vpn') + ? { + vpnClientAddressPool: gateway.vpnClientConfiguration.?vpnClientAddressPool ?? '' + vpnClientProtocols: gateway.vpnClientConfiguration.?vpnClientProtocols ?? '' + vpnAuthenticationTypes: gateway.vpnClientConfiguration.?vpnAuthenticationTypes ?? '' + aadTenant: gateway.vpnClientConfiguration.?aadTenant ?? '' + aadAudience: gateway.vpnClientConfiguration.?aadAudience ?? '' + aadIssuer: gateway.vpnClientConfiguration.?aadIssuer ?? '' + vpnClientRootCertificates: gateway.vpnClientConfiguration.?vpnClientRootCertificates ?? '' + radiusServerAddress: gateway.vpnClientConfiguration.?radiusServerAddress ?? '' + radiusServerSecret: gateway.vpnClientConfiguration.?radiusServerSecret ?? '' } - } - ], - // Add second IP configuration if activeActive is true - gateway.activeActive ? [ - { - id: resHubVnetSecondaryLocation.id - name: 'vnetGatewayConfig2' - properties: { - publicIPAddress: { - id: modGatewayPublicIpActiveActiveSecondaryLocation[i].outputs.outPublicIpId // Secondary Public IP - } - subnet: { - id: resGatewaySubnetRefSecondaryLocation.id + : null + ipConfigurations: concat( + // Primary IP configuration + [ + { + id: resHubVnetSecondaryLocation.id + name: 'vnetGatewayConfig1' + properties: { + publicIPAddress: { + id: modGatewayPublicIpSecondaryLocation[i].outputs.outPublicIpId // Primary Public IP + } + subnet: { + id: resGatewaySubnetRefSecondaryLocation.id + } } } - } - ] : [] - ) + ], + // Add second IP configuration if activeActive is true + gateway.activeActive + ? [ + { + id: resHubVnetSecondaryLocation.id + name: 'vnetGatewayConfig2' + properties: { + publicIPAddress: { + id: modGatewayPublicIpActiveActiveSecondaryLocation[i].outputs.outPublicIpId // Secondary Public IP + } + subnet: { + id: resGatewaySubnetRefSecondaryLocation.id + } + } + } + ] + : [] + ) + } } -}] +] // Create a Virtual Network Gateway resource lock if gateway.name is not equal to noconfigVpn or noconfigEr and parGlobalResourceLock.kind != 'None' or if parVirtualNetworkGatewayLock.kind != 'None' -resource resVirtualNetworkGatewayLock 'Microsoft.Authorization/locks@2020-05-01' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && (parVirtualNetworkGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { - scope: resGateway[i] - name: parVirtualNetworkGatewayLock.?name ?? '${resGateway[i].name}-lock' - properties: { - level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkGatewayLock.kind - notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkGatewayLock.?notes +resource resVirtualNetworkGatewayLock 'Microsoft.Authorization/locks@2020-05-01' = [ + for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && (parVirtualNetworkGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resGateway[i] + name: parVirtualNetworkGatewayLock.?name ?? '${resGateway[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkGatewayLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkGatewayLock.?notes + } } -}] +] // Create a Virtual Network Gateway resource lock if gateway.name is not equal to noconfigVpn or noconfigEr and parGlobalResourceLock.kind != 'None' or if parVirtualNetworkGatewayLock.kind != 'None' -resource resVirtualNetworkGatewayLockSecondaryLocation 'Microsoft.Authorization/locks@2020-05-01' = [for (gateway, i) in varGwConfigSecondaryLocation: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && (parVirtualNetworkGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { - scope: resGatewaySecondaryLocation[i] - name: parVirtualNetworkGatewayLock.?name ?? '${resGatewaySecondaryLocation[i].name}-lock' - properties: { - level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkGatewayLock.kind - notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkGatewayLock.?notes +resource resVirtualNetworkGatewayLockSecondaryLocation 'Microsoft.Authorization/locks@2020-05-01' = [ + for (gateway, i) in varGwConfigSecondaryLocation: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && (parVirtualNetworkGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resGatewaySecondaryLocation[i] + name: parVirtualNetworkGatewayLock.?name ?? '${resGatewaySecondaryLocation[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkGatewayLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkGatewayLock.?notes + } } -}] +] resource resAzureFirewallSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabled) { parent: resHubVnet @@ -1531,12 +1535,18 @@ resource resAzureFirewallSubnetRefSecondaryLocation 'Microsoft.Network/virtualNe name: 'AzureFirewallSubnet' } -resource resAzureFirewallMgmtSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabled && (contains(map(parSubnets, subnets => subnets.name), 'AzureFirewallManagementSubnet'))) { +resource resAzureFirewallMgmtSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabled && (contains( + map(parSubnets, subnets => subnets.name), + 'AzureFirewallManagementSubnet' +))) { parent: resHubVnet name: 'AzureFirewallManagementSubnet' } -resource resAzureFirewallMgmtSubnetRefSecondaryLocation 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabledSecondaryLocation && (contains(map(parSubnetsSecondaryLocation, subnets => subnets.name), 'AzureFirewallManagementSubnet'))) { +resource resAzureFirewallMgmtSubnetRefSecondaryLocation 'Microsoft.Network/virtualNetworks/subnets@2024-01-01' existing = if (parAzFirewallEnabledSecondaryLocation && (contains( + map(parSubnetsSecondaryLocation, subnets => subnets.name), + 'AzureFirewallManagementSubnet' +))) { parent: resHubVnetSecondaryLocation name: 'AzureFirewallManagementSubnet' } @@ -1579,7 +1589,10 @@ module modAzureFirewallPublicIpSecondaryLocation '../publicIp/publicIp.bicep' = } } -module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFirewallEnabled && (contains(map(parSubnets, subnets => subnets.name), 'AzureFirewallManagementSubnet'))) { +module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFirewallEnabled && (contains( + map(parSubnets, subnets => subnets.name), + 'AzureFirewallManagementSubnet' +))) { name: 'deploy-Firewall-mgmt-Public-IP' params: { parLocation: parLocation @@ -1598,7 +1611,10 @@ module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFire } } -module modAzureFirewallMgmtPublicIpSecondaryLocation '../publicIp/publicIp.bicep' = if (parAzFirewallEnabledSecondaryLocation && (contains(map(parSubnetsSecondaryLocation, subnets => subnets.name), 'AzureFirewallManagementSubnet'))) { +module modAzureFirewallMgmtPublicIpSecondaryLocation '../publicIp/publicIp.bicep' = if (parAzFirewallEnabledSecondaryLocation && (contains( + map(parSubnetsSecondaryLocation, subnets => subnets.name), + 'AzureFirewallManagementSubnet' +))) { name: 'deploy-Firewall-mgmt-Public-IP-Secondary-Location' params: { parLocation: parSecondaryLocation @@ -1621,54 +1637,58 @@ resource resFirewallPolicies 'Microsoft.Network/firewallPolicies@2024-01-01' = i name: parAzFirewallPoliciesName location: parLocation tags: parTags - properties: (parAzFirewallTier == 'Basic') ? { - sku: { - tier: parAzFirewallTier - } - snat: !empty(parAzFirewallPoliciesPrivateRanges) + properties: (parAzFirewallTier == 'Basic') ? { - autoLearnPrivateRanges: parAzFirewallPoliciesAutoLearn - privateRanges: parAzFirewallPoliciesPrivateRanges + sku: { + tier: parAzFirewallTier + } + snat: !empty(parAzFirewallPoliciesPrivateRanges) + ? { + autoLearnPrivateRanges: parAzFirewallPoliciesAutoLearn + privateRanges: parAzFirewallPoliciesPrivateRanges + } + : null + threatIntelMode: 'Alert' + } + : { + dnsSettings: { + enableProxy: parAzFirewallDnsProxyEnabled + servers: parAzFirewallDnsServers + } + sku: { + tier: parAzFirewallTier + } + threatIntelMode: parAzFirewallIntelMode } - : null - threatIntelMode: 'Alert' - } : { - dnsSettings: { - enableProxy: parAzFirewallDnsProxyEnabled - servers: parAzFirewallDnsServers - } - sku: { - tier: parAzFirewallTier - } - threatIntelMode: parAzFirewallIntelMode - } } resource resFirewallPoliciesSecondaryLocation 'Microsoft.Network/firewallPolicies@2024-01-01' = if (parAzFirewallEnabledSecondaryLocation && parAzFirewallPoliciesEnabledSecondaryLocation) { name: parAzFirewallPoliciesNameSecondaryLocation location: parSecondaryLocation tags: parTags - properties: (parAzFirewallTierSecondaryLocation == 'Basic') ? { - sku: { - tier: parAzFirewallTierSecondaryLocation - } - snat: !empty(parAzFirewallPoliciesPrivateRangesSecondaryLocation) + properties: (parAzFirewallTierSecondaryLocation == 'Basic') ? { - autoLearnPrivateRanges: parAzFirewallPoliciesAutoLearnSecondaryLocation - privateRanges: parAzFirewallPoliciesPrivateRangesSecondaryLocation + sku: { + tier: parAzFirewallTierSecondaryLocation + } + snat: !empty(parAzFirewallPoliciesPrivateRangesSecondaryLocation) + ? { + autoLearnPrivateRanges: parAzFirewallPoliciesAutoLearnSecondaryLocation + privateRanges: parAzFirewallPoliciesPrivateRangesSecondaryLocation + } + : null + threatIntelMode: 'Alert' + } + : { + dnsSettings: { + enableProxy: parAzFirewallDnsProxyEnabledSecondaryLocation + servers: parAzFirewallDnsServersSecondaryLocation + } + sku: { + tier: parAzFirewallTierSecondaryLocation + } + threatIntelMode: parAzFirewallIntelModeSecondaryLocation } - : null - threatIntelMode: 'Alert' - } : { - dnsSettings: { - enableProxy: parAzFirewallDnsProxyEnabledSecondaryLocation - servers: parAzFirewallDnsServersSecondaryLocation - } - sku: { - tier: parAzFirewallTierSecondaryLocation - } - threatIntelMode: parAzFirewallIntelModeSecondaryLocation - } } // Create Azure Firewall Policy resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' @@ -1701,98 +1721,98 @@ resource resAzureFirewall 'Microsoft.Network/azureFirewalls@2024-01-01' = if (pa location: parLocation tags: parTags zones: (!empty(parAzFirewallAvailabilityZones) ? parAzFirewallAvailabilityZones : []) - properties: parAzFirewallTier == 'Basic' ? { - ipConfigurations: varAzFirewallUseCustomPublicIps - ? map(parAzFirewallCustomPublicIps, ip => - { - name: 'ipconfig${uniqueString(ip)}' - properties: ip == parAzFirewallCustomPublicIps[0] - ? { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } - } - : { - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } - } - }) - : [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' + properties: parAzFirewallTier == 'Basic' + ? { + ipConfigurations: varAzFirewallUseCustomPublicIps + ? map(parAzFirewallCustomPublicIps, ip => { + name: 'ipconfig${uniqueString(ip)}' + properties: ip == parAzFirewallCustomPublicIps[0] + ? { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + : { + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + }) + : [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' + } + } + } + ] + managementIpConfiguration: { + name: 'mgmtIpConfig' + properties: { + publicIPAddress: { + id: parAzFirewallEnabled ? modAzureFirewallMgmtPublicIp.outputs.outPublicIpId : '' + } + subnet: { + id: resAzureFirewallMgmtSubnetRef.id + } } } - } - ] - managementIpConfiguration: { - name: 'mgmtIpConfig' - properties: { - publicIPAddress: { - id: parAzFirewallEnabled ? modAzureFirewallMgmtPublicIp.outputs.outPublicIpId : '' + sku: { + name: 'AZFW_VNet' + tier: parAzFirewallTier } - subnet: { - id: resAzureFirewallMgmtSubnetRef.id + firewallPolicy: { + id: resFirewallPolicies.id } } - } - sku: { - name: 'AZFW_VNet' - tier: parAzFirewallTier - } - firewallPolicy: { - id: resFirewallPolicies.id - } - } : { - ipConfigurations: varAzFirewallUseCustomPublicIps - ? map(parAzFirewallCustomPublicIps, ip => - { - name: 'ipconfig${uniqueString(ip)}' - properties: ip == parAzFirewallCustomPublicIps[0] - ? { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } + : { + ipConfigurations: varAzFirewallUseCustomPublicIps + ? map(parAzFirewallCustomPublicIps, ip => { + name: 'ipconfig${uniqueString(ip)}' + properties: ip == parAzFirewallCustomPublicIps[0] + ? { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + : { + publicIPAddress: { + id: parAzFirewallEnabled ? ip : '' + } + } + }) + : [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: resAzureFirewallSubnetRef.id + } + publicIPAddress: { + id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' + } + } + } + ] + sku: { + name: 'AZFW_VNet' + tier: parAzFirewallTier } - : { - publicIPAddress: { - id: parAzFirewallEnabled ? ip : '' - } - } - }) - : [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: resAzureFirewallSubnetRef.id - } - publicIPAddress: { - id: parAzFirewallEnabled ? modAzureFirewallPublicIp.outputs.outPublicIpId : '' - } + firewallPolicy: { + id: resFirewallPolicies.id } } - ] - sku: { - name: 'AZFW_VNet' - tier: parAzFirewallTier - } - firewallPolicy: { - id: resFirewallPolicies.id - } - } } // AzureFirewallSubnet is required to deploy Azure Firewall . This subnet must exist in the parsubnets array if you deploy. @@ -1805,98 +1825,104 @@ resource resAzureFirewallSecondaryLocation 'Microsoft.Network/azureFirewalls@202 location: parSecondaryLocation tags: parTags zones: (!empty(parAzFirewallAvailabilityZonesSecondaryLocation) ? parAzFirewallAvailabilityZonesSecondaryLocation : []) - properties: parAzFirewallTierSecondaryLocation == 'Basic' ? { - ipConfigurations: varAzFirewallUseCustomPublicIpsSecondaryLocation - ? map(parAzFirewallCustomPublicIpsSecondaryLocation, ip => - { - name: 'ipconfig${uniqueString(ip)}' - properties: ip == parAzFirewallCustomPublicIpsSecondaryLocation[0] - ? { - subnet: { - id: resAzureFirewallSubnetRefSecondaryLocation.id - } - publicIPAddress: { - id: parAzFirewallEnabledSecondaryLocation ? ip : '' + properties: parAzFirewallTierSecondaryLocation == 'Basic' + ? { + ipConfigurations: varAzFirewallUseCustomPublicIpsSecondaryLocation + ? map(parAzFirewallCustomPublicIpsSecondaryLocation, ip => { + name: 'ipconfig${uniqueString(ip)}' + properties: ip == parAzFirewallCustomPublicIpsSecondaryLocation[0] + ? { + subnet: { + id: resAzureFirewallSubnetRefSecondaryLocation.id + } + publicIPAddress: { + id: parAzFirewallEnabledSecondaryLocation ? ip : '' + } + } + : { + publicIPAddress: { + id: parAzFirewallEnabledSecondaryLocation ? ip : '' + } + } + }) + : [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: resAzureFirewallSubnetRefSecondaryLocation.id + } + publicIPAddress: { + id: parAzFirewallEnabledSecondaryLocation + ? modAzureFirewallPublicIpSecondaryLocation.outputs.outPublicIpId + : '' + } + } + } + ] + managementIpConfiguration: { + name: 'mgmtIpConfig' + properties: { + publicIPAddress: { + id: parAzFirewallEnabledSecondaryLocation + ? modAzureFirewallMgmtPublicIpSecondaryLocation.outputs.outPublicIpId + : '' + } + subnet: { + id: resAzureFirewallMgmtSubnetRefSecondaryLocation.id + } } } - : { - publicIPAddress: { - id: parAzFirewallEnabledSecondaryLocation ? ip : '' - } + sku: { + name: 'AZFW_VNet' + tier: parAzFirewallTierSecondaryLocation } - }) - : [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: resAzureFirewallSubnetRefSecondaryLocation.id - } - publicIPAddress: { - id: parAzFirewallEnabledSecondaryLocation ? modAzureFirewallPublicIpSecondaryLocation.outputs.outPublicIpId : '' - } + firewallPolicy: { + id: resFirewallPoliciesSecondaryLocation.id } } - ] - managementIpConfiguration: { - name: 'mgmtIpConfig' - properties: { - publicIPAddress: { - id: parAzFirewallEnabledSecondaryLocation ? modAzureFirewallMgmtPublicIpSecondaryLocation.outputs.outPublicIpId : '' + : { + ipConfigurations: varAzFirewallUseCustomPublicIpsSecondaryLocation + ? map(parAzFirewallCustomPublicIpsSecondaryLocation, ip => { + name: 'ipconfig${uniqueString(ip)}' + properties: ip == parAzFirewallCustomPublicIpsSecondaryLocation[0] + ? { + subnet: { + id: resAzureFirewallSubnetRefSecondaryLocation.id + } + publicIPAddress: { + id: parAzFirewallEnabledSecondaryLocation ? ip : '' + } + } + : { + publicIPAddress: { + id: parAzFirewallEnabledSecondaryLocation ? ip : '' + } + } + }) + : [ + { + name: 'ipconfig1' + properties: { + subnet: { + id: resAzureFirewallSubnetRefSecondaryLocation.id + } + publicIPAddress: { + id: parAzFirewallEnabledSecondaryLocation + ? modAzureFirewallPublicIpSecondaryLocation.outputs.outPublicIpId + : '' + } + } + } + ] + sku: { + name: 'AZFW_VNet' + tier: parAzFirewallTierSecondaryLocation } - subnet: { - id: resAzureFirewallMgmtSubnetRefSecondaryLocation.id + firewallPolicy: { + id: resFirewallPoliciesSecondaryLocation.id } } - } - sku: { - name: 'AZFW_VNet' - tier: parAzFirewallTierSecondaryLocation - } - firewallPolicy: { - id: resFirewallPoliciesSecondaryLocation.id - } - } : { - ipConfigurations: varAzFirewallUseCustomPublicIpsSecondaryLocation - ? map(parAzFirewallCustomPublicIpsSecondaryLocation, ip => - { - name: 'ipconfig${uniqueString(ip)}' - properties: ip == parAzFirewallCustomPublicIpsSecondaryLocation[0] - ? { - subnet: { - id: resAzureFirewallSubnetRefSecondaryLocation.id - } - publicIPAddress: { - id: parAzFirewallEnabledSecondaryLocation ? ip : '' - } - } - : { - publicIPAddress: { - id: parAzFirewallEnabledSecondaryLocation ? ip : '' - } - } - }) - : [ - { - name: 'ipconfig1' - properties: { - subnet: { - id: resAzureFirewallSubnetRefSecondaryLocation.id - } - publicIPAddress: { - id: parAzFirewallEnabledSecondaryLocation ? modAzureFirewallPublicIpSecondaryLocation.outputs.outPublicIpId : '' - } - } - } - ] - sku: { - name: 'AZFW_VNet' - tier: parAzFirewallTierSecondaryLocation - } - firewallPolicy: { - id: resFirewallPoliciesSecondaryLocation.id - } - } } // Create Azure Firewall resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' @@ -1931,7 +1957,9 @@ resource resHubRouteTable 'Microsoft.Network/routeTables@2024-01-01' = if (parAz properties: { addressPrefix: '0.0.0.0/0' nextHopType: 'VirtualAppliance' - nextHopIpAddress: parAzFirewallEnabled ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : '' + nextHopIpAddress: parAzFirewallEnabled + ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + : '' } } ] @@ -1951,7 +1979,9 @@ resource resHubRouteTableSecondaryLocation 'Microsoft.Network/routeTables@2024-0 properties: { addressPrefix: '0.0.0.0/0' nextHopType: 'VirtualAppliance' - nextHopIpAddress: parAzFirewallEnabledSecondaryLocation ? resAzureFirewallSecondaryLocation.properties.ipConfigurations[0].properties.privateIPAddress : '' + nextHopIpAddress: parAzFirewallEnabledSecondaryLocation + ? resAzureFirewallSecondaryLocation.properties.ipConfigurations[0].properties.privateIPAddress + : '' } } ] @@ -1979,21 +2009,49 @@ resource resHubRouteTableLockSecondaryLocation 'Microsoft.Authorization/locks@20 } } -module modPrivateDnsZones '../privateDnsZones/privateDnsZones.bicep' = if (parPrivateDnsZonesEnabled) { - name: 'deploy-Private-DNS-Zones' +module modPrivateDnsZonesAVMRegion1 'br/public:avm/ptn/network/private-link-private-dns-zones:0.2.1' = if (parPrivateDnsZonesEnabled) { + name: 'deploy-Private-DNS-Zones-AVM-${parLocation}' scope: resourceGroup(parPrivateDnsZonesResourceGroup) params: { - parLocation: parLocation - parTags: parTags - parVirtualNetworkIdToLink: resHubVnet.id - parVirtualNetworkIdToLinkFailover: parVirtualNetworkIdToLinkFailover - parPrivateDnsZones: parPrivateDnsZones - parPrivateDnsZoneAutoMergeAzureBackupZone: parPrivateDnsZoneAutoMergeAzureBackupZone - parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parPrivateDNSZonesLock - parTelemetryOptOut: parTelemetryOptOut + location: parLocation + privateLinkPrivateDnsZones: empty(parPrivateDnsZones) ? null : parPrivateDnsZones + virtualNetworkResourceIdsToLinkTo: union( + [resHubVnet.id, resHubVnetSecondaryLocation.id], + !empty(parVirtualNetworkIdToLinkFailover) ? [parVirtualNetworkIdToLinkFailover] : [], + parVirtualNetworkResourceIdsToLinkTo + ) + enableTelemetry: parTelemetryOptOut ? false : true + tags: parTags + lock: { + name: parPrivateDNSZonesLock.?name ?? 'pl-pdns-zone-lock' + kind: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parPrivateDNSZonesLock.kind + } } } +module modPrivateDnsZonesAVMRegion2 'br/public:avm/ptn/network/private-link-private-dns-zones:0.2.1' = if (parPrivateDnsZonesEnabled) { + name: 'deploy-Private-DNS-Zones-AVM-Multi-${parSecondaryLocation}' + scope: resourceGroup(parPrivateDnsZonesResourceGroup) + params: { + location: parSecondaryLocation + privateLinkPrivateDnsZones: empty(parPrivateDnsZones) ? null : parPrivateDnsZones + virtualNetworkResourceIdsToLinkTo: union( + [resHubVnet.id, resHubVnetSecondaryLocation.id], + !empty(parVirtualNetworkIdToLinkFailover) ? [parVirtualNetworkIdToLinkFailover] : [], + parVirtualNetworkResourceIdsToLinkTo + ) + enableTelemetry: parTelemetryOptOut ? false : true + tags: parTags + lock: { + name: parPrivateDNSZonesLock.?name ?? 'pl-pdns-zone-lock' + kind: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parPrivateDNSZonesLock.kind + } + } + dependsOn: [ + modPrivateDnsZonesAVMRegion1 + ] +} + // Optional Deployments for Customer Usage Attribution module modCustomerUsageAttribution '../../CRML/customerUsageAttribution/cuaIdResourceGroup.bicep' = if (!parTelemetryOptOut) { #disable-next-line no-loc-expr-outside-params //Only to ensure telemetry data is stored in same location as deployment. See https://github.com/Azure/ALZ-Bicep/wiki/FAQ#why-are-some-linter-rules-disabled-via-the-disable-next-line-bicep-function for more information @@ -2008,16 +2066,34 @@ module modCustomerUsageAttributionZtnP1 '../../CRML/customerUsageAttribution/cua } //If Azure Firewall is enabled we will deploy a RouteTable to redirect Traffic to the Firewall. -output outAzFirewallPrivateIp string = parAzFirewallEnabled ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress : '' -output outAzFirewallPrivateIpSecondaryLocation string = parAzFirewallEnabledSecondaryLocation ? resAzureFirewallSecondaryLocation.properties.ipConfigurations[0].properties.privateIPAddress : '' - +output outAzFirewallPrivateIp string = parAzFirewallEnabled + ? resAzureFirewall.properties.ipConfigurations[0].properties.privateIPAddress + : '' +output outAzFirewallPrivateIpSecondaryLocation string = parAzFirewallEnabledSecondaryLocation + ? resAzureFirewallSecondaryLocation.properties.ipConfigurations[0].properties.privateIPAddress + : '' //If Azure Firewall is enabled we will deploy a RouteTable to redirect Traffic to the Firewall. output outAzFirewallName string = parAzFirewallEnabled ? parAzFirewallName : '' -output outAzFirewallNameSecondaryLocation string = parAzFirewallEnabledSecondaryLocation ? parAzFirewallNameSecondaryLocation : '' - -output outPrivateDnsZones array = (parPrivateDnsZonesEnabled ? modPrivateDnsZones.outputs.outPrivateDnsZones : []) -output outPrivateDnsZonesNames array = (parPrivateDnsZonesEnabled ? modPrivateDnsZones.outputs.outPrivateDnsZonesNames : []) +output outAzFirewallNameSecondaryLocation string = parAzFirewallEnabledSecondaryLocation + ? parAzFirewallNameSecondaryLocation + : '' + +output outPrivateDnsZones array = (parPrivateDnsZonesEnabled + ? union( + modPrivateDnsZonesAVMRegion1.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink, + modPrivateDnsZonesAVMRegion2.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink + ) + : []) +output outPrivateDnsZonesNames array = (parPrivateDnsZonesEnabled + ? map( + union( + modPrivateDnsZonesAVMRegion1.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink, + modPrivateDnsZonesAVMRegion2.outputs.combinedPrivateLinkPrivateDnsZonesReplacedWithVnetsToLink + ), + zone => zone.pdnsZoneName + ) + : []) output outDdosPlanResourceId string = resDdosProtectionPlan.id output outDdosPlanResourceIdSecondaryLocation string = resDdosProtectionPlanSecondaryLocation.id @@ -2029,14 +2105,21 @@ output outHubVirtualNetworkId string = resHubVnet.id output outHubVirtualNetworkIdSecondaryLocation string = resHubVnetSecondaryLocation.id output outHubRouteTableId string = parAzFirewallEnabled ? resHubRouteTable.id : '' -output outHubRouteTableIdSecondaryLocation string = parAzFirewallEnabledSecondaryLocation ? resHubRouteTableSecondaryLocation.id : '' +output outHubRouteTableIdSecondaryLocation string = parAzFirewallEnabledSecondaryLocation + ? resHubRouteTableSecondaryLocation.id + : '' output outHubRouteTableName string = parAzFirewallEnabled ? resHubRouteTable.name : '' -output outHubRouteTableNameSecondaryLocation string = parAzFirewallEnabledSecondaryLocation ? resHubRouteTableSecondaryLocation.name : '' +output outHubRouteTableNameSecondaryLocation string = parAzFirewallEnabledSecondaryLocation + ? resHubRouteTableSecondaryLocation.name + : '' output outBastionNsgId string = parAzBastionEnabled ? resBastionNsg.id : '' -output outBastionNsgIdSecondaryLocation string = parAzBastionEnabledSecondaryLocation ? resBastionNsgSecondaryLocation.id : '' +output outBastionNsgIdSecondaryLocation string = parAzBastionEnabledSecondaryLocation + ? resBastionNsgSecondaryLocation.id + : '' output outBastionNsgName string = parAzBastionEnabled ? resBastionNsg.name : '' -output outBastionNsgNameSecondaryLocation string = parAzBastionEnabledSecondaryLocation ? resBastionNsgSecondaryLocation.name : '' - +output outBastionNsgNameSecondaryLocation string = parAzBastionEnabledSecondaryLocation + ? resBastionNsgSecondaryLocation.name + : '' diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index 1171e2791..13d5016da 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -259,7 +259,7 @@ param parPrivateDnsZonesEnabled bool = true @sys.description('Resource Group Name for Private DNS Zones.') param parPrivateDnsZonesResourceGroup string = resourceGroup().name -@sys.description('Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones') +@sys.description('Array of DNS Zones to provision and link to Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones') param parPrivateDnsZones array = [] @sys.description('Resource ID of Failover VNet for Private DNS Zone VNet Failover Links') From 65c158a1159bd4746f255cfa230186c7466dcdc8 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:01:56 +0000 Subject: [PATCH 08/14] add rel notes draft --- releaseNoteDraft.md | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 releaseNoteDraft.md diff --git a/releaseNoteDraft.md b/releaseNoteDraft.md new file mode 100644 index 000000000..531a29c8d --- /dev/null +++ b/releaseNoteDraft.md @@ -0,0 +1,48 @@ +ALZ Bicep Release Notes: + +The local private DNS zones modules (`privateDnsZones.bicep`) has been replaced in the networking related modules in this repo with the AVM Pattern module of [`avm/ptn/network/private-link-private-dns-zones`](https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones) to resolve bug #695. + +This has meant some breaking changes to each of the networking modules that are detailed below. + +#### `hubNetworking.bicep` & `hubNetworking-multiRegion.bicep` + +- `parPrivateDnsZones` default value changed to an empty array (`[]`) + - Only enter values in here if you want to override the defaults in the underlying AVM pattern module. See: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones +- `parPrivateDnsZoneAutoMergeAzureBackupZone` removed from module +- `parVirtualNetworkResourceIdsToLinkTo` added to module +- The value returned in `outPrivateDnsZones` has changed + +**From:** + +``` +[ + { + "name": "privatelink.api.azureml.ms", + "id": "/subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.api.azureml.ms" + }, + { + "name": "privatelink.notebooks.azure.net", + "id": "subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.notebooks.azure.net" + }, + … +] +``` + +**To:** +``` +[ + { + "pdnsZoneName": "privatelink.api.azureml.ms", + "virtualNetworkResourceIdsToLinkTo": [ + "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" + ] + }, + { + "pdnsZoneName": "privatelink.notebooks.azure.net", + "virtualNetworkResourceIdsToLinkTo": [ + "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" + ] + }, + … +] +``` From 853949897535610e6840bb5503ba4550a0d20945 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:40:03 +0000 Subject: [PATCH 09/14] remove pdns module --- .../bicep/modules/privateDnsZones/README.md | 174 +----------- .../modules/privateDnsZones/bicepconfig.json | 124 -------- .../generateddocs/privateDnsZones.bicep.md | 197 ------------- .../privateDnsZones/media/bicepVisualizer.png | Bin 69089 -> 0 bytes .../media/exampleDeploymentOutput.png | Bin 164350 -> 0 bytes .../mc-privateDnsZones.parameters.all.json | 56 ---- .../mc-privateDnsZones.parameters.min.json | 48 ---- .../privateDnsZones.parameters.all.json | 98 ------- .../privateDnsZones.parameters.min.json | 84 ------ .../privateDnsZones/privateDnsZones.bicep | 264 ------------------ .../samples/baseline.sample.bicep | 96 ------- .../generateddocs/baseline.sample.bicep.md | 34 --- .../generateddocs/minimum.sample.bicep.md | 34 --- .../samples/minimum.sample.bicep | 24 -- .../vwanConnectivity/vwanConnectivity.bicep | 113 ++------ releaseNoteDraft.md | 44 ++- 16 files changed, 69 insertions(+), 1321 deletions(-) delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/bicepconfig.json delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/media/bicepVisualizer.png delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/media/exampleDeploymentOutput.png delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/parameters/mc-privateDnsZones.parameters.all.json delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/parameters/mc-privateDnsZones.parameters.min.json delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/parameters/privateDnsZones.parameters.all.json delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/parameters/privateDnsZones.parameters.min.json delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/samples/baseline.sample.bicep delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/samples/generateddocs/baseline.sample.bicep.md delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/samples/generateddocs/minimum.sample.bicep.md delete mode 100644 infra-as-code/bicep/modules/privateDnsZones/samples/minimum.sample.bicep diff --git a/infra-as-code/bicep/modules/privateDnsZones/README.md b/infra-as-code/bicep/modules/privateDnsZones/README.md index 7b0cabc2c..012d0507f 100644 --- a/infra-as-code/bicep/modules/privateDnsZones/README.md +++ b/infra-as-code/bicep/modules/privateDnsZones/README.md @@ -1,174 +1,4 @@ # Module: Private DNS Zones -This module deploys Private DNS Zones used for Private Link based on the recommendations from the Azure Landing Zone Conceptual Architecture. - -Module deploys the following resources: - -- Private DNS Zones - See [DNS Zones](#dns-zones) for more info -- Private DNS Zone Links - Links deployed zones with provided Hub Network - -## Parameters - -- [Parameters for Azure Commercial Cloud](generateddocs/privateDnsZones.bicep.md) - -> **NOTE:** Although there are generated parameter markdowns for Azure Commercial Cloud, this same module can still be used in Azure China. Example parameter are in the [parameters](./parameters/) folder. - -## DNS Zones - -### Regional Zones - -The following DNS Zones are region specific and will be deployed with the provided region in the `parLocation` parameter by default: - -- `privatelink.xxxxxx.batch.azure.com` -- `privatelink.xxxxxx.azmk8s.io` -- `privatelink.xxxxxx.kusto.windows.net` - -**Note:** The region specific zones are included in the parameters files with the region set as `xxxxxx`. For these zones to deploy properly, replace `xxxxxx` with the target region. For example: `privatelink.xxxxxx.azmk8s.io` would become `privatelink.eastus.azmk8s.io` for a deployment targeting the East US region. - -### Geo Code Zones - -The following DNS Zone use a geo code associated to the Azure Region. - -- `privatelink.xxx.backup.windowsazure.com` - -If the Azure Region entered in `parLocation` matches a lookup to the map in `varAzBackupGeoCodes` we will append Geo Codes (value) used to generate region-specific DNS zone names for Azure Backup private endpoints. then insert Azure Backup Private DNS Zone with appropriate geo code inserted alongside zones in `parPrivateDnsZones` into a new array called `varPrivateDnsZonesMerge`. If not just return `parPrivateDnsZones` as the only values in `varPrivateDnsZonesMerge`. To override this see the parameter `parPrivateDnsZoneAutoMergeAzureBackupZone`. - -> For more information on Azure Backup and Private Link, or geo codes, please refer to: [Create and use private endpoints for Azure Backup](https://learn.microsoft.com/azure/backup/private-endpoints#when-using-custom-dns-server-or-host-files) - -### Prefixed DNS Zone - -The DNS Zone `privatelink.{dnsPrefix}.database.windows.net` is not deployed by default as the DNS Prefix is individual. - -You can add the zone to your parameters file with the required DNS Prefix in the zone name. - -### All Zones and more details - -For more details on private DNS Zones please refer to this link: -[https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-dns#azure-services-dns-zone-configuration](https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-dns#azure-services-dns-zone-configuration) - -## Outputs - -The module will generate the following outputs: - -| Output | Type | Example | -| ------------------ | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| outPrivateDnsZones | array | `[{"name":"privatelink.azurecr.io","id":"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/net-lz-spk-eastus-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurecr.io"},{"name":"privatelink.azurewebsites.net","id":"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/net-lz-spk-eastus-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurewebsites.net"}]` | -| outPrivateDnsZonesNames | array | `["privatelink.azurecr.io", "privatelink.azurewebsites.net"]` | - -## Deployment -> **Note:** `bicepconfig.json` file is included in the module directory. This file allows us to override Bicep Linters. Currently there are two URLs which were removed because of linter warnings. URLs removed are the following: database.windows.net and core.windows.net - -In this example, the hub resources will be deployed to the resource group specified. According to the Azure Landing Zone Conceptual Architecture, the hub resources should be deployed into the Platform connectivity subscription. During the deployment step, we will take the default values and not pass any parameters. - -There are two different sets of input parameters; one for deploying to Azure global regions, and another for deploying specifically to Azure China regions. This is due to different private DNS zone names for Azure services in Azure global regions and Azure China. The recommended private DNS zone names are available [here](https://learn.microsoft.com/azure/private-link/private-endpoint-dns). Other differences in Azure China regions are as follow: -- DDoS Protection feature is not available. parDdosEnabled parameter is set as false. -- The SKUs available for an ExpressRoute virtual network gateway are Standard, HighPerformance and UltraPerformance. Sku is set as "Standard" in the example parameters file. - - | Azure Cloud | Bicep template | Input parameters file | - | -------------- | --------------------- | ------------------------------------------ | - | Global regions | privateDnsZones.bicep | parameters/privateDnsZones.parameters.all.json | - | China regions | privateDnsZones.bicep | parameters/mc-privateDnsZones.parameters.all.json | - -> For the examples below we assume you have downloaded or cloned the Git repo as-is and are in the root of the repository as your selected directory in your terminal of choice. - -### Azure CLI - -```bash -# For Azure global regions -# Set Platform connectivity subscription ID as the the current subscription -ConnectivitySubscriptionId="[your platform connectivity subscription ID]" -az account set --subscription $ConnectivitySubscriptionId - -# Set the top level MG Prefix in accordance to your environment. This example assumes default 'alz'. -TopLevelMGPrefix="alz" - -dateYMD=$(date +%Y%m%dT%H%M%S%NZ) -NAME="alz-PrivateDnsZonesDeployment-${dateYMD}" -RESOURCEGROUP="rg-$TopLevelMGPrefix-private-dns-001" -TEMPLATEFILE="infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep" -PARAMETERS="@infra-as-code/bicep/modules/privateDnsZones/parameters/privateDnsZones.parameters.all.json" - -az group create --location eastus \ - --name $RESOURCEGROUP - -az deployment group create --name ${NAME:0:63} --resource-group $RESOURCEGROUP --parameters $PARAMETERS --template-file $TEMPLATEFILE -``` -OR -```bash -# For Azure China regions -# Set Platform connectivity subscription ID as the the current subscription -ConnectivitySubscriptionId="[your platform connectivity subscription ID]" -az account set --subscription $ConnectivitySubscriptionId - -# Set the top level MG Prefix in accordance to your environment. This example assumes default 'alz'. -TopLevelMGPrefix="alz" - -dateYMD=$(date +%Y%m%dT%H%M%S%NZ) -NAME="alz-PrivateDnsZonesDeployment-${dateYMD}" -RESOURCEGROUP="rg-$TopLevelMGPrefix-private-dns-001" -TEMPLATEFILE="infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep" -PARAMETERS="@infra-as-code/bicep/modules/privateDnsZones/parameters/privateDnsZones.parameters.all.json" - -az group create --location chinaeast2 \ - --name $RESOURCEGROUP - -az deployment group create --name ${NAME:0:63} --resource-group $RESOURCEGROUP --parameters $PARAMETERS --template-file $TEMPLATEFILE -``` - -### PowerShell - -```powershell -# For Azure global regions -# Set Platform connectivity subscription ID as the the current subscription -$ConnectivitySubscriptionId = "[your platform connectivity subscription ID]" - -Select-AzSubscription -SubscriptionId $ConnectivitySubscriptionId - -# Set the top level MG Prefix in accordance to your environment. This example assumes default 'alz'. -$TopLevelMGPrefix = "alz" - -New-AzResourceGroup ` - -Name $inputObject.ResourceGroupName ` - -Location 'eastus' - -$inputObject = @{ - DeploymentName = -join ('alz-PrivateDnsZonesDeploy-{0}' -f (Get-Date -Format 'yyyyMMddTHHMMssffffZ'))[0..63] - ResourceGroupName = "rg-$TopLevelMGPrefix-private-dns-001" - TemplateFile = "infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep" - TemplateParameterFile = "infra-as-code/bicep/modules/privateDnsZones/parameters/privateDnsZones.parameters.all.json" -} - -New-AzResourceGroupDeployment @inputObject -``` -OR - -```powershell -# For Azure China regions -# Set Platform connectivity subscription ID as the the current subscription -$ConnectivitySubscriptionId = "[your platform connectivity subscription ID]" - -Select-AzSubscription -SubscriptionId $ConnectivitySubscriptionId - -# Set the top level MG Prefix in accordance to your environment. This example assumes default 'alz'. -$TopLevelMGPrefix = "alz" - -New-AzResourceGroup ` - -Name $inputObject.ResourceGroupName ` - -Location 'chinaeast2' - -$inputObject = @{ - DeploymentName = -join ('alz-PrivateDnsZonesDeploy-{0}' -f (Get-Date -Format 'yyyyMMddTHHMMssffffZ'))[0..63] - ResourceGroupName = "rg-$TopLevelMGPrefix-private-dns-001" - TemplateFile = "infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep" - TemplateParameterFile = "infra-as-code/bicep/modules/privateDnsZones/parameters/privateDnsZones.parameters.all.json" -} - -New-AzResourceGroupDeployment @inputObject -``` -## Example Output in Azure global regions - -![Example Deployment Output](media/exampleDeploymentOutput.png "Example Deployment Output in Azure global regions") - -## Bicep Visualizer - -![Bicep Visualizer](media/bicepVisualizer.png "Bicep Visualizer") +> [!IMPORTANT] +> This module has been removed as of `v0.20.0` and replaced with the AVM Pattern Module of [`avm/ptn/network/private-link-private-dns-zones`](https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones). Please use this module going forward. diff --git a/infra-as-code/bicep/modules/privateDnsZones/bicepconfig.json b/infra-as-code/bicep/modules/privateDnsZones/bicepconfig.json deleted file mode 100644 index ad3802e9b..000000000 --- a/infra-as-code/bicep/modules/privateDnsZones/bicepconfig.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "analyzers": { - "core": { - "enabled": true, - "verbose": true, - "rules": { - "adminusername-should-not-be-literal": { - "level": "error" - }, - "artifacts-parameters": { - "level": "error" - }, - "decompiler-cleanup": { - "level": "error" - }, - "max-outputs": { - "level": "error" - }, - "max-params": { - "level": "error" - }, - "max-resources": { - "level": "error" - }, - "max-variables": { - "level": "error" - }, - "no-hardcoded-env-urls": { - "level": "error", - "disallowedhosts": [ - "management.core.windows.net", - "gallery.azure.com", - "management.core.windows.net", - "management.azure.com", - "login.microsoftonline.com", - "graph.windows.net", - "trafficmanager.net", - "vault.azure.net", - "datalake.azure.net", - "azuredatalakestore.net", - "azuredatalakeanalytics.net", - "vault.azure.net", - "api.loganalytics.io", - "api.loganalytics.iov1", - "asazure.windows.net", - "region.asazure.windows.net", - "api.loganalytics.iov1", - "api.loganalytics.io", - "asazure.windows.net", - "region.asazure.windows.net", - "batch.core.windows.net" - ], - "excludedhosts": [ - "schema.management.azure.com" - ] - }, - "no-hardcoded-location": { - "level": "error" - }, - "no-loc-expr-outside-params": { - "level": "error" - }, - "no-unnecessary-dependson": { - "level": "error" - }, - "no-unused-existing-resources": { - "level": "error" - }, - "no-unused-params": { - "level": "error" - }, - "no-unused-vars": { - "level": "error" - }, - "outputs-should-not-contain-secrets": { - "level": "error" - }, - "prefer-interpolation": { - "level": "error" - }, - "prefer-unquoted-property-names": { - "level": "error" - }, - "protect-commandtoexecute-secrets": { - "level": "error" - }, - "secure-parameter-default": { - "level": "error" - }, - "secure-params-in-nested-deploy": { - "level": "error" - }, - "secure-secrets-in-params": { - "level": "error" - }, - "simplify-interpolation": { - "level": "error" - }, - "simplify-json-null": { - "level": "error" - }, - "use-parent-property": { - "level": "error" - }, - "use-recent-api-versions": { - "level": "warning", - "maxAllowedAgeInDays": 730 - }, - "use-resource-id-functions": { - "level": "error" - }, - "use-resource-symbol-reference": { - "level": "error" - }, - "use-stable-resource-identifiers": { - "level": "error" - }, - "use-stable-vm-image": { - "level": "error" - } - } - } - } -} diff --git a/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md b/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md deleted file mode 100644 index c74da478d..000000000 --- a/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md +++ /dev/null @@ -1,197 +0,0 @@ -# ALZ Bicep - Private DNS Zones - -Module used to set up Private DNS Zones in accordance to Azure Landing Zones - -## Parameters - -Parameter name | Required | Description --------------- | -------- | ----------- -parLocation | No | The Azure Region to deploy the resources into. -parPrivateDnsZones | No | Array of custom DNS Zones to provision in Hub Virtual Network. -parPrivateDnsZoneAutoMergeAzureBackupZone | No | Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. -parTags | No | Tags you would like to be applied to all resources in this module. -parVirtualNetworkIdToLink | No | Resource ID of VNet for Private DNS Zone VNet Links. -parVirtualNetworkIdToLinkFailover | No | Resource ID of VNet for Failover Private DNS Zone VNet Links. -parResourceLockConfig | No | Resource Lock Configuration for Private DNS Zones. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. -parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. - -### parLocation - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -The Azure Region to deploy the resources into. - -- Default value: `[resourceGroup().location]` - -### parPrivateDnsZones - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Array of custom DNS Zones to provision in Hub Virtual Network. - -- Default value: `[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))] [format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))] [format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))] privatelink.adf.azure.com privatelink.afs.azure.net privatelink.agentsvc.azure-automation.net privatelink.analysis.windows.net privatelink.api.azureml.ms privatelink.azconfig.io privatelink.azure-api.net privatelink.azure-automation.net privatelink.azurecr.io privatelink.azure-devices.net privatelink.azure-devices-provisioning.net privatelink.azuredatabricks.net privatelink.azurehdinsight.net privatelink.azurehealthcareapis.com privatelink.azurestaticapps.net privatelink.azuresynapse.net privatelink.azurewebsites.net privatelink.batch.azure.com privatelink.blob.core.windows.net privatelink.cassandra.cosmos.azure.com privatelink.cognitiveservices.azure.com privatelink.database.windows.net privatelink.datafactory.azure.net privatelink.dev.azuresynapse.net privatelink.dfs.core.windows.net privatelink.dicom.azurehealthcareapis.com privatelink.digitaltwins.azure.net privatelink.directline.botframework.com privatelink.documents.azure.com privatelink.eventgrid.azure.net privatelink.file.core.windows.net privatelink.gremlin.cosmos.azure.com privatelink.guestconfiguration.azure.com privatelink.his.arc.azure.com privatelink.dp.kubernetesconfiguration.azure.com privatelink.managedhsm.azure.net privatelink.mariadb.database.azure.com privatelink.media.azure.net privatelink.mongo.cosmos.azure.com privatelink.monitor.azure.com privatelink.mysql.database.azure.com privatelink.notebooks.azure.net privatelink.ods.opinsights.azure.com privatelink.oms.opinsights.azure.com privatelink.pbidedicated.windows.net privatelink.postgres.database.azure.com privatelink.prod.migration.windowsazure.com privatelink.purview.azure.com privatelink.purviewstudio.azure.com privatelink.queue.core.windows.net privatelink.redis.cache.windows.net privatelink.redisenterprise.cache.azure.net privatelink.search.windows.net privatelink.service.signalr.net privatelink.servicebus.windows.net privatelink.siterecovery.windowsazure.com privatelink.sql.azuresynapse.net privatelink.table.core.windows.net privatelink.table.cosmos.azure.com privatelink.tip1.powerquery.microsoft.com privatelink.token.botframework.com privatelink.vaultcore.azure.net privatelink.web.core.windows.net privatelink.webpubsub.azure.com` - -### parPrivateDnsZoneAutoMergeAzureBackupZone - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. - -- Default value: `True` - -### parTags - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Tags you would like to be applied to all resources in this module. - -### parVirtualNetworkIdToLink - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Resource ID of VNet for Private DNS Zone VNet Links. - -### parVirtualNetworkIdToLinkFailover - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Resource ID of VNet for Failover Private DNS Zone VNet Links. - -### parResourceLockConfig - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Resource Lock Configuration for Private DNS Zones. - -- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. -- `notes` - Notes about this lock. - - - -- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Private DNS Zones Module.}` - -### parTelemetryOptOut - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Set Parameter to true to Opt-out of deployment telemetry. - -- Default value: `False` - -## Outputs - -Name | Type | Description ----- | ---- | ----------- -outPrivateDnsZones | array | -outPrivateDnsZonesNames | array | - -## Snippets - -### Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "template": "infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.json" - }, - "parameters": { - "parLocation": { - "value": "[resourceGroup().location]" - }, - "parPrivateDnsZones": { - "value": [ - "[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))]", - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] - }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true - }, - "parTags": { - "value": {} - }, - "parVirtualNetworkIdToLink": { - "value": "" - }, - "parVirtualNetworkIdToLinkFailover": { - "value": "" - }, - "parResourceLockConfig": { - "value": { - "kind": "None", - "notes": "This lock was created by the ALZ Bicep Private DNS Zones Module." - } - }, - "parTelemetryOptOut": { - "value": false - } - } -} -``` diff --git a/infra-as-code/bicep/modules/privateDnsZones/media/bicepVisualizer.png b/infra-as-code/bicep/modules/privateDnsZones/media/bicepVisualizer.png deleted file mode 100644 index 37b0d74e4dcfe5328b807bf9737d61d624de0a97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69089 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�n-t zw&ZtKTKi)qOrFETy(cRP-$7e71nQ6b& zs5v=$Hp>6|iKV{)`e@Epb=V>yHS-2Cy7QQb)!?ZbT%H0P5}9em{uYZ_8W%pdPrWJa z@Bd;J0@+^!=4SlZS;^{T&tZqG&eyj`b1nfb2B$m|$hQ3ncqUD3vMWJ5Geog}bay5J zpt15Scwv1HwYD@cbW&3eN>ScZvsR(Q*PI`p64Usnp>3$sr(s`j61Gk0_EC8sp;$1r z3W+=oy8HOlpX-%LQ2i^tlc1izCOISqNJIx7bYf1W5Q|x*@*~_OTZjiVs~J_BIniKI zPJW=hqHdMsBDc_jkFloO^DCJ6y(D}`;3;5R$S+@#sFsOt&o{cLyR9CwxNd%7*%^Pa zG~jk36SI!~ms+m@Qi>xVv+jz1k4}2z9g3(ieXCQRN#vy7I6kH-$6nO{JWnlVi*4Tf z`Y|_xe`=fyj{DvlqE%~viIZo|k$>>)wym2rv+c&s)?cIaEzk}ytvxb6Cj1WpWMINm zzy11UArgpbYg<#KcuB;v-F*AtOHII67Vu#ENed^O**G3>)Qad+HQ^Aphq+`>0&OO6 zXXm?_|SeoPO0m7mv-Tq#GeKW zKDl45M=ODl;_|fw=cZEH?y{`+Ua0mu?MIp$QyR(2KotV&)`hIurwLgaiHe9jB z0CU~)VQgF8kx`V}lb|V^KW_~5wW0jgi!>p=qh9~37m2Wx`L1AO^E*=_t)e_F5Bua9 zGmqvi*tx}8_2cohbCC(pdf#lhMQ!Iy_r%I-&H=H2&A`ib5p#K#KiYe~KIZzSYvk4nbQr@ZD{jg=IKuJBawj z)hXqEYbELLejq6MgIG%Skmj|brwPWBMm}vX$k=AgP~w^>ON=yYO7-&8MxCgD2cdiK z9@iN{r`%#~DxvB;HH#83GcB667MUYv9h$Stp1re$bj__P47UXs%$$_^cZT6gm=ZtvW1Zan0P7^L0I?kHXjPiE2x>6d>9wrg zY^lvWd@D)c=ydzt&CrC_U}T%g0_o`=b$M8Kh7{>G<9pG1*dLSWpJ%3cT|;-@f*)fv-9F6kOQL8XlQmzD>KwqOhG1zAlPe1jOkP5ayV_MCkad)%Arx1s0 zPusE`AT12!$jvq_{qRINKK#S7e;6i)tW1oJ-L+a2E>Nu2ck z30#e%to(mG>P!fXw50sPp0p@qB}A0btLCIai(V_DcsvCZKW#YM#1^|>>8t{3jvg;A zo}MAx8=Kw7EwlxYLS&$hpv7hl89B@(zRhC-)dJS|!TCx0GTX^_8n^psZ?lPSAPw}|{uQvutSF7R}D`zYU10sBGR=&9$ zEGz*iJ<0>aSVntCQGyWX2?{e4k?{<4?Q~<02oy} zXTW%92fREY*SVW0%><$b8&w1aK}rdc zlx~#<2?>z~=@vw~1OeTYAd=GE-3_v75D^iOZV(V9H{A_q-Js8d&w0)n-x=qN_Z{Q+ z4}-n;9c#_C)?9PVdChCuZ7+=yJSZZ18FtEK0Wd(pA6g~I77Tr`2@h7kOR^R^fDF

X2IF%P5 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 U4;Q!R&wzj8BGQktg|*%PFK4!v;s5{u diff --git a/infra-as-code/bicep/modules/privateDnsZones/media/exampleDeploymentOutput.png b/infra-as-code/bicep/modules/privateDnsZones/media/exampleDeploymentOutput.png deleted file mode 100644 index c179093a55337a40e1c709e2b64524d8906bcaf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164350 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

DUHC_u|n1uMPfu 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

Ysot= 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 je50b6aDvnD{6u#ac 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 zone.pdnsZoneName + ) + : []) // Output Azure Firewall Private IP's output outAzFwPrivateIps array = [for (hub, i) in azureFirewallInHubsIndex: { diff --git a/releaseNoteDraft.md b/releaseNoteDraft.md index 531a29c8d..9ba8b4979 100644 --- a/releaseNoteDraft.md +++ b/releaseNoteDraft.md @@ -9,7 +9,49 @@ This has meant some breaking changes to each of the networking modules that are - `parPrivateDnsZones` default value changed to an empty array (`[]`) - Only enter values in here if you want to override the defaults in the underlying AVM pattern module. See: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones - `parPrivateDnsZoneAutoMergeAzureBackupZone` removed from module -- `parVirtualNetworkResourceIdsToLinkTo` added to module +- `parVirtualNetworkResourceIdsToLinkTo` added to module, you can prefer to use this parameter instead of `parVirtualNetworkIdToLink` & `parVirtualNetworkIdToLinkFailover` if you wish (they are automatically all merged together by the module anyway) +- The value returned in `outPrivateDnsZones` has changed + +**From:** + +``` +[ + { + "name": "privatelink.api.azureml.ms", + "id": "/subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.api.azureml.ms" + }, + { + "name": "privatelink.notebooks.azure.net", + "id": "subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.notebooks.azure.net" + }, + … +] +``` + +**To:** +``` +[ + { + "pdnsZoneName": "privatelink.api.azureml.ms", + "virtualNetworkResourceIdsToLinkTo": [ + "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" + ] + }, + { + "pdnsZoneName": "privatelink.notebooks.azure.net", + "virtualNetworkResourceIdsToLinkTo": [ + "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" + ] + }, + … +] +``` + +#### `vwanConnectivity.bicep` + +- `parPrivateDnsZones` default value changed to an empty array (`[]`) + - Only enter values in here if you want to override the defaults in the underlying AVM pattern module. See: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones +- `parVirtualNetworkIdToLink` & `parVirtualNetworkIdToLinkFailover` removed from module and replaced with `parVirtualNetworkResourceIdsToLinkTo` - The value returned in `outPrivateDnsZones` has changed **From:** From fc9ac62e6a48762f9ada4edde0e2741cf01984a4 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:45:01 +0000 Subject: [PATCH 10/14] doc updates --- .../bicep/modules/hubNetworking/README.md | 14 -------------- tests/pipelines/base-unit-validate.yml | 8 -------- tests/pipelines/mc-base-unit-validate.yml | 8 -------- 3 files changed, 30 deletions(-) diff --git a/infra-as-code/bicep/modules/hubNetworking/README.md b/infra-as-code/bicep/modules/hubNetworking/README.md index 0900806ea..0372b946d 100644 --- a/infra-as-code/bicep/modules/hubNetworking/README.md +++ b/infra-as-code/bicep/modules/hubNetworking/README.md @@ -22,20 +22,6 @@ Module deploys the following resources: > - Although there are generated parameter markdowns for Azure Commercial Cloud, this same module can still be used in Azure China. Example parameter are in the [parameters](./parameters/) folder. > > - The file `parameters/hubNetworking.parameters.az.all.json` contains parameter values for SKUs that are compatible with availability zones for relevant resource types. In cases where you are deploying to a region that does not support availability zones, you should opt for the `parameters/hubNetworking.parameters.all.json` file. -> -> - When deploying using the `parameters/hubNetworking.parameters.all.json` you must update the `parPrivateDnsZones` parameter by replacing the `xxxxxx` placeholders with the deployment region or geo code, for Azure Backup. Failure to do so will cause these services to be unreachable over private endpoints. -> -> For example, if deploying to East US the following zone entries: -> - `privatelink.xxxxxx.azmk8s.io` -> - `privatelink.xxxxxx.backup.windowsazure.com` -> - `privatelink.xxxxxx.batch.azure.com` -> -> Will become: -> - `privatelink.eastus.azmk8s.io` -> - `privatelink.eus.backup.windowsazure.com` -> - `privatelink.eastus.batch.azure.com` -> -> See child module, [`privateDnsZones.bicep` docs](https://github.com/Azure/ALZ-Bicep/tree/main/infra-as-code/bicep/modules/privateDnsZones#dns-zones) for more info on how this works To configure P2S VPN connections edit the vpnClientConfiguration value in the `parVpnGatewayConfig` parameter. diff --git a/tests/pipelines/base-unit-validate.yml b/tests/pipelines/base-unit-validate.yml index 207ea6ad7..134e8d8b5 100644 --- a/tests/pipelines/base-unit-validate.yml +++ b/tests/pipelines/base-unit-validate.yml @@ -174,14 +174,6 @@ jobs: script: | az deployment group validate --resource-group $(ResourceGroupName) --template-file infra-as-code/bicep/modules/vnetPeering/vnetPeering.bicep --parameters parDestinationVirtualNetworkId="/subscriptions/$(subscriptionId)/resourceGroups/$(ResourceGroupName)/providers/Microsoft.Network/virtualNetworks/alz-hub-$(Location)" parSourceVirtualNetworkName="vnet-spoke" parDestinationVirtualNetworkName="alz-hub-$(Location)" --name $(ManagementGroupPrefix) - - task: Bash@3 - displayName: Az CLI Validate Private DNS Zones - name: validate_private_dns - inputs: - targetType: "inline" - script: | - az deployment group validate --resource-group $(ResourceGroupName) --template-file infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep --parameters @infra-as-code/bicep/modules/privateDnsZones/parameters/privateDnsZones.parameters.all.json --name $(ManagementGroupPrefix) - - task: Bash@3 displayName: Az CLI Validate Public IP name: validate_public_ip diff --git a/tests/pipelines/mc-base-unit-validate.yml b/tests/pipelines/mc-base-unit-validate.yml index 9a59c8632..5d1c3aae9 100644 --- a/tests/pipelines/mc-base-unit-validate.yml +++ b/tests/pipelines/mc-base-unit-validate.yml @@ -155,14 +155,6 @@ jobs: script: | az deployment group validate --resource-group $(ResourceGroupName) --template-file infra-as-code/bicep/modules/vnetPeering/vnetPeering.bicep --parameters parDestinationVirtualNetworkId="/subscriptions/$(subscriptionId)/resourceGroups/$(ResourceGroupName)/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus" parSourceVirtualNetworkName="vnet-spoke" parDestinationVirtualNetworkName="alz-hub-eastus" --name $(ManagementGroupPrefix) - - task: Bash@3 - displayName: Az CLI Validate Private DNS Zones - name: validate_private_dns - inputs: - targetType: "inline" - script: | - az deployment group validate --resource-group $(ResourceGroupName) --template-file infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep --parameters @infra-as-code/bicep/modules/privateDnsZones/parameters/mc-privateDnsZones.parameters.all.json --name $(ManagementGroupPrefix) - - task: Bash@3 displayName: Az CLI Validate Public IP name: validate_public_ip From d171cecd7b4383bccb096b5ad11aba31c8ff1d59 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:00:08 +0000 Subject: [PATCH 11/14] update params --- docs/wiki/CustomerUsage.md | 1 - .../hubNetworking.parameters.all.json | 74 +---------------- .../hubNetworking.parameters.az.all.json | 74 +---------------- ...working.parameters.az.multiRegion.all.json | 74 +---------------- .../vwanConnectivity.parameters.all.json | 81 +------------------ .../vwanConnectivity.parameters.az.all.json | 81 +------------------ ...ctivity.parameters.az.multiRegion.all.json | 81 +------------------ 7 files changed, 12 insertions(+), 454 deletions(-) diff --git a/docs/wiki/CustomerUsage.md b/docs/wiki/CustomerUsage.md index d65d4c060..80e9b07b1 100644 --- a/docs/wiki/CustomerUsage.md +++ b/docs/wiki/CustomerUsage.md @@ -48,7 +48,6 @@ The following are the unique ID's (also known as PIDs) used in each of the modul | virtualNetworkPeer | ab8e3b12-b0fa-40aa-8630-e3f7699e2142 | | vwanConnectivity | 7f94f23b-7a59-4a5c-9a8d-2a253a566f61 | | vnetPeeringVwan | 7b5e6db2-1e8c-4b01-8eee-e1830073a63d | -| privateDnsZones | 981733dd-3195-4fda-a4ee-605ab959edb6 | | hubSpoke - Orchestration | 50ad3b1a-f72c-4de4-8293-8a6399991beb | | hubPeeredSpoke - Orchestration | 8ea6f19a-d698-4c00-9afb-5c92d4766fd2 | | SubPlacementAll - Orchestration | bb800623-86ff-4ab4-8901-93c2b70967ae | diff --git a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json index 36763ff08..5e93eb89d 100644 --- a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json +++ b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json @@ -115,79 +115,7 @@ "value": true }, "parPrivateDnsZones": { - "value": [ - "privatelink.xxxxxx.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] - }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true + "value": [] }, "parVpnGatewayEnabled": { "value": true diff --git a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json index f1f95bc14..ec30bd6ca 100644 --- a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json +++ b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json @@ -127,79 +127,7 @@ "value": true }, "parPrivateDnsZones": { - "value": [ - "privatelink.xxxxxx.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] - }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true + "value": [] }, "parVpnGatewayEnabled": { "value": true diff --git a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.multiRegion.all.json b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.multiRegion.all.json index 685c833f9..b4ca1f4de 100644 --- a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.multiRegion.all.json +++ b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.multiRegion.all.json @@ -239,79 +239,7 @@ "value": true }, "parPrivateDnsZones": { - "value": [ - "privatelink.xxxxxx.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] - }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true + "value": [] }, "parVpnGatewayEnabled": { "value": true diff --git a/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json b/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json index 9a4519166..c67436e56 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json +++ b/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json @@ -67,91 +67,16 @@ "value": true }, "parPrivateDnsZones": { - "value": [ - "privatelink.xxxxxx.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] + "value": [] }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true - }, - "parVirtualNetworkIdToLink": { - "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus" + "parVirtualNetworkResourceIdsToLinkTo": { + "value": [] }, "parTags": { "value": { "Environment": "Live" } }, - "parVirtualNetworkIdToLinkFailover": { - "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus-failover" - }, "parTelemetryOptOut": { "value": false }, diff --git a/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json b/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json index 893a10411..0f6b8d2cd 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json +++ b/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json @@ -67,91 +67,16 @@ "value": true }, "parPrivateDnsZones": { - "value": [ - "privatelink.xxxxxx.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.xxxxxx.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] + "value": [] }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true - }, - "parVirtualNetworkIdToLink": { - "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus" + "parVirtualNetworkResourceIdsToLinkTo": { + "value": [] }, "parTags": { "value": { "Environment": "Live" } }, - "parVirtualNetworkIdToLinkFailover": { - "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus-failover" - }, "parTelemetryOptOut": { "value": false }, diff --git a/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.multiRegion.all.json b/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.multiRegion.all.json index 976085211..826e15d19 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.multiRegion.all.json +++ b/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.multiRegion.all.json @@ -90,91 +90,16 @@ "value": true }, "parPrivateDnsZones": { - "value": [ - "privatelink.westus.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.westus.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.westus.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) - "privatelink.westus.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] + "value": [] }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true - }, - "parVirtualNetworkIdToLink": { - "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus" + "parVirtualNetworkResourceIdsToLinkTo": { + "value": [] }, "parTags": { "value": { "Environment": "Live" } }, - "parVirtualNetworkIdToLinkFailover": { - "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus-failover" - }, "parTelemetryOptOut": { "value": false }, From 8bb8f317affb4e1112c26aa2f3dc78199068dddd Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:06:05 +0000 Subject: [PATCH 12/14] fix psrule --- .../samples/baseline.sample.bicep | 72 ------------------- .../samples/minimum.sample.bicep | 1 - 2 files changed, 73 deletions(-) diff --git a/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep b/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep index c33b2397f..e5eecb79e 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep +++ b/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep @@ -45,8 +45,6 @@ module minimum_vwan_conn '../vwanConnectivity.bicep' = { parVpnGatewayName: '${parCompanyPrefix}-vpngw' parExpressRouteGatewayName: '${parCompanyPrefix}-ergw' parAzFirewallName: '${parCompanyPrefix}-fw' - parVirtualNetworkIdToLink: '/subscriptions/xxxxxxxxx-b761-4132-9ed1-2c90d07c4885/resourceGroups/rg-vnet/providers/Microsoft.Network/virtualNetworks/vnet' - parAzFirewallPoliciesName: '${parCompanyPrefix}-azfwpolicy-${parLocation}' parVpnGatewayScaleUnit: 1 @@ -58,76 +56,6 @@ module minimum_vwan_conn '../vwanConnectivity.bicep' = { parPrivateDnsZonesEnabled: true parPrivateDnsZonesResourceGroup: resourceGroup().name - parPrivateDnsZones: [ - 'privatelink.${toLower(parLocation)}.azmk8s.io' - 'privatelink.${toLower(parLocation)}.batch.azure.com' - 'privatelink.${toLower(parLocation)}.kusto.windows.net' - 'privatelink.adf.azure.com' - 'privatelink.afs.azure.net' - 'privatelink.agentsvc.azure-automation.net' - 'privatelink.analysis.windows.net' - 'privatelink.api.azureml.ms' - 'privatelink.azconfig.io' - 'privatelink.azure-api.net' - 'privatelink.azure-automation.net' - 'privatelink.azurecr.io' - 'privatelink.azure-devices.net' - 'privatelink.azure-devices-provisioning.net' - 'privatelink.azuredatabricks.net' - 'privatelink.azurehdinsight.net' - 'privatelink.azurehealthcareapis.com' - 'privatelink.azurestaticapps.net' - 'privatelink.azuresynapse.net' - 'privatelink.azurewebsites.net' - 'privatelink.batch.azure.com' - 'privatelink.blob.core.windows.net' - 'privatelink.cassandra.cosmos.azure.com' - 'privatelink.cognitiveservices.azure.com' - 'privatelink.database.windows.net' - 'privatelink.datafactory.azure.net' - 'privatelink.dev.azuresynapse.net' - 'privatelink.dfs.core.windows.net' - 'privatelink.dicom.azurehealthcareapis.com' - 'privatelink.digitaltwins.azure.net' - 'privatelink.directline.botframework.com' - 'privatelink.documents.azure.com' - 'privatelink.eventgrid.azure.net' - 'privatelink.file.core.windows.net' - 'privatelink.gremlin.cosmos.azure.com' - 'privatelink.guestconfiguration.azure.com' - 'privatelink.his.arc.azure.com' - 'privatelink.dp.kubernetesconfiguration.azure.com' - 'privatelink.managedhsm.azure.net' - 'privatelink.mariadb.database.azure.com' - 'privatelink.media.azure.net' - 'privatelink.mongo.cosmos.azure.com' - 'privatelink.monitor.azure.com' - 'privatelink.mysql.database.azure.com' - 'privatelink.notebooks.azure.net' - 'privatelink.ods.opinsights.azure.com' - 'privatelink.oms.opinsights.azure.com' - 'privatelink.pbidedicated.windows.net' - 'privatelink.postgres.database.azure.com' - 'privatelink.prod.migration.windowsazure.com' - 'privatelink.purview.azure.com' - 'privatelink.purviewstudio.azure.com' - 'privatelink.queue.core.windows.net' - 'privatelink.redis.cache.windows.net' - 'privatelink.redisenterprise.cache.azure.net' - 'privatelink.search.windows.net' - 'privatelink.service.signalr.net' - 'privatelink.servicebus.windows.net' - 'privatelink.siterecovery.windowsazure.com' - 'privatelink.sql.azuresynapse.net' - 'privatelink.table.core.windows.net' - 'privatelink.table.cosmos.azure.com' - 'privatelink.tip1.powerquery.microsoft.com' - 'privatelink.token.botframework.com' - 'privatelink.vaultcore.azure.net' - 'privatelink.web.core.windows.net' - 'privatelink.webpubsub.azure.com' - ] - parTags: { key1: 'value1' } diff --git a/infra-as-code/bicep/modules/vwanConnectivity/samples/minimum.sample.bicep b/infra-as-code/bicep/modules/vwanConnectivity/samples/minimum.sample.bicep index 23bec2228..c0510215b 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/samples/minimum.sample.bicep +++ b/infra-as-code/bicep/modules/vwanConnectivity/samples/minimum.sample.bicep @@ -19,6 +19,5 @@ module minimum_vwan_conn '../vwanConnectivity.bicep' = { name: 'minimum_vwan_conn' params: { parLocation: location - parVirtualNetworkIdToLink: '/subscriptions/xxxxxxxxx-b761-4132-9ed1-2c90d07c4885/resourceGroups/rg-vnet/providers/Microsoft.Network/virtualNetworks/vnet' } } From c729ff43ca3d01bfc3b2716f8cc4693e71e3a411 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:17:29 +0000 Subject: [PATCH 13/14] readme updates --- .../hubNetworking-multiRegion.bicep.md | 95 ++------------- .../generateddocs/hubNetworking.bicep.md | 4 +- .../generateddocs/vwanConnectivity.bicep.md | 108 ++---------------- 3 files changed, 21 insertions(+), 186 deletions(-) diff --git a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking-multiRegion.bicep.md b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking-multiRegion.bicep.md index f7819e663..f06180266 100644 --- a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking-multiRegion.bicep.md +++ b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking-multiRegion.bicep.md @@ -76,9 +76,9 @@ parDisableBgpRoutePropagationSecondaryLocation | No | Switch to enable/dis parHubRouteTableLock | No | Resource Lock Configuration for Hub Route Table. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPrivateDnsZonesEnabled | No | Switch to enable/disable Private DNS Zones deployment. parPrivateDnsZonesResourceGroup | No | Resource Group Name for Private DNS Zones. -parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones -parPrivateDnsZoneAutoMergeAzureBackupZone | No | Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. +parPrivateDnsZones | No | Array of DNS Zones to provision and link to Hub Virtual Networks. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones parVirtualNetworkIdToLinkFailover | No | Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +parVirtualNetworkResourceIdsToLinkTo | No | Array of Resource IDs of VNets to link to Private DNS Zones. Hub VNets are automatically included by module. parPrivateDNSZonesLock | No | Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parVpnGatewayEnabled | No | Switch to enable/disable VPN virtual network gateway deployment. parVpnGatewayEnabledSecondaryLocation | No | Switch to enable/disable VPN virtual network gateway deployment in secondary location. @@ -686,23 +686,19 @@ Resource Group Name for Private DNS Zones. ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones +Array of DNS Zones to provision and link to Hub Virtual Networks. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones -- Default value: `[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))] [format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))] [format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))] [format('privatelink.{0}.backup.windowsazure.com', toLower(parameters('parLocation')))] privatelink.adf.azure.com privatelink.afs.azure.net privatelink.agentsvc.azure-automation.net privatelink.analysis.windows.net privatelink.api.azureml.ms privatelink.azconfig.io privatelink.azure-api.net privatelink.azure-automation.net privatelink.azurecr.io privatelink.azure-devices.net privatelink.azure-devices-provisioning.net privatelink.azuredatabricks.net privatelink.azurehdinsight.net privatelink.azurehealthcareapis.com privatelink.azurestaticapps.net privatelink.azuresynapse.net privatelink.azurewebsites.net privatelink.batch.azure.com privatelink.blob.core.windows.net privatelink.cassandra.cosmos.azure.com privatelink.cognitiveservices.azure.com privatelink.database.windows.net privatelink.datafactory.azure.net privatelink.dev.azuresynapse.net privatelink.dfs.core.windows.net privatelink.dicom.azurehealthcareapis.com privatelink.digitaltwins.azure.net privatelink.directline.botframework.com privatelink.documents.azure.com privatelink.eventgrid.azure.net privatelink.file.core.windows.net privatelink.gremlin.cosmos.azure.com privatelink.guestconfiguration.azure.com privatelink.his.arc.azure.com privatelink.dp.kubernetesconfiguration.azure.com privatelink.managedhsm.azure.net privatelink.mariadb.database.azure.com privatelink.media.azure.net privatelink.mongo.cosmos.azure.com privatelink.monitor.azure.com privatelink.mysql.database.azure.com privatelink.notebooks.azure.net privatelink.ods.opinsights.azure.com privatelink.oms.opinsights.azure.com privatelink.pbidedicated.windows.net privatelink.postgres.database.azure.com privatelink.prod.migration.windowsazure.com privatelink.purview.azure.com privatelink.purviewstudio.azure.com privatelink.queue.core.windows.net privatelink.redis.cache.windows.net privatelink.redisenterprise.cache.azure.net privatelink.search.windows.net privatelink.service.signalr.net privatelink.servicebus.windows.net privatelink.siterecovery.windowsazure.com privatelink.sql.azuresynapse.net privatelink.table.core.windows.net privatelink.table.cosmos.azure.com privatelink.tip1.powerquery.microsoft.com privatelink.token.botframework.com privatelink.vaultcore.azure.net privatelink.web.core.windows.net privatelink.webpubsub.azure.com` - -### parPrivateDnsZoneAutoMergeAzureBackupZone +### parVirtualNetworkIdToLinkFailover ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. - -- Default value: `True` +Resource ID of Failover VNet for Private DNS Zone VNet Failover Links -### parVirtualNetworkIdToLinkFailover +### parVirtualNetworkResourceIdsToLinkTo ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +Array of Resource IDs of VNets to link to Private DNS Zones. Hub VNets are automatically included by module. ### parPrivateDNSZonesLock @@ -1140,83 +1136,14 @@ outBastionNsgNameSecondaryLocation | string | "value": "[resourceGroup().name]" }, "parPrivateDnsZones": { - "value": [ - "[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.backup.windowsazure.com', toLower(parameters('parLocation')))]", - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] - }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true + "value": [] }, "parVirtualNetworkIdToLinkFailover": { "value": "" }, + "parVirtualNetworkResourceIdsToLinkTo": { + "value": [] + }, "parPrivateDNSZonesLock": { "value": { "kind": "None", diff --git a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md index c5ad326fd..bd7acda70 100644 --- a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md +++ b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md @@ -46,7 +46,7 @@ parDisableBgpRoutePropagation | No | Switch to enable/disable BGP Propagat parHubRouteTableLock | No | Resource Lock Configuration for Hub Route Table. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPrivateDnsZonesEnabled | No | Switch to enable/disable Private DNS Zones deployment. parPrivateDnsZonesResourceGroup | No | Resource Group Name for Private DNS Zones. -parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones +parPrivateDnsZones | No | Array of DNS Zones to provision and link to Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones parVirtualNetworkIdToLinkFailover | No | Resource ID of Failover VNet for Private DNS Zone VNet Failover Links parVirtualNetworkResourceIdsToLinkTo | No | Array of Resource IDs of VNets to link to Private DNS Zones. Hub VNet is automatically included by module. parPrivateDNSZonesLock | No | Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. @@ -413,7 +413,7 @@ Resource Group Name for Private DNS Zones. ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones +Array of DNS Zones to provision and link to Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones ### parVirtualNetworkIdToLinkFailover diff --git a/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md b/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md index c4046009d..be04c65ef 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md +++ b/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md @@ -32,10 +32,8 @@ parDdosPlanName | No | DDoS Plan Name. parDdosLock | No | Resource Lock Configuration for DDoS Plan. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPrivateDnsZonesEnabled | No | Switch to enable/disable Private DNS Zones deployment. parPrivateDnsZonesResourceGroup | No | Resource Group Name for Private DNS Zones. -parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. -parPrivateDnsZoneAutoMergeAzureBackupZone | No | Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. -parVirtualNetworkIdToLink | No | Resource ID of VNet for Private DNS Zone VNet Links -parVirtualNetworkIdToLinkFailover | No | Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones +parVirtualNetworkResourceIdsToLinkTo | No | Array of Resource IDs of VNets to link to Private DNS Zones. parPrivateDNSZonesLock | No | Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTags | No | Tags you would like to be applied to all resources in this module. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry @@ -296,29 +294,13 @@ Resource Group Name for Private DNS Zones. ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Array of DNS Zones to provision in Hub Virtual Network. +Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones, baked into underlying AVM module see: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones -- Default value: `[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))] [format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))] [format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))] privatelink.adf.azure.com privatelink.afs.azure.net privatelink.agentsvc.azure-automation.net privatelink.analysis.windows.net privatelink.api.azureml.ms privatelink.azconfig.io privatelink.azure-api.net privatelink.azure-automation.net privatelink.azurecr.io privatelink.azure-devices.net privatelink.azure-devices-provisioning.net privatelink.azuredatabricks.net privatelink.azurehdinsight.net privatelink.azurehealthcareapis.com privatelink.azurestaticapps.net privatelink.azuresynapse.net privatelink.azurewebsites.net privatelink.batch.azure.com privatelink.blob.core.windows.net privatelink.cassandra.cosmos.azure.com privatelink.cognitiveservices.azure.com privatelink.database.windows.net privatelink.datafactory.azure.net privatelink.dev.azuresynapse.net privatelink.dfs.core.windows.net privatelink.dicom.azurehealthcareapis.com privatelink.digitaltwins.azure.net privatelink.directline.botframework.com privatelink.documents.azure.com privatelink.eventgrid.azure.net privatelink.file.core.windows.net privatelink.gremlin.cosmos.azure.com privatelink.guestconfiguration.azure.com privatelink.his.arc.azure.com privatelink.dp.kubernetesconfiguration.azure.com privatelink.managedhsm.azure.net privatelink.mariadb.database.azure.com privatelink.media.azure.net privatelink.mongo.cosmos.azure.com privatelink.monitor.azure.com privatelink.mysql.database.azure.com privatelink.notebooks.azure.net privatelink.ods.opinsights.azure.com privatelink.oms.opinsights.azure.com privatelink.pbidedicated.windows.net privatelink.postgres.database.azure.com privatelink.prod.migration.windowsazure.com privatelink.purview.azure.com privatelink.purviewstudio.azure.com privatelink.queue.core.windows.net privatelink.redis.cache.windows.net privatelink.redisenterprise.cache.azure.net privatelink.search.windows.net privatelink.service.signalr.net privatelink.servicebus.windows.net privatelink.siterecovery.windowsazure.com privatelink.sql.azuresynapse.net privatelink.table.core.windows.net privatelink.table.cosmos.azure.com privatelink.tip1.powerquery.microsoft.com privatelink.token.botframework.com privatelink.vaultcore.azure.net privatelink.web.core.windows.net privatelink.webpubsub.azure.com` - -### parPrivateDnsZoneAutoMergeAzureBackupZone - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. - -- Default value: `True` - -### parVirtualNetworkIdToLink - -![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) - -Resource ID of VNet for Private DNS Zone VNet Links - -### parVirtualNetworkIdToLinkFailover +### parVirtualNetworkResourceIdsToLinkTo ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +Array of Resource IDs of VNets to link to Private DNS Zones. ### parPrivateDNSZonesLock @@ -488,84 +470,10 @@ outAzFwPrivateIps | array | "value": "[resourceGroup().name]" }, "parPrivateDnsZones": { - "value": [ - "[format('privatelink.{0}.azmk8s.io', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.batch.azure.com', toLower(parameters('parLocation')))]", - "[format('privatelink.{0}.kusto.windows.net', toLower(parameters('parLocation')))]", - "privatelink.adf.azure.com", - "privatelink.afs.azure.net", - "privatelink.agentsvc.azure-automation.net", - "privatelink.analysis.windows.net", - "privatelink.api.azureml.ms", - "privatelink.azconfig.io", - "privatelink.azure-api.net", - "privatelink.azure-automation.net", - "privatelink.azurecr.io", - "privatelink.azure-devices.net", - "privatelink.azure-devices-provisioning.net", - "privatelink.azuredatabricks.net", - "privatelink.azurehdinsight.net", - "privatelink.azurehealthcareapis.com", - "privatelink.azurestaticapps.net", - "privatelink.azuresynapse.net", - "privatelink.azurewebsites.net", - "privatelink.batch.azure.com", - "privatelink.blob.core.windows.net", - "privatelink.cassandra.cosmos.azure.com", - "privatelink.cognitiveservices.azure.com", - "privatelink.database.windows.net", - "privatelink.datafactory.azure.net", - "privatelink.dev.azuresynapse.net", - "privatelink.dfs.core.windows.net", - "privatelink.dicom.azurehealthcareapis.com", - "privatelink.digitaltwins.azure.net", - "privatelink.directline.botframework.com", - "privatelink.documents.azure.com", - "privatelink.eventgrid.azure.net", - "privatelink.file.core.windows.net", - "privatelink.gremlin.cosmos.azure.com", - "privatelink.guestconfiguration.azure.com", - "privatelink.his.arc.azure.com", - "privatelink.dp.kubernetesconfiguration.azure.com", - "privatelink.managedhsm.azure.net", - "privatelink.mariadb.database.azure.com", - "privatelink.media.azure.net", - "privatelink.mongo.cosmos.azure.com", - "privatelink.monitor.azure.com", - "privatelink.mysql.database.azure.com", - "privatelink.notebooks.azure.net", - "privatelink.ods.opinsights.azure.com", - "privatelink.oms.opinsights.azure.com", - "privatelink.pbidedicated.windows.net", - "privatelink.postgres.database.azure.com", - "privatelink.prod.migration.windowsazure.com", - "privatelink.purview.azure.com", - "privatelink.purviewstudio.azure.com", - "privatelink.queue.core.windows.net", - "privatelink.redis.cache.windows.net", - "privatelink.redisenterprise.cache.azure.net", - "privatelink.search.windows.net", - "privatelink.service.signalr.net", - "privatelink.servicebus.windows.net", - "privatelink.siterecovery.windowsazure.com", - "privatelink.sql.azuresynapse.net", - "privatelink.table.core.windows.net", - "privatelink.table.cosmos.azure.com", - "privatelink.tip1.powerquery.microsoft.com", - "privatelink.token.botframework.com", - "privatelink.vaultcore.azure.net", - "privatelink.web.core.windows.net", - "privatelink.webpubsub.azure.com" - ] - }, - "parPrivateDnsZoneAutoMergeAzureBackupZone": { - "value": true - }, - "parVirtualNetworkIdToLink": { - "value": "" + "value": [] }, - "parVirtualNetworkIdToLinkFailover": { - "value": "" + "parVirtualNetworkResourceIdsToLinkTo": { + "value": [] }, "parPrivateDNSZonesLock": { "value": { From 8779d14fa064c59f9160d53fbc679827767ec020 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:32:51 +0000 Subject: [PATCH 14/14] remove --- releaseNoteDraft.md | 90 --------------------------------------------- 1 file changed, 90 deletions(-) delete mode 100644 releaseNoteDraft.md diff --git a/releaseNoteDraft.md b/releaseNoteDraft.md deleted file mode 100644 index 9ba8b4979..000000000 --- a/releaseNoteDraft.md +++ /dev/null @@ -1,90 +0,0 @@ -ALZ Bicep Release Notes: - -The local private DNS zones modules (`privateDnsZones.bicep`) has been replaced in the networking related modules in this repo with the AVM Pattern module of [`avm/ptn/network/private-link-private-dns-zones`](https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones) to resolve bug #695. - -This has meant some breaking changes to each of the networking modules that are detailed below. - -#### `hubNetworking.bicep` & `hubNetworking-multiRegion.bicep` - -- `parPrivateDnsZones` default value changed to an empty array (`[]`) - - Only enter values in here if you want to override the defaults in the underlying AVM pattern module. See: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones -- `parPrivateDnsZoneAutoMergeAzureBackupZone` removed from module -- `parVirtualNetworkResourceIdsToLinkTo` added to module, you can prefer to use this parameter instead of `parVirtualNetworkIdToLink` & `parVirtualNetworkIdToLinkFailover` if you wish (they are automatically all merged together by the module anyway) -- The value returned in `outPrivateDnsZones` has changed - -**From:** - -``` -[ - { - "name": "privatelink.api.azureml.ms", - "id": "/subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.api.azureml.ms" - }, - { - "name": "privatelink.notebooks.azure.net", - "id": "subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.notebooks.azure.net" - }, - … -] -``` - -**To:** -``` -[ - { - "pdnsZoneName": "privatelink.api.azureml.ms", - "virtualNetworkResourceIdsToLinkTo": [ - "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" - ] - }, - { - "pdnsZoneName": "privatelink.notebooks.azure.net", - "virtualNetworkResourceIdsToLinkTo": [ - "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" - ] - }, - … -] -``` - -#### `vwanConnectivity.bicep` - -- `parPrivateDnsZones` default value changed to an empty array (`[]`) - - Only enter values in here if you want to override the defaults in the underlying AVM pattern module. See: https://github.com/Azure/bicep-registry-modules/tree/main/avm/ptn/network/private-link-private-dns-zones#parameter-privatelinkprivatednszones -- `parVirtualNetworkIdToLink` & `parVirtualNetworkIdToLinkFailover` removed from module and replaced with `parVirtualNetworkResourceIdsToLinkTo` -- The value returned in `outPrivateDnsZones` has changed - -**From:** - -``` -[ - { - "name": "privatelink.api.azureml.ms", - "id": "/subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.api.azureml.ms" - }, - { - "name": "privatelink.notebooks.azure.net", - "id": "subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.notebooks.azure.net" - }, - … -] -``` - -**To:** -``` -[ - { - "pdnsZoneName": "privatelink.api.azureml.ms", - "virtualNetworkResourceIdsToLinkTo": [ - "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" - ] - }, - { - "pdnsZoneName": "privatelink.notebooks.azure.net", - "virtualNetworkResourceIdsToLinkTo": [ - "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/alz-hub-uksouth" - ] - }, - … -] -```