diff --git a/src/bicep/form/mlz.portal.json b/src/bicep/form/mlz.portal.json index 353729aac..2ae1aeff0 100644 --- a/src/bicep/form/mlz.portal.json +++ b/src/bicep/form/mlz.portal.json @@ -100,10 +100,20 @@ "text": "The Identity spoke can be used to house Active Directory and other AuthN and AuthZ solutions." } }, + { + "name": "deployIdentity", + "type": "Microsoft.Common.CheckBox", + "label": "Deploy identity resources?", + "toolTip": "Check here to create the identity resources.", + "constraints": { + "required": false + } + }, { "name": "identitySubscriptionId", "label": "Identity Subscription", "type": "Microsoft.Common.DropDown", + "visible": "[steps('basics').identitySection.deployIdentity]", "defaultValue": "", "toolTip": "Select the Subscription for your Mission Landing Zone Identity network.", "multiselect": false, @@ -195,11 +205,11 @@ "name": "location", "type": "Microsoft.Common.LocationSelector", "label": "Location", - "toolTip": "Select the location for the AVD session hosts.", + "toolTip": "Select the deployment location for MLZ.", "resourceTypes": [ - "Microsoft.Compute/virtualMachines" + "Microsoft.Compute/virtualMachines" ] - } + } ] }, { @@ -444,6 +454,7 @@ "name": "identityVirtualNetwork", "label": "Identity Virtual Network", "type": "Microsoft.Common.Section", + "visible": "[steps('basics').identitySection.deployIdentity]", "elements": [ { "name": "virtualNetworkAddressCidrRange", @@ -992,6 +1003,7 @@ "parameters": { "bastionHostSubnetAddressPrefix": "[steps('remoteAccess').azureBastionSubnetSection.bastionSubnetAddressCidrRange]", "deployDefender": "[steps('compliance').defenderSection.deployDefender]", + "deployIdentity": "[steps('basics').identitySection.deployIdentity]", "deployPolicy": "[steps('compliance').policySection.deployPolicy]", "deployRemoteAccess": "[steps('remoteAccess').remoteAccessSection.deployRemoteAccess]", "deploySentinel": "[steps('compliance').sentinelSection.deploySentinel]", @@ -1004,7 +1016,7 @@ "hubVirtualNetworkAddressPrefix": "[steps('networking').hubVirtualNetwork.virtualNetworkAddressCidrRange]", "hybridUseBenefit": "[steps('remoteAccess').windowsVmSection.hybridUseBenefit]", "identitySubnetAddressPrefix": "[steps('networking').identityVirtualNetwork.subnetAddressCidrRange]", - "identitySubscriptionId": "[replace(steps('basics').identitySection.identitySubscriptionId, '/subscriptions/', '')]", + "identitySubscriptionId": "[if(steps('basics').identitySection.deployIdentity, replace(steps('basics').identitySection.identitySubscriptionId, '/subscriptions/', ''), replace(steps('basics').hubSection.hubSubscriptionId, '/subscriptions/', ''))]", "identityVirtualNetworkAddressPrefix": "[steps('networking').identityVirtualNetwork.virtualNetworkAddressCidrRange]", "linuxVmAdminPasswordOrKey": "[if(equals(steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.authenticationType, 'password'), steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.password, steps('remoteAccess').linuxVmSection.linuxVmAdminPasswordOrKey.sshPublicKey)]", "linuxVmAdminUsername": "[steps('remoteAccess').linuxVmSection.linuxVmAdminUsername]", diff --git a/src/bicep/mlz.bicep b/src/bicep/mlz.bicep index 2936b2a35..13d954707 100644 --- a/src/bicep/mlz.bicep +++ b/src/bicep/mlz.bicep @@ -48,6 +48,9 @@ param supportedClouds array = [ 'AzureUSGovernment' ] +@description('Choose to deploy the identity resources. The identity resoures are not required if you plan to use cloud identities.') +param deployIdentity bool + // RESOURCE NAMING PARAMETERS @description('A suffix to use for naming deployments uniquely. It defaults to the Bicep resolution of the "utcNow()" function.') @@ -655,26 +658,8 @@ var bastionHostPublicIPAddressAllocationMethod = 'Static' // SPOKES -var spokes = [ - { - name: identityName - subscriptionId: identitySubscriptionId - resourceGroupName: identityResourceGroupName - logStorageAccountName: identityLogStorageAccountName - virtualNetworkName: identityVirtualNetworkName - virtualNetworkAddressPrefix: identityVirtualNetworkAddressPrefix - virtualNetworkDiagnosticsLogs: identityVirtualNetworkDiagnosticsLogs - virtualNetworkDiagnosticsMetrics: identityVirtualNetworkDiagnosticsMetrics - networkSecurityGroupName: identityNetworkSecurityGroupName - networkSecurityGroupRules: identityNetworkSecurityGroupRules - networkSecurityGroupDiagnosticsLogs: identityNetworkSecurityGroupDiagnosticsLogs - networkSecurityGroupDiagnosticsMetrics: identityNetworkSecurityGroupDiagnosticsMetrics - routeTableName: identityRouteTableName - subnetName: identitySubnetName - subnetAddressPrefix: identitySubnetAddressPrefix - subnetPrivateEndpointNetworkPolicies: 'Disabled' - subnetPrivateLinkServiceNetworkPolicies: 'Disabled' - } +var spokes = union(spokesCommon, spokesIdentity) +var spokesCommon = [ { name: operationsName subscriptionId: operationsSubscriptionId @@ -714,6 +699,27 @@ var spokes = [ subnetPrivateLinkServiceNetworkPolicies: 'Disabled' } ] +var spokesIdentity = deployIdentity ? [ + { + name: identityName + subscriptionId: identitySubscriptionId + resourceGroupName: identityResourceGroupName + logStorageAccountName: identityLogStorageAccountName + virtualNetworkName: identityVirtualNetworkName + virtualNetworkAddressPrefix: identityVirtualNetworkAddressPrefix + virtualNetworkDiagnosticsLogs: identityVirtualNetworkDiagnosticsLogs + virtualNetworkDiagnosticsMetrics: identityVirtualNetworkDiagnosticsMetrics + networkSecurityGroupName: identityNetworkSecurityGroupName + networkSecurityGroupRules: identityNetworkSecurityGroupRules + networkSecurityGroupDiagnosticsLogs: identityNetworkSecurityGroupDiagnosticsLogs + networkSecurityGroupDiagnosticsMetrics: identityNetworkSecurityGroupDiagnosticsMetrics + routeTableName: identityRouteTableName + subnetName: identitySubnetName + subnetAddressPrefix: identitySubnetAddressPrefix + subnetPrivateEndpointNetworkPolicies: 'Disabled' + subnetPrivateLinkServiceNetworkPolicies: 'Disabled' + } +] : [] // TAGS @@ -880,9 +886,19 @@ module privateDnsZones './modules/private-dns.bicep' = { name: 'deploy-private-dns-zones-${deploymentNameSuffix}' scope: resourceGroup(hubSubscriptionId, hubResourceGroupName) params: { - vnetName: hubNetwork.outputs.virtualNetworkName + deployIdentity: deployIdentity + deploymentNameSuffix: deploymentNameSuffix + hubVirtualNetworkName: hubNetwork.outputs.virtualNetworkName + hubVirtualNetworkResourceGroupName: hubResourceGroupName + hubVirtualNetworkSubscriptionId: hubSubscriptionId + identityVirtualNetworkName: deployIdentity ? spokes[2].virtualNetworkName : '' + identityVirtualNetworkResourceGroupName: identityResourceGroupName + identityVirtualNetworkSubscriptionId: identitySubscriptionId tags: tags } + dependsOn: [ + spokeNetworks + ] } // OPERATIONS CMK DEPENDANCIES @@ -897,7 +913,7 @@ module operationsCustomerManagedKeys './core/operations-customer-managed-keys.bi keyVaultPrivateDnsZoneResourceId: privateDnsZones.outputs.keyvaultDnsPrivateDnsZoneId location: location resourcePrefix: resourcePrefix - subnetResourceId: spokeNetworks[1].outputs.subnetResourceId + subnetResourceId: spokeNetworks[0].outputs.subnetResourceId tags: calculatedTags userAssignedIdentityName: operationsUserAssignedIdentityName } @@ -921,7 +937,7 @@ module azureMonitor './modules/azure-monitor.bicep' = if (contains(supportedClou location: location tags: tags resourcePrefix: resourcePrefix - subnetResourceId: spokeNetworks[1].outputs.subnetResourceId + subnetResourceId: spokeNetworks[0].outputs.subnetResourceId } dependsOn: [ logAnalyticsWorkspace diff --git a/src/bicep/mlz.json b/src/bicep/mlz.json index 91eeae44e..3ff3c2767 100644 --- a/src/bicep/mlz.json +++ b/src/bicep/mlz.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "12597188585186624077" + "templateHash": "9000107242870608619" } }, "parameters": { @@ -71,6 +71,12 @@ "description": "Supported Azure Clouds array. It defaults to the Public cloud and the Azure US Government cloud." } }, + "deployIdentity": { + "type": "bool", + "metadata": { + "description": "Choose to deploy the identity resources. The identity resoures are not required if you plan to use cloud identities." + } + }, "deploymentNameSuffix": { "type": "string", "defaultValue": "[utcNow()]", @@ -1302,26 +1308,8 @@ "windowsVmName": "[replace(variables('virtualMachineNamingConvention'), variables('nameToken'), 'bas-windows')]", "bastionHostPublicIPAddressSkuName": "Standard", "bastionHostPublicIPAddressAllocationMethod": "Static", - "spokes": [ - { - "name": "[variables('identityName')]", - "subscriptionId": "[parameters('identitySubscriptionId')]", - "resourceGroupName": "[variables('identityResourceGroupName')]", - "logStorageAccountName": "[variables('identityLogStorageAccountName')]", - "virtualNetworkName": "[variables('identityVirtualNetworkName')]", - "virtualNetworkAddressPrefix": "[parameters('identityVirtualNetworkAddressPrefix')]", - "virtualNetworkDiagnosticsLogs": "[parameters('identityVirtualNetworkDiagnosticsLogs')]", - "virtualNetworkDiagnosticsMetrics": "[parameters('identityVirtualNetworkDiagnosticsMetrics')]", - "networkSecurityGroupName": "[variables('identityNetworkSecurityGroupName')]", - "networkSecurityGroupRules": "[parameters('identityNetworkSecurityGroupRules')]", - "networkSecurityGroupDiagnosticsLogs": "[parameters('identityNetworkSecurityGroupDiagnosticsLogs')]", - "networkSecurityGroupDiagnosticsMetrics": "[parameters('identityNetworkSecurityGroupDiagnosticsMetrics')]", - "routeTableName": "[variables('identityRouteTableName')]", - "subnetName": "[variables('identitySubnetName')]", - "subnetAddressPrefix": "[parameters('identitySubnetAddressPrefix')]", - "subnetPrivateEndpointNetworkPolicies": "Disabled", - "subnetPrivateLinkServiceNetworkPolicies": "Disabled" - }, + "spokes": "[union(variables('spokesCommon'), variables('spokesIdentity'))]", + "spokesCommon": [ { "name": "[variables('operationsName')]", "subscriptionId": "[parameters('operationsSubscriptionId')]", @@ -1361,6 +1349,7 @@ "subnetPrivateLinkServiceNetworkPolicies": "Disabled" } ], + "spokesIdentity": "[if(parameters('deployIdentity'), createArray(createObject('name', variables('identityName'), 'subscriptionId', parameters('identitySubscriptionId'), 'resourceGroupName', variables('identityResourceGroupName'), 'logStorageAccountName', variables('identityLogStorageAccountName'), 'virtualNetworkName', variables('identityVirtualNetworkName'), 'virtualNetworkAddressPrefix', parameters('identityVirtualNetworkAddressPrefix'), 'virtualNetworkDiagnosticsLogs', parameters('identityVirtualNetworkDiagnosticsLogs'), 'virtualNetworkDiagnosticsMetrics', parameters('identityVirtualNetworkDiagnosticsMetrics'), 'networkSecurityGroupName', variables('identityNetworkSecurityGroupName'), 'networkSecurityGroupRules', parameters('identityNetworkSecurityGroupRules'), 'networkSecurityGroupDiagnosticsLogs', parameters('identityNetworkSecurityGroupDiagnosticsLogs'), 'networkSecurityGroupDiagnosticsMetrics', parameters('identityNetworkSecurityGroupDiagnosticsMetrics'), 'routeTableName', variables('identityRouteTableName'), 'subnetName', variables('identitySubnetName'), 'subnetAddressPrefix', parameters('identitySubnetAddressPrefix'), 'subnetPrivateEndpointNetworkPolicies', 'Disabled', 'subnetPrivateLinkServiceNetworkPolicies', 'Disabled')), createArray())]", "defaultTags": { "resourcePrefix": "[parameters('resourcePrefix')]", "resourceSuffix": "[parameters('resourceSuffix')]", @@ -3577,9 +3566,28 @@ }, "mode": "Incremental", "parameters": { - "vnetName": { + "deployIdentity": { + "value": "[parameters('deployIdentity')]" + }, + "deploymentNameSuffix": { + "value": "[parameters('deploymentNameSuffix')]" + }, + "hubVirtualNetworkName": { "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.virtualNetworkName.value]" }, + "hubVirtualNetworkResourceGroupName": { + "value": "[variables('hubResourceGroupName')]" + }, + "hubVirtualNetworkSubscriptionId": { + "value": "[parameters('hubSubscriptionId')]" + }, + "identityVirtualNetworkName": "[if(parameters('deployIdentity'), createObject('value', variables('spokes')[2].virtualNetworkName), createObject('value', ''))]", + "identityVirtualNetworkResourceGroupName": { + "value": "[variables('identityResourceGroupName')]" + }, + "identityVirtualNetworkSubscriptionId": { + "value": "[parameters('identitySubscriptionId')]" + }, "tags": { "value": "[parameters('tags')]" } @@ -3591,43 +3599,44 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "980613473868384333" + "templateHash": "556553486991873372" } }, "parameters": { - "vnetName": { - "type": "string", - "metadata": { - "description": "The name of the virtual network the private dns zones will be connected to" - } + "deployIdentity": { + "type": "bool" }, - "vnetResourceGroup": { - "type": "string", - "defaultValue": "[resourceGroup().name]", - "metadata": { - "description": "The name of the the resource group where the virtual network exists" - } + "deploymentNameSuffix": { + "type": "string" }, - "vnetSubscriptionId": { - "type": "string", - "defaultValue": "[subscription().subscriptionId]", - "metadata": { - "description": "The subscription id of the subscription the virtual network exists in" - } + "hubVirtualNetworkName": { + "type": "string" + }, + "hubVirtualNetworkResourceGroupName": { + "type": "string" + }, + "hubVirtualNetworkSubscriptionId": { + "type": "string" + }, + "identityVirtualNetworkName": { + "type": "string" + }, + "identityVirtualNetworkResourceGroupName": { + "type": "string" + }, + "identityVirtualNetworkSubscriptionId": { + "type": "string" }, "tags": { - "type": "object", - "metadata": { - "description": "The tags that will be associated to the resources" - } + "type": "object" } }, "variables": { "copy": [ { - "name": "privatelink_backup_names", + "name": "privateDnsZoneNames_Backup", "count": "[length(items(variables('locations')))]", - "input": "[format('privatelink.{0}.backup.{1}', items(variables('locations'))[copyIndex('privatelink_backup_names')].value.recoveryServicesGeo, coalesce(variables('privatelink_backup_suffixes')[environment().name], variables('cloudSuffix')))]" + "input": "[format('privatelink.{0}.backup.{1}', items(variables('locations'))[copyIndex('privateDnsZoneNames_Backup')].value.recoveryServicesGeo, coalesce(variables('privateDnsZoneSuffixes_Backup')[environment().name], variables('cloudSuffix')))]" } ], "$fxv#0": { @@ -4016,397 +4025,177 @@ }, "cloudSuffix": "[replace(replace(environment().resourceManager, 'https://management.', ''), '/', '')]", "locations": "[variables('$fxv#0')[environment().name]]", - "privatelink_agentsvc_azure_automation_name": "[format('privatelink.agentsvc.azure-automation.{0}', coalesce(variables('privatelink_azure_automation_suffixes')[environment().name], variables('cloudSuffix')))]", - "privatelink_azure_automation_suffixes": { + "privateDnsZoneNames": "[union(createArray(format('privatelink.agentsvc.azure-automation.{0}', coalesce(variables('privateDnsZoneSuffixes_AzureAutomation')[environment().name], variables('cloudSuffix'))), format('privatelink.azure-automation.{0}', coalesce(variables('privateDnsZoneSuffixes_AzureAutomation')[environment().name], variables('cloudSuffix'))), format('privatelink.wvd.{0}', coalesce(variables('privateDnsZoneSuffixes_AzureVirtualDesktop')[environment().name], variables('cloudSuffix'))), format('privatelink-global.wvd.{0}', coalesce(variables('privateDnsZoneSuffixes_AzureVirtualDesktop')[environment().name], variables('cloudSuffix'))), format('privatelink.file.{0}', environment().suffixes.storage), format('privatelink.queue.{0}', environment().suffixes.storage), format('privatelink.table.{0}', environment().suffixes.storage), format('privatelink.blob.{0}', environment().suffixes.storage), replace(format('privatelink{0}', environment().suffixes.keyvaultDns), 'vault', 'vaultcore'), format('privatelink.monitor.{0}', coalesce(variables('privateDnsZoneSuffixes_Monitor')[environment().name], variables('cloudSuffix'))), format('privatelink.ods.opinsights.{0}', coalesce(variables('privateDnsZoneSuffixes_Monitor')[environment().name], variables('cloudSuffix'))), format('privatelink.oms.opinsights.{0}', coalesce(variables('privateDnsZoneSuffixes_Monitor')[environment().name], variables('cloudSuffix')))), variables('privateDnsZoneNames_Backup'))]", + "privateDnsZoneSuffixes_AzureAutomation": { "AzureCloud": "net", "AzureUSGovernment": "us" }, - "privatelink_azure_automation_name": "[format('privatelink.azure-automation.{0}', coalesce(variables('privatelink_azure_automation_suffixes')[environment().name], variables('cloudSuffix')))]", - "privatelink_avd_suffixes": { + "privateDnsZoneSuffixes_AzureVirtualDesktop": { "AzureCloud": "microsoft.com", "AzureUSGovernment": "azure.us" }, - "privatelink_avd_name": "[format('privatelink.wvd.{0}', coalesce(variables('privatelink_avd_suffixes')[environment().name], variables('cloudSuffix')))]", - "privatelink_avd_global_name": "[format('privatelink-global.wvd.{0}', coalesce(variables('privatelink_avd_suffixes')[environment().name], variables('cloudSuffix')))]", - "privatelink_backup_suffixes": { + "privateDnsZoneSuffixes_Backup": { "AzureCloud": "windowsazure.com", "AzureUSGovernment": "windowsazure.us" }, - "privatelink_file_name": "[format('privatelink.file.{0}', environment().suffixes.storage)]", - "privatelink_queue_name": "[format('privatelink.queue.{0}', environment().suffixes.storage)]", - "privatelink_table_name": "[format('privatelink.table.{0}', environment().suffixes.storage)]", - "privatelink_blob_name": "[format('privatelink.blob.{0}', environment().suffixes.storage)]", - "privatelink_keyvaultDns_name": "[replace(format('privatelink{0}', environment().suffixes.keyvaultDns), 'vault', 'vaultcore')]", - "privatelink_monitor_suffixes": { + "privateDnsZoneSuffixes_Monitor": { "AzureCloud": "azure.com", "AzureUSGovernment": "azure.us" }, - "privatelink_monitor_name": "[format('privatelink.monitor.{0}', coalesce(variables('privatelink_monitor_suffixes')[environment().name], variables('cloudSuffix')))]", - "privatelink_ods_opinsights_name": "[format('privatelink.ods.opinsights.{0}', coalesce(variables('privatelink_monitor_suffixes')[environment().name], variables('cloudSuffix')))]", - "privatelink_oms_opinsights_name": "[format('privatelink.oms.opinsights.{0}', coalesce(variables('privatelink_monitor_suffixes')[environment().name], variables('cloudSuffix')))]" + "virtualNetworks": "[union(createArray(createObject('name', parameters('hubVirtualNetworkName'), 'resourceGroupName', parameters('hubVirtualNetworkResourceGroupName'), 'subscriptionId', parameters('hubVirtualNetworkSubscriptionId'))), if(parameters('deployIdentity'), createArray(createObject('name', parameters('identityVirtualNetworkName'), 'resourceGroupName', parameters('identityVirtualNetworkResourceGroupName'), 'subscriptionId', parameters('identityVirtualNetworkSubscriptionId'))), createArray()))]" }, "resources": [ - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_avd_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_avd_global_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, { "copy": { - "name": "privateDnsZone_backup_rsv", - "count": "[length(variables('privatelink_backup_names'))]" + "name": "privateDnsZones", + "count": "[length(variables('privateDnsZoneNames'))]" }, - "condition": "[not(contains(variables('privatelink_backup_names')[copyIndex()], '..'))]", "type": "Microsoft.Network/privateDnsZones", "apiVersion": "2018-09-01", - "name": "[variables('privatelink_backup_names')[copyIndex()]]", + "name": "[variables('privateDnsZoneNames')[copyIndex()]]", "location": "global", "tags": "[parameters('tags')]" }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_file_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_queue_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_table_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_keyvaultDns_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_monitor_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_oms_opinsights_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_ods_opinsights_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_agentsvc_azure_automation_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_azure_automation_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones", - "apiVersion": "2018-09-01", - "name": "[variables('privatelink_blob_name')]", - "location": "global", - "tags": "[parameters('tags')]" - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_avd_name'), format('{0}-link', variables('privatelink_avd_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_avd_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_file_name'), format('{0}-link', variables('privatelink_file_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_file_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_table_name'), format('{0}-link', variables('privatelink_table_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_table_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_keyvaultDns_name'), format('{0}-link', variables('privatelink_keyvaultDns_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_keyvaultDns_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_queue_name'), format('{0}-link', variables('privatelink_queue_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_queue_name'))]" - ] - }, { "copy": { - "name": "virtualNetworkLink_backup_rsv", - "count": "[length(variables('privatelink_backup_names'))]" - }, - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_backup_names')[copyIndex()], format('{0}-link', variables('privatelink_backup_names')[copyIndex()]))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_backup_names')[copyIndex()])]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_avd_global_name'), format('{0}-link', variables('privatelink_avd_global_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_avd_global_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_monitor_name'), format('{0}-link', variables('privatelink_monitor_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_monitor_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_oms_opinsights_name'), format('{0}-link', variables('privatelink_oms_opinsights_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_oms_opinsights_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_ods_opinsights_name'), format('{0}-link', variables('privatelink_ods_opinsights_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_ods_opinsights_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_agentsvc_azure_automation_name'), format('{0}-link', variables('privatelink_agentsvc_azure_automation_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_agentsvc_azure_automation_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_azure_automation_name'), format('{0}-link', variables('privatelink_azure_automation_name')))]", - "location": "global", - "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" - } + "name": "virtualNetworkLinks", + "count": "[length(variables('virtualNetworks'))]", + "mode": "serial", + "batchSize": 1 }, - "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_azure_automation_name'))]" - ] - }, - { - "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", - "apiVersion": "2018-09-01", - "name": "[format('{0}/{1}', variables('privatelink_blob_name'), format('{0}-link', variables('privatelink_blob_name')))]", - "location": "global", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('deploy-virtual-network-links-{0}-{1}', copyIndex(), parameters('deploymentNameSuffix'))]", "properties": { - "registrationEnabled": false, - "virtualNetwork": { - "id": "[resourceId(parameters('vnetSubscriptionId'), parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]" + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateDnsZoneNames": { + "value": "[variables('privateDnsZoneNames')]" + }, + "virtualNetworkName": { + "value": "[variables('virtualNetworks')[copyIndex()].name]" + }, + "virtualNetworkResourceGroupName": { + "value": "[variables('virtualNetworks')[copyIndex()].resourceGroupName]" + }, + "virtualNetworkSubscriptionId": { + "value": "[variables('virtualNetworks')[copyIndex()].subscriptionId]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "3715367426949365008" + } + }, + "parameters": { + "privateDnsZoneNames": { + "type": "array" + }, + "virtualNetworkName": { + "type": "string" + }, + "virtualNetworkResourceGroupName": { + "type": "string" + }, + "virtualNetworkSubscriptionId": { + "type": "string" + } + }, + "resources": [ + { + "copy": { + "name": "virtualNetworkLinks", + "count": "[length(parameters('privateDnsZoneNames'))]" + }, + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2018-09-01", + "name": "[format('{0}/{1}', parameters('privateDnsZoneNames')[copyIndex()], parameters('virtualNetworkName'))]", + "location": "global", + "properties": { + "registrationEnabled": false, + "virtualNetwork": { + "id": "[resourceId(parameters('virtualNetworkSubscriptionId'), parameters('virtualNetworkResourceGroupName'), 'Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]" + } + } + } + ] } }, "dependsOn": [ - "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_blob_name'))]" + "privateDnsZones" ] } ], "outputs": { "agentsvcPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_agentsvc_azure_automation_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.agentsvc.azure-automation')))[0])]" }, "automationPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_azure_automation_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.azure-automation')))[0])]" }, "avdGlobalPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_avd_global_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink-global.wvd')))[0])]" }, "avdPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_avd_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.wvd')))[0])]" }, "backupPrivateDnsZoneIds": { "type": "array", "copy": { - "count": "[length(variables('privatelink_backup_names'))]", - "input": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_backup_names')[copyIndex()])]" + "count": "[length(variables('privateDnsZoneNames_Backup'))]", + "input": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneNames_Backup')[copyIndex()])]" } }, "blobPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_blob_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.blob')))[0])]" }, "filePrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_file_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.file')))[0])]" }, "keyvaultDnsPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_keyvaultDns_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.vaultcore')))[0])]" }, "monitorPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_monitor_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.monitor')))[0])]" }, "odsPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_ods_opinsights_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.ods.opinsights')))[0])]" }, "omsPrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_oms_opinsights_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.oms.opinsights')))[0])]" }, "queuePrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_queue_name'))]" - }, - "storagePrivateDnsZoneId": { - "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_blob_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.queue')))[0])]" }, "tablePrivateDnsZoneId": { "type": "string", - "value": "[resourceId('Microsoft.Network/privateDnsZones', variables('privatelink_table_name'))]" + "value": "[resourceId('Microsoft.Network/privateDnsZones', filter(variables('privateDnsZoneNames'), lambda('name', contains(lambdaVariables('name'), 'privatelink.table')))[0])]" } } } }, "dependsOn": [ - "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix')))]" + "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), variables('hubResourceGroupName')), 'Microsoft.Resources/deployments', format('deploy-vnet-hub-{0}', parameters('deploymentNameSuffix')))]", + "spokeNetworks" ] }, { @@ -4440,7 +4229,7 @@ "value": "[parameters('resourcePrefix')]" }, "subnetResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[1].subscriptionId, variables('spokes')[1].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[1].name, parameters('deploymentNameSuffix'))), '2022-09-01').outputs.subnetResourceId.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[0].subscriptionId, variables('spokes')[0].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[0].name, parameters('deploymentNameSuffix'))), '2022-09-01').outputs.subnetResourceId.value]" }, "tags": { "value": "[variables('calculatedTags')]" @@ -5095,7 +4884,7 @@ "value": "[parameters('resourcePrefix')]" }, "subnetResourceId": { - "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[1].subscriptionId, variables('spokes')[1].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[1].name, parameters('deploymentNameSuffix'))), '2022-09-01').outputs.subnetResourceId.value]" + "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('spokes')[0].subscriptionId, variables('spokes')[0].resourceGroupName), 'Microsoft.Resources/deployments', format('deploy-vnet-{0}-{1}', variables('spokes')[0].name, parameters('deploymentNameSuffix'))), '2022-09-01').outputs.subnetResourceId.value]" } }, "template": { diff --git a/src/bicep/modules/private-dns.bicep b/src/bicep/modules/private-dns.bicep index 1dde40334..da69f59fe 100644 --- a/src/bicep/modules/private-dns.bicep +++ b/src/bicep/modules/private-dns.bicep @@ -3,306 +3,93 @@ Copyright (c) Microsoft Corporation. Licensed under the MIT License. */ -@description('The name of the virtual network the private dns zones will be connected to') -param vnetName string - -@description('The name of the the resource group where the virtual network exists') -param vnetResourceGroup string = resourceGroup().name - -@description('The subscription id of the subscription the virtual network exists in') -param vnetSubscriptionId string = subscription().subscriptionId - -@description('The tags that will be associated to the resources') +param deployIdentity bool +param deploymentNameSuffix string +param hubVirtualNetworkName string +param hubVirtualNetworkResourceGroupName string +param hubVirtualNetworkSubscriptionId string +param identityVirtualNetworkName string +param identityVirtualNetworkResourceGroupName string +param identityVirtualNetworkSubscriptionId string param tags object var cloudSuffix = replace(replace(environment().resourceManager, 'https://management.', ''), '/', '') var locations = (loadJsonContent('../data/locations.json'))[environment().name] -var privatelink_agentsvc_azure_automation_name = 'privatelink.agentsvc.azure-automation.${privatelink_azure_automation_suffixes[environment().name] ?? cloudSuffix}' -var privatelink_azure_automation_suffixes = { +var privateDnsZoneNames = union([ + 'privatelink.agentsvc.azure-automation.${privateDnsZoneSuffixes_AzureAutomation[environment().name] ?? cloudSuffix}' + 'privatelink.azure-automation.${privateDnsZoneSuffixes_AzureAutomation[environment().name] ?? cloudSuffix}' + 'privatelink.wvd.${privateDnsZoneSuffixes_AzureVirtualDesktop[environment().name] ?? cloudSuffix}' + 'privatelink-global.wvd.${privateDnsZoneSuffixes_AzureVirtualDesktop[environment().name] ?? cloudSuffix}' + 'privatelink.file.${environment().suffixes.storage}' + 'privatelink.queue.${environment().suffixes.storage}' + 'privatelink.table.${environment().suffixes.storage}' + 'privatelink.blob.${environment().suffixes.storage}' + replace('privatelink${environment().suffixes.keyvaultDns}', 'vault', 'vaultcore') + 'privatelink.monitor.${privateDnsZoneSuffixes_Monitor[environment().name] ?? cloudSuffix}' + 'privatelink.ods.opinsights.${privateDnsZoneSuffixes_Monitor[environment().name] ?? cloudSuffix}' + 'privatelink.oms.opinsights.${privateDnsZoneSuffixes_Monitor[environment().name] ?? cloudSuffix}' +], privateDnsZoneNames_Backup) +var privateDnsZoneNames_Backup = [for location in items(locations): 'privatelink.${location.value.recoveryServicesGeo}.backup.${privateDnsZoneSuffixes_Backup[environment().name] ?? cloudSuffix}'] +var privateDnsZoneSuffixes_AzureAutomation = { AzureCloud: 'net' AzureUSGovernment: 'us' } -var privatelink_azure_automation_name = 'privatelink.azure-automation.${privatelink_azure_automation_suffixes[environment().name] ?? cloudSuffix}' -var privatelink_avd_suffixes = { +var privateDnsZoneSuffixes_AzureVirtualDesktop = { AzureCloud: 'microsoft.com' AzureUSGovernment: 'azure.us' } -var privatelink_avd_name = 'privatelink.wvd.${privatelink_avd_suffixes[environment().name] ?? cloudSuffix}' -var privatelink_avd_global_name = 'privatelink-global.wvd.${privatelink_avd_suffixes[environment().name] ?? cloudSuffix}' -var privatelink_backup_suffixes = { +var privateDnsZoneSuffixes_Backup = { AzureCloud: 'windowsazure.com' AzureUSGovernment: 'windowsazure.us' } -var privatelink_backup_names = [for location in items(locations): 'privatelink.${location.value.recoveryServicesGeo}.backup.${privatelink_backup_suffixes[environment().name] ?? cloudSuffix}'] -var privatelink_file_name = 'privatelink.file.${environment().suffixes.storage}' -var privatelink_queue_name = 'privatelink.queue.${environment().suffixes.storage}' -var privatelink_table_name = 'privatelink.table.${environment().suffixes.storage}' -var privatelink_blob_name = 'privatelink.blob.${environment().suffixes.storage}' -var privatelink_keyvaultDns_name = replace('privatelink${environment().suffixes.keyvaultDns}', 'vault', 'vaultcore') -var privatelink_monitor_suffixes = { +var privateDnsZoneSuffixes_Monitor = { AzureCloud: 'azure.com' AzureUSGovernment: 'azure.us' } -var privatelink_monitor_name = 'privatelink.monitor.${privatelink_monitor_suffixes[environment().name] ?? cloudSuffix}' -var privatelink_ods_opinsights_name = 'privatelink.ods.opinsights.${privatelink_monitor_suffixes[environment().name] ?? cloudSuffix}' -var privatelink_oms_opinsights_name = 'privatelink.oms.opinsights.${privatelink_monitor_suffixes[environment().name] ?? cloudSuffix}' - -resource privateDnsZone_avd 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_avd_name - location: 'global' - tags: tags -} - -resource privateDnsZone_avd_global 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_avd_global_name - location: 'global' - tags: tags -} +var virtualNetworks = union([ + { + name: hubVirtualNetworkName + resourceGroupName: hubVirtualNetworkResourceGroupName + subscriptionId: hubVirtualNetworkSubscriptionId + } +], deployIdentity ? [ + { + name: identityVirtualNetworkName + resourceGroupName: identityVirtualNetworkResourceGroupName + subscriptionId: identityVirtualNetworkSubscriptionId + } +] : []) -resource privateDnsZone_backup_rsv 'Microsoft.Network/privateDnsZones@2018-09-01' = [for name in privatelink_backup_names: if (!(contains(name, '..'))) { +resource privateDnsZones 'Microsoft.Network/privateDnsZones@2018-09-01' = [for name in privateDnsZoneNames: { name: name location: 'global' tags: tags }] -resource privateDnsZone_file 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_file_name - location: 'global' - tags: tags -} - -resource privateDnsZone_queue 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_queue_name - location: 'global' - tags: tags -} - -resource privateDnsZone_table 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_table_name - location: 'global' - tags: tags -} - -resource privateDnsZone_keyvaultDns 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_keyvaultDns_name - location: 'global' - tags: tags -} - -resource privateDnsZone_monitor 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_monitor_name - location: 'global' - tags: tags -} - -resource privateDnsZone_oms_opinsights 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_oms_opinsights_name - location: 'global' - tags: tags -} - -resource privateDnsZone_ods_opinsights 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_ods_opinsights_name - location: 'global' - tags: tags -} - -resource privateDnsZone_agentsvc_azure_automation 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_agentsvc_azure_automation_name - location: 'global' - tags: tags -} - -resource privateDnsZone_azure_automation 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_azure_automation_name - location: 'global' - tags: tags -} - -resource privateDnsZone_blob 'Microsoft.Network/privateDnsZones@2018-09-01' = { - name: privatelink_blob_name - location: 'global' - tags: tags -} - -resource virtualNetworkLink_avd 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_avd_name}-link' - parent: privateDnsZone_avd - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_file 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_file_name}-link' - parent: privateDnsZone_file - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_table 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_table_name}-link' - parent: privateDnsZone_table - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_keyvaultDns 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_keyvaultDns_name}-link' - parent: privateDnsZone_keyvaultDns - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } +@batchSize(1) +module virtualNetworkLinks 'virtual-network-link.bicep' = [for (virtualNetwork, i) in virtualNetworks:{ + name: 'deploy-virtual-network-links-${i}-${deploymentNameSuffix}' + params: { + privateDnsZoneNames: privateDnsZoneNames + virtualNetworkName: virtualNetwork.name + virtualNetworkResourceGroupName: virtualNetwork.resourceGroupName + virtualNetworkSubscriptionId: virtualNetwork.subscriptionId } - dependsOn: [] -} - -resource virtualNetworkLink_queue 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_queue_name}-link' - parent: privateDnsZone_queue - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_backup_rsv 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = [for (name, i) in privatelink_backup_names: { - name: '${name}-link' - parent: privateDnsZone_backup_rsv[i] - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] + dependsOn: [ + privateDnsZones + ] }] -resource virtualNetworkLink_avd_global 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_avd_global_name}-link' - parent: privateDnsZone_avd_global - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_monitor 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_monitor_name}-link' - parent: privateDnsZone_monitor - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_oms_opinsights 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_oms_opinsights_name}-link' - parent: privateDnsZone_oms_opinsights - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_ods_opinsights 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_ods_opinsights_name}-link' - parent: privateDnsZone_ods_opinsights - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -resource virtualNetworkLink_agentsvc_azure_automation 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_agentsvc_azure_automation_name}-link' - parent: privateDnsZone_agentsvc_azure_automation - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } -} - -resource virtualNetworkLink_azure_automation 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_azure_automation_name}-link' - parent: privateDnsZone_azure_automation - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } -} - -resource virtualNetworkLink_blob 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = { - name: '${privatelink_blob_name}-link' - parent: privateDnsZone_blob - location: 'global' - properties: { - registrationEnabled: false - virtualNetwork: { - id: resourceId(vnetSubscriptionId, vnetResourceGroup, 'Microsoft.Network/virtualNetworks', vnetName) - } - } - dependsOn: [] -} - -output agentsvcPrivateDnsZoneId string = privateDnsZone_agentsvc_azure_automation.id -output automationPrivateDnsZoneId string = privateDnsZone_azure_automation.id -output avdGlobalPrivateDnsZoneId string = privateDnsZone_avd_global.id -output avdPrivateDnsZoneId string = privateDnsZone_avd.id -output backupPrivateDnsZoneIds array = [for (name, i) in privatelink_backup_names: privateDnsZone_backup_rsv[i].id] -output blobPrivateDnsZoneId string = privateDnsZone_blob.id -output filePrivateDnsZoneId string = privateDnsZone_file.id -output keyvaultDnsPrivateDnsZoneId string = privateDnsZone_keyvaultDns.id -output monitorPrivateDnsZoneId string = privateDnsZone_monitor.id -output odsPrivateDnsZoneId string = privateDnsZone_ods_opinsights.id -output omsPrivateDnsZoneId string = privateDnsZone_oms_opinsights.id -output queuePrivateDnsZoneId string = privateDnsZone_queue.id -output storagePrivateDnsZoneId string = privateDnsZone_blob.id -output tablePrivateDnsZoneId string = privateDnsZone_table.id +output agentsvcPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.agentsvc.azure-automation'))[0]) +output automationPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.azure-automation'))[0]) +output avdGlobalPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink-global.wvd'))[0]) +output avdPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.wvd'))[0]) +output backupPrivateDnsZoneIds array = [for name in privateDnsZoneNames_Backup: resourceId('Microsoft.Network/privateDnsZones', name)] +output blobPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.blob'))[0]) +output filePrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.file'))[0]) +output keyvaultDnsPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.vaultcore'))[0]) +output monitorPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.monitor'))[0]) +output odsPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.ods.opinsights'))[0]) +output omsPrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.oms.opinsights'))[0]) +output queuePrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.queue'))[0]) +output tablePrivateDnsZoneId string = resourceId('Microsoft.Network/privateDnsZones', filter(privateDnsZoneNames, name => contains(name, 'privatelink.table'))[0]) diff --git a/src/bicep/modules/virtual-network-link.bicep b/src/bicep/modules/virtual-network-link.bicep new file mode 100644 index 000000000..55b1cdf38 --- /dev/null +++ b/src/bicep/modules/virtual-network-link.bicep @@ -0,0 +1,20 @@ +param privateDnsZoneNames array +param virtualNetworkName string +param virtualNetworkResourceGroupName string +param virtualNetworkSubscriptionId string + +resource privateDnsZones 'Microsoft.Network/privateDnsZones@2018-09-01' existing = [for (name, i) in privateDnsZoneNames: { + name: name +}] + +resource virtualNetworkLinks 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2018-09-01' = [for (name, i) in privateDnsZoneNames: { + name: virtualNetworkName + parent: privateDnsZones[i] + location: 'global' + properties: { + registrationEnabled: false + virtualNetwork: { + id: resourceId(virtualNetworkSubscriptionId, virtualNetworkResourceGroupName, 'Microsoft.Network/virtualNetworks', virtualNetworkName) + } + } +}]