From e5b3141d2789ae5626c12abd2c71f9bc83f3dede Mon Sep 17 00:00:00 2001 From: Prajwal D C Date: Mon, 23 Mar 2026 10:20:40 +0530 Subject: [PATCH] fix: Fixed issues related to intermittent WAF deployment failures --- infra/main.bicep | 124 ++- infra/main.json | 2652 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 2169 insertions(+), 607 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index fddd01bc..36b3b265 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -771,36 +771,46 @@ module avmAiServices 'modules/account/aifoundry.bicep' = { // WAF related parameters publicNetworkAccess: (enablePrivateNetworking) ? 'Disabled' : 'Enabled' //publicNetworkAccess: 'Enabled' // Always enabled for AI Services - privateEndpoints: (enablePrivateNetworking && empty(existingProjectResourceId)) - ? [ - { - name: 'pep-aiservices-${solutionSuffix}' - customNetworkInterfaceName: 'nic-aiservices-${solutionSuffix}' - privateEndpointResourceId: virtualNetwork!.outputs.resourceId - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [ - { - name: 'ai-services-dns-zone-cognitiveservices' - privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId - } - { - name: 'ai-services-dns-zone-openai' - privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.openAI]!.outputs.resourceId - } - { - name: 'ai-services-dns-zone-aiservices' - privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.aiServices]!.outputs.resourceId - } - { - name: 'ai-services-dns-zone-contentunderstanding' - privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.contentUnderstanding]!.outputs.resourceId - } - ] - } - subnetResourceId: virtualNetwork!.outputs.backendSubnetResourceId // Use the backend subnet - } - ] - : [] + } +} + +module cognitiveServicePrivateEndpoint 'br/public:avm/res/network/private-endpoint:0.8.1' = if (enablePrivateNetworking && empty(existingProjectResourceId)) { + name: take('avm.res.network.private-endpoint.${solutionSuffix}', 64) + params: { + name: 'pep-aiservices-${solutionSuffix}' + location: location + tags: tags + customNetworkInterfaceName: 'nic-aiservices-${solutionSuffix}' + privateLinkServiceConnections: [ + { + name: 'pep-aiservices-${solutionSuffix}-cognitiveservices-connection' + properties: { + privateLinkServiceId: avmAiServices.outputs.resourceId + groupIds: ['account'] + } + } + ] + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { + name: 'ai-services-dns-zone-cognitiveservices' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId + } + { + name: 'ai-services-dns-zone-openai' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.openAI]!.outputs.resourceId + } + { + name: 'ai-services-dns-zone-aiservices' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.aiServices]!.outputs.resourceId + } + { + name: 'ai-services-dns-zone-contentunderstanding' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.contentUnderstanding]!.outputs.resourceId + } + ] + } + subnetResourceId: virtualNetwork!.outputs.backendSubnetResourceId } } @@ -838,28 +848,38 @@ module avmAiServices_cu 'br/public:avm/res/cognitive-services/account:0.13.2' = ] publicNetworkAccess: (enablePrivateNetworking) ? 'Disabled' : 'Enabled' - privateEndpoints: (enablePrivateNetworking) - ? [ - { - name: 'pep-aicu-${solutionSuffix}' - customNetworkInterfaceName: 'nic-aicu-${solutionSuffix}' - privateEndpointResourceId: virtualNetwork!.outputs.resourceId - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [ - { - name: 'aicu-dns-zone-cognitiveservices' - privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId - } - { - name: 'aicu-dns-zone-contentunderstanding' - privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.contentUnderstanding]!.outputs.resourceId - } - ] - } - subnetResourceId: virtualNetwork!.outputs.backendSubnetResourceId // Use the backend subnet - } - ] - : [] + } +} + +module contentUnderstandingPrivateEndpoint 'br/public:avm/res/network/private-endpoint:0.8.1' = if (enablePrivateNetworking) { + name: take('avm.res.network.private-endpoint.aicu-${solutionSuffix}', 64) + params: { + name: 'pep-aicu-${solutionSuffix}' + location: location + tags: tags + customNetworkInterfaceName: 'nic-aicu-${solutionSuffix}' + privateLinkServiceConnections: [ + { + name: 'pep-aicu-${solutionSuffix}-cognitiveservices-connection' + properties: { + privateLinkServiceId: avmAiServices_cu.outputs.resourceId + groupIds: ['account'] + } + } + ] + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { + name: 'aicu-dns-zone-cognitiveservices' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId + } + { + name: 'aicu-dns-zone-contentunderstanding' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.contentUnderstanding]!.outputs.resourceId + } + ] + } + subnetResourceId: virtualNetwork!.outputs.backendSubnetResourceId } } diff --git a/infra/main.json b/infra/main.json index 4a195a2b..574b0c91 100644 --- a/infra/main.json +++ b/infra/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "4821257159531769907" + "version": "0.41.2.15936", + "templateHash": "9054063171311777669" }, "name": "Content Processing Solution Accelerator", "description": "Bicep template to deploy the Content Processing Solution Accelerator with AVM compliance." @@ -350,8 +350,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "637986880127430337" + "version": "0.41.2.15936", + "templateHash": "4055670269816744382" } }, "definitions": { @@ -19227,8 +19227,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "3741201002953968110" + "version": "0.41.2.15936", + "templateHash": "6350282028214740152" } }, "parameters": { @@ -23233,8 +23233,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "10844547551448610415" + "version": "0.41.2.15936", + "templateHash": "13929816981891754138" } }, "parameters": { @@ -23825,8 +23825,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "7885429842089695683" + "version": "0.41.2.15936", + "templateHash": "17694195801715707119" }, "name": "Container Registry Module" }, @@ -35178,8 +35178,8 @@ "avmContainerApp", "avmContainerApp_API", "avmManagedIdentity", - "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageQueue)]", "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageBlob)]", + "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageQueue)]", "virtualNetwork" ] }, @@ -35280,8 +35280,7 @@ } ] }, - "publicNetworkAccess": "[if(parameters('enablePrivateNetworking'), createObject('value', 'Disabled'), createObject('value', 'Enabled'))]", - "privateEndpoints": "[if(and(parameters('enablePrivateNetworking'), empty(variables('existingProjectResourceId'))), createObject('value', createArray(createObject('name', format('pep-aiservices-{0}', variables('solutionSuffix')), 'customNetworkInterfaceName', format('nic-aiservices-{0}', variables('solutionSuffix')), 'privateEndpointResourceId', reference('virtualNetwork').outputs.resourceId.value, 'privateDnsZoneGroup', createObject('privateDnsZoneGroupConfigs', createArray(createObject('name', 'ai-services-dns-zone-cognitiveservices', 'privateDnsZoneResourceId', reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)).outputs.resourceId.value), createObject('name', 'ai-services-dns-zone-openai', 'privateDnsZoneResourceId', reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)).outputs.resourceId.value), createObject('name', 'ai-services-dns-zone-aiservices', 'privateDnsZoneResourceId', reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)).outputs.resourceId.value), createObject('name', 'ai-services-dns-zone-contentunderstanding', 'privateDnsZoneResourceId', reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)).outputs.resourceId.value))), 'subnetResourceId', reference('virtualNetwork').outputs.backendSubnetResourceId.value))), createObject('value', createArray()))]" + "publicNetworkAccess": "[if(parameters('enablePrivateNetworking'), createObject('value', 'Disabled'), createObject('value', 'Enabled'))]" }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -35290,8 +35289,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "7557665774149769517" + "version": "0.41.2.15936", + "templateHash": "11676375352983709807" }, "name": "Cognitive Services", "description": "This module deploys a Cognitive Service." @@ -36540,8 +36539,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "6588447351857766372" + "version": "0.41.2.15936", + "templateHash": "8716336912243881623" } }, "definitions": { @@ -38349,8 +38348,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "14939823368517410024" + "version": "0.41.2.15936", + "templateHash": "10989408486030617267" } }, "definitions": { @@ -38503,8 +38502,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "13151306134286549002" + "version": "0.41.2.15936", + "templateHash": "7933643033523871028" } }, "definitions": { @@ -38721,8 +38720,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "6588447351857766372" + "version": "0.41.2.15936", + "templateHash": "8716336912243881623" } }, "definitions": { @@ -40530,8 +40529,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "14939823368517410024" + "version": "0.41.2.15936", + "templateHash": "10989408486030617267" } }, "definitions": { @@ -40684,8 +40683,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.40.2.10011", - "templateHash": "13151306134286549002" + "version": "0.41.2.15936", + "templateHash": "7933643033523871028" } }, "definitions": { @@ -40925,18 +40924,14 @@ "dependsOn": [ "avmContainerApp", "avmManagedIdentity", - "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)]", - "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]", - "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)]", - "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]", - "logAnalyticsWorkspace", - "virtualNetwork" + "logAnalyticsWorkspace" ] }, - "avmAiServices_cu": { + "cognitiveServicePrivateEndpoint": { + "condition": "[and(parameters('enablePrivateNetworking'), empty(variables('existingProjectResourceId')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2025-04-01", - "name": "[take(format('avm.res.cognitive-services.account.content-understanding.{0}', variables('solutionSuffix')), 64)]", + "name": "[take(format('avm.res.network.private-endpoint.{0}', variables('solutionSuffix')), 64)]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -40944,57 +40939,55 @@ "mode": "Incremental", "parameters": { "name": { - "value": "[format('aicu-{0}', variables('solutionSuffix'))]" + "value": "[format('pep-aiservices-{0}', variables('solutionSuffix'))]" }, "location": { - "value": "[parameters('contentUnderstandingLocation')]" - }, - "sku": { - "value": "S0" - }, - "managedIdentities": { - "value": { - "systemAssigned": false, - "userAssignedResourceIds": [ - "[reference('avmManagedIdentity').outputs.resourceId.value]" - ] - } - }, - "kind": { - "value": "AIServices" + "value": "[parameters('location')]" }, "tags": { - "value": { - "app": "[variables('solutionSuffix')]", - "location": "[parameters('location')]" - } - }, - "customSubDomainName": { - "value": "[format('aicu-{0}', variables('solutionSuffix'))]" - }, - "disableLocalAuth": { - "value": true - }, - "enableTelemetry": { - "value": "[parameters('enableTelemetry')]" + "value": "[parameters('tags')]" }, - "networkAcls": { - "value": { - "bypass": "AzureServices", - "defaultAction": "Allow" - } + "customNetworkInterfaceName": { + "value": "[format('nic-aiservices-{0}', variables('solutionSuffix'))]" }, - "roleAssignments": { + "privateLinkServiceConnections": { "value": [ { - "principalId": "[reference('avmContainerApp').outputs.systemAssignedMIPrincipalId.value]", - "roleDefinitionIdOrName": "a97b65f3-24c7-4388-baec-2e87135dc908", - "principalType": "ServicePrincipal" + "name": "[format('pep-aiservices-{0}-cognitiveservices-connection', variables('solutionSuffix'))]", + "properties": { + "privateLinkServiceId": "[reference('avmAiServices').outputs.resourceId.value]", + "groupIds": [ + "account" + ] + } } ] }, - "publicNetworkAccess": "[if(parameters('enablePrivateNetworking'), createObject('value', 'Disabled'), createObject('value', 'Enabled'))]", - "privateEndpoints": "[if(parameters('enablePrivateNetworking'), createObject('value', createArray(createObject('name', format('pep-aicu-{0}', variables('solutionSuffix')), 'customNetworkInterfaceName', format('nic-aicu-{0}', variables('solutionSuffix')), 'privateEndpointResourceId', reference('virtualNetwork').outputs.resourceId.value, 'privateDnsZoneGroup', createObject('privateDnsZoneGroupConfigs', createArray(createObject('name', 'aicu-dns-zone-cognitiveservices', 'privateDnsZoneResourceId', reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)).outputs.resourceId.value), createObject('name', 'aicu-dns-zone-contentunderstanding', 'privateDnsZoneResourceId', reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)).outputs.resourceId.value))), 'subnetResourceId', reference('virtualNetwork').outputs.backendSubnetResourceId.value))), createObject('value', createArray()))]" + "privateDnsZoneGroup": { + "value": { + "privateDnsZoneGroupConfigs": [ + { + "name": "ai-services-dns-zone-cognitiveservices", + "privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)).outputs.resourceId.value]" + }, + { + "name": "ai-services-dns-zone-openai", + "privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)).outputs.resourceId.value]" + }, + { + "name": "ai-services-dns-zone-aiservices", + "privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)).outputs.resourceId.value]" + }, + { + "name": "ai-services-dns-zone-contentunderstanding", + "privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)).outputs.resourceId.value]" + } + ] + } + }, + "subnetResourceId": { + "value": "[reference('virtualNetwork').outputs.backendSubnetResourceId.value]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -41003,384 +40996,1165 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.37.4.10188", - "templateHash": "9381727816193702843" + "version": "0.30.23.60470", + "templateHash": "2541425927059591098" }, - "name": "Cognitive Services", - "description": "This module deploys a Cognitive Service." + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" }, "definitions": { - "privateEndpointOutputType": { + "privateDnsZoneGroupType": { "type": "object", "properties": { "name": { - "type": "string", - "metadata": { - "description": "The name of the private endpoint." - } - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the private endpoint." - } - }, - "groupId": { "type": "string", "nullable": true, "metadata": { - "description": "The group Id for the private endpoint Group." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "FQDN that resolves to private endpoint IP address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "A list of private IP addresses of the private endpoint." - } - } - } - }, - "metadata": { - "description": "The custom DNS configurations of the private endpoint." + "description": "Optional. The name of the Private DNS Zone Group." } }, - "networkInterfaceResourceIds": { + "privateDnsZoneGroupConfigs": { "type": "array", "items": { - "type": "string" + "$ref": "#/definitions/privateDnsZoneGroupConfigType" }, "metadata": { - "description": "The IDs of the network interfaces associated with the private endpoint." + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." } } - }, - "metadata": { - "__bicep_export!": true, - "description": "The type for the private endpoint output." } }, - "deploymentType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of cognitive service account deployment." - } - }, - "model": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of Cognitive Services account deployment model." - } - }, - "format": { - "type": "string", - "metadata": { - "description": "Required. The format of Cognitive Services account deployment model." - } - }, - "version": { - "type": "string", - "metadata": { - "description": "Required. The version of Cognitive Services account deployment model." - } + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." } }, - "metadata": { - "description": "Required. Properties of Cognitive Services account deployment model." - } - }, - "sku": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource model definition representing SKU." - } - }, - "capacity": { - "type": "int", - "nullable": true, - "metadata": { - "description": "Optional. The capacity of the resource model definition representing SKU." - } - }, - "tier": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The tier of the resource model definition representing SKU." - } - }, - "size": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The size of the resource model definition representing SKU." - } - }, - "family": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The family of the resource model definition representing SKU." - } + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, - "nullable": true, - "metadata": { - "description": "Optional. The resource model definition representing SKU." - } - }, - "raiPolicyName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of RAI policy." - } - }, - "versionUpgradeOption": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The version upgrade option." + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } } } }, - "metadata": { - "__bicep_export!": true, - "description": "The type for a cognitive services account deployment." - } + "nullable": true }, - "endpointType": { + "lockType": { "type": "object", "properties": { "name": { "type": "string", "nullable": true, "metadata": { - "description": "Type of the endpoint." + "description": "Optional. Specify the name of lock." } }, - "endpoint": { + "kind": { "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], "nullable": true, "metadata": { - "description": "The endpoint URI." + "description": "Optional. Specify the type of lock." } } }, - "metadata": { - "__bicep_export!": true, - "description": "The type for a cognitive services account endpoint." - } + "nullable": true }, - "secretsExportConfigurationType": { - "type": "object", - "properties": { - "keyVaultResourceId": { - "type": "string", - "metadata": { - "description": "Required. The key vault name where to store the keys and connection strings generated by the modules." - } - }, - "accessKey1Name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name for the accessKey1 secret to create." - } - }, - "accessKey2Name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name for the accessKey2 secret to create." + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } } } }, - "metadata": { - "__bicep_export!": true, - "description": "The type of the secrets exported to the provided Key Vault." - } + "nullable": true }, - "commitmentPlanType": { - "type": "object", - "properties": { - "autoRenew": { - "type": "bool", - "metadata": { - "description": "Required. Whether the plan should auto-renew at the end of the current commitment period." - } - }, - "current": { - "type": "object", + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, "properties": { - "count": { - "type": "int", - "metadata": { - "description": "Required. The number of committed instances (e.g., number of containers or cores)." + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } } }, - "tier": { - "type": "string", - "metadata": { - "description": "Required. The tier of the commitment plan (e.g., T1, T2)." - } + "metadata": { + "description": "Required. Properties of private link service connection." } - }, - "metadata": { - "description": "Required. The current commitment configuration." - } - }, - "hostingModel": { - "type": "string", - "metadata": { - "description": "Required. The hosting model for the commitment plan. (e.g., DisconnectedContainer, ConnectedContainer, ProvisionedWeb, Web)." } - }, - "planType": { - "type": "string", - "metadata": { - "description": "Required. The plan type indicating which capability the plan applies to (e.g., NTTS, STT, CUSTOMSTT, ADDON)." - } - }, - "commitmentPlanGuid": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The unique identifier of an existing commitment plan to update. Set to null to create a new plan." - } - }, - "next": { - "type": "object", + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, "properties": { - "count": { - "type": "int", - "metadata": { - "description": "Required. The number of committed instances for the next period." + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } } }, - "tier": { - "type": "string", - "metadata": { - "description": "Required. The tier for the next commitment period." - } + "metadata": { + "description": "Required. Properties of private link service connection." } - }, - "nullable": true, - "metadata": { - "description": "Optional. The configuration of the next commitment period, if scheduled." } } }, - "metadata": { - "__bicep_export!": true, - "description": "The type for a disconnected container commitment plan." - } + "nullable": true }, - "networkInjectionType": { - "type": "object", - "properties": { - "scenario": { - "type": "string", - "allowedValues": [ - "agent", - "none" - ], - "metadata": { - "description": "Required. The scenario for the network injection." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. The Resource ID of the subnet on the Virtual Network on which to inject." - } - }, - "useMicrosoftManagedNetwork": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Whether to use Microsoft Managed Network. Defaults to false." + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } } } }, - "metadata": { - "__bicep_export!": true, - "description": "Type for network configuration in AI Foundry where virtual network injection occurs to secure scenarios like Agents entirely within a private network." - } + "nullable": true }, - "_1.secretSetOutputType": { + "privateDnsZoneGroupConfigType": { "type": "object", "properties": { - "secretResourceId": { - "type": "string", - "metadata": { - "description": "The resourceId of the exported secret." - } - }, - "secretUri": { + "name": { "type": "string", + "nullable": true, "metadata": { - "description": "The secret URI of the exported secret." + "description": "Optional. The name of the private DNS zone group config." } }, - "secretUriWithVersion": { + "privateDnsZoneResourceId": { "type": "string", "metadata": { - "description": "The secret URI with version of the exported secret." + "description": "Required. The resource id of the private DNS zone." } } }, "metadata": { - "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", "__bicep_imported_from!": { - "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.6.0" + "sourceTemplate": "private-dns-zone-group/main.bicep" } } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } }, - "_2.lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.8.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "12329174801198479603" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "avmAiServices", + "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)]", + "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]", + "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]", + "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)]", + "virtualNetwork" + ] + }, + "avmAiServices_cu": { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2025-04-01", + "name": "[take(format('avm.res.cognitive-services.account.content-understanding.{0}', variables('solutionSuffix')), 64)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('aicu-{0}', variables('solutionSuffix'))]" + }, + "location": { + "value": "[parameters('contentUnderstandingLocation')]" + }, + "sku": { + "value": "S0" + }, + "managedIdentities": { + "value": { + "systemAssigned": false, + "userAssignedResourceIds": [ + "[reference('avmManagedIdentity').outputs.resourceId.value]" + ] + } + }, + "kind": { + "value": "AIServices" + }, + "tags": { + "value": { + "app": "[variables('solutionSuffix')]", + "location": "[parameters('location')]" + } + }, + "customSubDomainName": { + "value": "[format('aicu-{0}', variables('solutionSuffix'))]" + }, + "disableLocalAuth": { + "value": true + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "networkAcls": { + "value": { + "bypass": "AzureServices", + "defaultAction": "Allow" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "[reference('avmContainerApp').outputs.systemAssignedMIPrincipalId.value]", + "roleDefinitionIdOrName": "a97b65f3-24c7-4388-baec-2e87135dc908", + "principalType": "ServicePrincipal" + } + ] + }, + "publicNetworkAccess": "[if(parameters('enablePrivateNetworking'), createObject('value', 'Disabled'), createObject('value', 'Enabled'))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.37.4.10188", + "templateHash": "9381727816193702843" + }, + "name": "Cognitive Services", + "description": "This module deploys a Cognitive Service." + }, + "definitions": { + "privateEndpointOutputType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + } + }, + "groupId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "The group Id for the private endpoint Group." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "A list of private IP addresses of the private endpoint." + } + } + } + }, + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + } + }, + "networkInterfaceResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The type for the private endpoint output." + } + }, + "deploymentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of cognitive service account deployment." + } + }, + "model": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of Cognitive Services account deployment model." + } + }, + "format": { + "type": "string", + "metadata": { + "description": "Required. The format of Cognitive Services account deployment model." + } + }, + "version": { + "type": "string", + "metadata": { + "description": "Required. The version of Cognitive Services account deployment model." + } + } + }, + "metadata": { + "description": "Required. Properties of Cognitive Services account deployment model." + } + }, + "sku": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource model definition representing SKU." + } + }, + "capacity": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The capacity of the resource model definition representing SKU." + } + }, + "tier": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tier of the resource model definition representing SKU." + } + }, + "size": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The size of the resource model definition representing SKU." + } + }, + "family": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The family of the resource model definition representing SKU." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource model definition representing SKU." + } + }, + "raiPolicyName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of RAI policy." + } + }, + "versionUpgradeOption": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version upgrade option." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The type for a cognitive services account deployment." + } + }, + "endpointType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Type of the endpoint." + } + }, + "endpoint": { + "type": "string", + "nullable": true, + "metadata": { + "description": "The endpoint URI." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The type for a cognitive services account endpoint." + } + }, + "secretsExportConfigurationType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The key vault name where to store the keys and connection strings generated by the modules." + } + }, + "accessKey1Name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name for the accessKey1 secret to create." + } + }, + "accessKey2Name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name for the accessKey2 secret to create." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The type of the secrets exported to the provided Key Vault." + } + }, + "commitmentPlanType": { + "type": "object", + "properties": { + "autoRenew": { + "type": "bool", + "metadata": { + "description": "Required. Whether the plan should auto-renew at the end of the current commitment period." + } + }, + "current": { + "type": "object", + "properties": { + "count": { + "type": "int", + "metadata": { + "description": "Required. The number of committed instances (e.g., number of containers or cores)." + } + }, + "tier": { + "type": "string", + "metadata": { + "description": "Required. The tier of the commitment plan (e.g., T1, T2)." + } + } + }, + "metadata": { + "description": "Required. The current commitment configuration." + } + }, + "hostingModel": { + "type": "string", + "metadata": { + "description": "Required. The hosting model for the commitment plan. (e.g., DisconnectedContainer, ConnectedContainer, ProvisionedWeb, Web)." + } + }, + "planType": { + "type": "string", + "metadata": { + "description": "Required. The plan type indicating which capability the plan applies to (e.g., NTTS, STT, CUSTOMSTT, ADDON)." + } + }, + "commitmentPlanGuid": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The unique identifier of an existing commitment plan to update. Set to null to create a new plan." + } + }, + "next": { + "type": "object", + "properties": { + "count": { + "type": "int", + "metadata": { + "description": "Required. The number of committed instances for the next period." + } + }, + "tier": { + "type": "string", + "metadata": { + "description": "Required. The tier for the next commitment period." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The configuration of the next commitment period, if scheduled." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The type for a disconnected container commitment plan." + } + }, + "networkInjectionType": { + "type": "object", + "properties": { + "scenario": { + "type": "string", + "allowedValues": [ + "agent", + "none" + ], + "metadata": { + "description": "Required. The scenario for the network injection." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Resource ID of the subnet on the Virtual Network on which to inject." + } + }, + "useMicrosoftManagedNetwork": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Whether to use Microsoft Managed Network. Defaults to false." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "Type for network configuration in AI Foundry where virtual network injection occurs to secure scenarios like Agents entirely within a private network." + } + }, + "_1.secretSetOutputType": { + "type": "object", + "properties": { + "secretResourceId": { + "type": "string", + "metadata": { + "description": "The resourceId of the exported secret." + } + }, + "secretUri": { + "type": "string", + "metadata": { + "description": "The secret URI of the exported secret." + } + }, + "secretUriWithVersion": { + "type": "string", + "metadata": { + "description": "The secret URI with version of the exported secret." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.6.0" + } + } + }, + "_2.lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." } }, "notes": { @@ -43235,88 +44009,886 @@ ] } }, - "outputs": { - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group the private endpoint was deployed into." + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2024-05-01', 'full').location]" + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/customDnsConfigType" + }, + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "The resource IDs of the network interfaces associated with the private endpoint." + }, + "value": "[map(reference('privateEndpoint').networkInterfaces, lambda('nic', lambdaVariables('nic').id))]" + }, + "groupId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[coalesce(tryGet(tryGet(tryGet(tryGet(reference('privateEndpoint'), 'manualPrivateLinkServiceConnections'), 0, 'properties'), 'groupIds'), 0), tryGet(tryGet(tryGet(tryGet(reference('privateEndpoint'), 'privateLinkServiceConnections'), 0, 'properties'), 'groupIds'), 0))]" + } + } + } + }, + "dependsOn": [ + "cognitiveService" + ] + }, + "secretsExport": { + "condition": "[not(equals(parameters('secretsExportConfiguration'), null()))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-secrets-kv', uniqueString(deployment().name, parameters('location')))]", + "subscriptionId": "[split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/')[2]]", + "resourceGroup": "[split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/')[4]]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[last(split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/'))]" + }, + "secretsToSet": { + "value": "[union(createArray(), if(contains(parameters('secretsExportConfiguration'), 'accessKey1Name'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'accessKey1Name'), 'value', listKeys('cognitiveService', '2025-06-01').key1)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'accessKey2Name'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'accessKey2Name'), 'value', listKeys('cognitiveService', '2025-06-01').key2)), createArray()))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.37.4.10188", + "templateHash": "10828079590669389085" + } + }, + "definitions": { + "secretSetOutputType": { + "type": "object", + "properties": { + "secretResourceId": { + "type": "string", + "metadata": { + "description": "The resourceId of the exported secret." + } + }, + "secretUri": { + "type": "string", + "metadata": { + "description": "The secret URI of the exported secret." + } + }, + "secretUriWithVersion": { + "type": "string", + "metadata": { + "description": "The secret URI with version of the exported secret." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" + } + } + }, + "secretToSetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret to set." + } + }, + "value": { + "type": "securestring", + "metadata": { + "description": "Required. The value of the secret to set." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for the secret to set via the secrets export feature.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" + } + } + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the Key Vault to set the ecrets in." + } + }, + "secretsToSet": { + "type": "array", + "items": { + "$ref": "#/definitions/secretToSetType" + }, + "metadata": { + "description": "Required. The secrets to set in the Key Vault." + } + } + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2024-11-01", + "name": "[parameters('keyVaultName')]" + }, + "secrets": { + "copy": { + "name": "secrets", + "count": "[length(parameters('secretsToSet'))]" + }, + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2024-11-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('secretsToSet')[copyIndex()].name)]", + "properties": { + "value": "[parameters('secretsToSet')[copyIndex()].value]" + } + } + }, + "outputs": { + "secretsSet": { + "type": "array", + "items": { + "$ref": "#/definitions/secretSetOutputType" + }, + "metadata": { + "description": "The references to the secrets exported to the provided Key Vault." + }, + "copy": { + "count": "[length(range(0, length(coalesce(parameters('secretsToSet'), createArray()))))]", + "input": { + "secretResourceId": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretsToSet')[range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()]].name)]", + "secretUri": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUri]", + "secretUriWithVersion": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUriWithVersion]" + } + } + } + } + } + }, + "dependsOn": [ + "cognitiveService" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the cognitive services account." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the cognitive services account." + }, + "value": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the cognitive services account was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "endpoint": { + "type": "string", + "metadata": { + "description": "The service endpoint of the cognitive services account." + }, + "value": "[reference('cognitiveService').endpoint]" + }, + "endpoints": { + "$ref": "#/definitions/endpointType", + "metadata": { + "description": "All endpoints available for the cognitive services account, types depends on the cognitive service kind." + }, + "value": "[reference('cognitiveService').endpoints]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[tryGet(tryGet(reference('cognitiveService', '2025-06-01', 'full'), 'identity'), 'principalId')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('cognitiveService', '2025-06-01', 'full').location]" + }, + "exportedSecrets": { + "$ref": "#/definitions/secretsOutputType", + "metadata": { + "description": "A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret's name." + }, + "value": "[if(not(equals(parameters('secretsExportConfiguration'), null())), toObject(reference('secretsExport').outputs.secretsSet.value, lambda('secret', last(split(lambdaVariables('secret').secretResourceId, '/'))), lambda('secret', lambdaVariables('secret'))), createObject())]" + }, + "privateEndpoints": { + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointOutputType" + }, + "metadata": { + "description": "The private endpoints of the congitive services account." + }, + "copy": { + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]", + "input": { + "name": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[tryGet(tryGet(reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs, 'groupId'), 'value')]", + "customDnsConfigs": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfigs.value]", + "networkInterfaceResourceIds": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceResourceIds.value]" + } + } + } + } + } + }, + "dependsOn": [ + "avmContainerApp", + "avmManagedIdentity" + ] + }, + "contentUnderstandingPrivateEndpoint": { + "condition": "[parameters('enablePrivateNetworking')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2025-04-01", + "name": "[take(format('avm.res.network.private-endpoint.aicu-{0}', variables('solutionSuffix')), 64)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('pep-aicu-{0}', variables('solutionSuffix'))]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "customNetworkInterfaceName": { + "value": "[format('nic-aicu-{0}', variables('solutionSuffix'))]" + }, + "privateLinkServiceConnections": { + "value": [ + { + "name": "[format('pep-aicu-{0}-cognitiveservices-connection', variables('solutionSuffix'))]", + "properties": { + "privateLinkServiceId": "[reference('avmAiServices_cu').outputs.resourceId.value]", + "groupIds": [ + "account" + ] + } + } + ] + }, + "privateDnsZoneGroup": { + "value": { + "privateDnsZoneGroupConfigs": [ + { + "name": "aicu-dns-zone-cognitiveservices", + "privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)).outputs.resourceId.value]" + }, + { + "name": "aicu-dns-zone-contentunderstanding", + "privateDnsZoneResourceId": "[reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)).outputs.resourceId.value]" + } + ] + } + }, + "subnetResourceId": { + "value": "[reference('virtualNetwork').outputs.backendSubnetResourceId.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "2541425927059591098" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } }, - "value": "[resourceGroup().name]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the private endpoint." + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } }, - "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } }, - "name": { - "type": "string", - "metadata": { - "description": "The name of the private endpoint." + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } }, - "value": "[parameters('name')]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } }, - "value": "[reference('privateEndpoint', '2024-05-01', 'full').location]" + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } }, - "customDnsConfigs": { - "type": "array", - "items": { - "$ref": "#/definitions/customDnsConfigType" + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } }, - "metadata": { - "description": "The custom DNS configurations of the private endpoint." + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } }, - "value": "[reference('privateEndpoint').customDnsConfigs]" + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } }, - "networkInterfaceResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "The resource IDs of the network interfaces associated with the private endpoint." - }, - "value": "[map(reference('privateEndpoint').networkInterfaces, lambda('nic', lambdaVariables('nic').id))]" + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" }, - "groupId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "The group Id for the private endpoint Group." - }, - "value": "[coalesce(tryGet(tryGet(tryGet(tryGet(reference('privateEndpoint'), 'manualPrivateLinkServiceConnections'), 0, 'properties'), 'groupIds'), 0), tryGet(tryGet(tryGet(tryGet(reference('privateEndpoint'), 'privateLinkServiceConnections'), 0, 'properties'), 'groupIds'), 0))]" + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.8.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" } } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" }, "dependsOn": [ - "cognitiveService" + "privateEndpoint" ] }, - "secretsExport": { - "condition": "[not(equals(parameters('secretsExportConfiguration'), null()))]", + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-secrets-kv', uniqueString(deployment().name, parameters('location')))]", - "subscriptionId": "[split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/')[2]]", - "resourceGroup": "[split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/')[4]]", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { - "keyVaultName": { - "value": "[last(split(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '/'))]" + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" }, - "secretsToSet": { - "value": "[union(createArray(), if(contains(parameters('secretsExportConfiguration'), 'accessKey1Name'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'accessKey1Name'), 'value', listKeys('cognitiveService', '2025-06-01').key1)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'accessKey2Name'), createArray(createObject('name', tryGet(parameters('secretsExportConfiguration'), 'accessKey2Name'), 'value', listKeys('cognitiveService', '2025-06-01').key2)), createArray()))]" + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" } }, "template": { @@ -43326,212 +44898,182 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.37.4.10188", - "templateHash": "10828079590669389085" - } + "version": "0.30.23.60470", + "templateHash": "12329174801198479603" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" }, "definitions": { - "secretSetOutputType": { - "type": "object", - "properties": { - "secretResourceId": { - "type": "string", - "metadata": { - "description": "The resourceId of the exported secret." - } - }, - "secretUri": { - "type": "string", - "metadata": { - "description": "The secret URI of the exported secret." - } - }, - "secretUriWithVersion": { - "type": "string", - "metadata": { - "description": "The secret URI with version of the exported secret." - } - } - }, - "metadata": { - "description": "An AVM-aligned type for the output of the secret set via the secrets export feature.", - "__bicep_imported_from!": { - "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" - } - } - }, - "secretToSetType": { + "privateDnsZoneGroupConfigType": { "type": "object", "properties": { "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the secret to set." + "description": "Optional. The name of the private DNS zone group config." } }, - "value": { - "type": "securestring", + "privateDnsZoneResourceId": { + "type": "string", "metadata": { - "description": "Required. The value of the secret to set." + "description": "Required. The resource id of the private DNS zone." } } }, "metadata": { - "description": "An AVM-aligned type for the secret to set via the secrets export feature.", - "__bicep_imported_from!": { - "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" - } + "__bicep_export!": true } } }, "parameters": { - "keyVaultName": { + "privateEndpointName": { "type": "string", "metadata": { - "description": "Required. The name of the Key Vault to set the ecrets in." + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." } }, - "secretsToSet": { + "privateDnsZoneConfigs": { "type": "array", "items": { - "$ref": "#/definitions/secretToSetType" + "$ref": "#/definitions/privateDnsZoneGroupConfigType" }, + "minLength": 1, + "maxLength": 5, "metadata": { - "description": "Required. The secrets to set in the Key Vault." + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." } } }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, "resources": { - "keyVault": { + "privateEndpoint": { "existing": true, - "type": "Microsoft.KeyVault/vaults", - "apiVersion": "2024-11-01", - "name": "[parameters('keyVaultName')]" + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" }, - "secrets": { - "copy": { - "name": "secrets", - "count": "[length(parameters('secretsToSet'))]" - }, - "type": "Microsoft.KeyVault/vaults/secrets", - "apiVersion": "2024-11-01", - "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('secretsToSet')[copyIndex()].name)]", + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", "properties": { - "value": "[parameters('secretsToSet')[copyIndex()].value]" - } + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] } }, "outputs": { - "secretsSet": { - "type": "array", - "items": { - "$ref": "#/definitions/secretSetOutputType" + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", "metadata": { - "description": "The references to the secrets exported to the provided Key Vault." + "description": "The resource ID of the private endpoint DNS zone group." }, - "copy": { - "count": "[length(range(0, length(coalesce(parameters('secretsToSet'), createArray()))))]", - "input": { - "secretResourceId": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretsToSet')[range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()]].name)]", - "secretUri": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUri]", - "secretUriWithVersion": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUriWithVersion]" - } - } + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" } } } }, "dependsOn": [ - "cognitiveService" + "privateEndpoint" ] } }, "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the cognitive services account." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the cognitive services account." - }, - "value": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('name'))]" - }, "resourceGroupName": { "type": "string", "metadata": { - "description": "The resource group the cognitive services account was deployed into." + "description": "The resource group the private endpoint was deployed into." }, "value": "[resourceGroup().name]" }, - "endpoint": { + "resourceId": { "type": "string", "metadata": { - "description": "The service endpoint of the cognitive services account." - }, - "value": "[reference('cognitiveService').endpoint]" - }, - "endpoints": { - "$ref": "#/definitions/endpointType", - "metadata": { - "description": "All endpoints available for the cognitive services account, types depends on the cognitive service kind." + "description": "The resource ID of the private endpoint." }, - "value": "[reference('cognitiveService').endpoints]" + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" }, - "systemAssignedMIPrincipalId": { + "name": { "type": "string", - "nullable": true, "metadata": { - "description": "The principal ID of the system assigned identity." + "description": "The name of the private endpoint." }, - "value": "[tryGet(tryGet(reference('cognitiveService', '2025-06-01', 'full'), 'identity'), 'principalId')]" + "value": "[parameters('name')]" }, "location": { "type": "string", "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('cognitiveService', '2025-06-01', 'full').location]" + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" }, - "exportedSecrets": { - "$ref": "#/definitions/secretsOutputType", + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", "metadata": { - "description": "A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret's name." + "description": "The custom DNS configurations of the private endpoint." }, - "value": "[if(not(equals(parameters('secretsExportConfiguration'), null())), toObject(reference('secretsExport').outputs.secretsSet.value, lambda('secret', last(split(lambdaVariables('secret').secretResourceId, '/'))), lambda('secret', lambdaVariables('secret'))), createObject())]" + "value": "[reference('privateEndpoint').customDnsConfigs]" }, - "privateEndpoints": { + "networkInterfaceIds": { "type": "array", - "items": { - "$ref": "#/definitions/privateEndpointOutputType" + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", "metadata": { - "description": "The private endpoints of the congitive services account." + "description": "The group Id for the private endpoint Group." }, - "copy": { - "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]", - "input": { - "name": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", - "resourceId": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", - "groupId": "[tryGet(tryGet(reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs, 'groupId'), 'value')]", - "customDnsConfigs": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfigs.value]", - "networkInterfaceResourceIds": "[reference(format('cognitiveService_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceResourceIds.value]" - } - } + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" } } } }, "dependsOn": [ - "avmContainerApp", - "avmManagedIdentity", - "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]", + "avmAiServices_cu", "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]", + "[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').contentUnderstanding)]", "virtualNetwork" ] },