Skip to content

Commit 187b85d

Browse files
fixed without private endpoint
1 parent 83c2c40 commit 187b85d

14 files changed

Lines changed: 199 additions & 31 deletions

infra/main.bicep

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,9 @@ module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-service
583583
virtualNetworkRules: []
584584
ipRules: []
585585
}
586-
managedIdentities: { userAssignedResourceIds: [userAssignedIdentity!.outputs.resourceId] } //To create accounts or projects, you must enable a managed identity on your resource
586+
managedIdentities: {
587+
userAssignedResourceIds: [userAssignedIdentity!.outputs.resourceId]
588+
} //To create accounts or projects, you must enable a managed identity on your resource
587589
roleAssignments: [
588590
{
589591
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User
@@ -654,6 +656,27 @@ var aiFoundryAiProjectEndpoint = useExistingAiFoundryAiProject
654656
? existingAiFoundryAiServicesProject!.properties.endpoints['AI Foundry API']
655657
: aiFoundryAiServicesProject!.outputs.apiEndpoint
656658

659+
// ========== Search Service to AI Services Role Assignment ========== //
660+
resource searchServiceToAiServicesRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!useExistingAiFoundryAiProject) {
661+
name: guid(aiSearchName, '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd', aiFoundryAiServicesResourceName)
662+
properties: {
663+
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd') // Cognitive Services OpenAI User
664+
principalId: aiSearch.outputs.systemAssignedMIPrincipalId!
665+
principalType: 'ServicePrincipal'
666+
}
667+
}
668+
669+
// Role assignment for existing AI Services scenario
670+
module searchServiceToExistingAiServicesRoleAssignment 'modules/role-assignment.bicep' = if (useExistingAiFoundryAiProject) {
671+
name: 'searchToExistingAiServices-roleAssignment'
672+
scope: resourceGroup(aiFoundryAiServicesSubscriptionId, aiFoundryAiServicesResourceGroupName)
673+
params: {
674+
principalId: aiSearch.outputs.systemAssignedMIPrincipalId!
675+
roleDefinitionId: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' // Cognitive Services OpenAI User
676+
targetResourceName: existingAiFoundryAiServices.name
677+
}
678+
}
679+
657680
// ========== AI Foundry: AI Search ========== //
658681
var aiSearchName = 'srch-${solutionSuffix}'
659682
var aiSearchConnectionName = 'foundry-search-connection-${solutionSuffix}'
@@ -671,29 +694,34 @@ module aiSearch 'br/public:avm/res/search/search-service:0.11.1' = {
671694
disableLocalAuth: false
672695
hostingMode: 'default'
673696
sku: 'standard'
674-
managedIdentities: { userAssignedResourceIds: [userAssignedIdentity!.outputs.resourceId] }
697+
managedIdentities: { systemAssigned: true }
675698
networkRuleSet: {
676699
bypass: 'AzureServices'
677700
ipRules: []
678701
}
679702
replicaCount: 1
680703
partitionCount: 1
681704
roleAssignments: [
682-
// {
683-
// roleDefinitionIdOrName: 'Cognitive Services Contributor' // Cognitive Search Contributor
684-
// principalId: userAssignedIdentity.outputs.principalId
685-
// principalType: 'ServicePrincipal'
686-
// }
687-
// {
688-
// roleDefinitionIdOrName: 'Cognitive Services OpenAI User'//'5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'// Cognitive Services OpenAI User
689-
// principalId: userAssignedIdentity.outputs.principalId
690-
// principalType: 'ServicePrincipal'
691-
// }
692705
{
693-
roleDefinitionIdOrName: 'Search Index Data Contributor' // 1407120a-92aa-4202-b7e9-c0e197c71c8f
706+
roleDefinitionIdOrName: '1407120a-92aa-4202-b7e9-c0e197c71c8f' // Search Index Data Reader
707+
principalId: userAssignedIdentity.outputs.principalId
708+
principalType: 'ServicePrincipal'
709+
}
710+
{
711+
roleDefinitionIdOrName: '7ca78c08-252a-4471-8644-bb5ff32d4ba0' // Search Service Contributor
694712
principalId: userAssignedIdentity.outputs.principalId
695713
principalType: 'ServicePrincipal'
696714
}
715+
{
716+
roleDefinitionIdOrName: '1407120a-92aa-4202-b7e9-c0e197c71c8f' // Search Index Data Reader
717+
principalId: aiFoundryAiServicesProject!.outputs.systemAssignedMIPrincipalId
718+
principalType: 'ServicePrincipal'
719+
}
720+
{
721+
roleDefinitionIdOrName: '7ca78c08-252a-4471-8644-bb5ff32d4ba0' // Search Service Contributor
722+
principalId: aiFoundryAiServicesProject!.outputs.systemAssignedMIPrincipalId
723+
principalType: 'ServicePrincipal'
724+
}
697725
]
698726
semanticSearch: 'free'
699727
// WAF aligned configuration for Private Networking

infra/main.json

Lines changed: 136 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"_generator": {
77
"name": "bicep",
88
"version": "0.37.4.10188",
9-
"templateHash": "12183275118675645429"
9+
"templateHash": "8879061517486739995"
1010
},
1111
"name": "Document Generation Solution Accelerator",
1212
"description": "CSA CTO Gold Standard Solution Accelerator for Document Generation.\n"
@@ -183,14 +183,14 @@
183183
},
184184
"enableMonitoring": {
185185
"type": "bool",
186-
"defaultValue": true,
186+
"defaultValue": false,
187187
"metadata": {
188188
"description": "Optional. Enable monitoring applicable resources, aligned with the Well Architected Framework recommendations. This setting enables Application Insights and Log Analytics and configures all the resources applicable resources to send logs. Defaults to false."
189189
}
190190
},
191191
"enableScalability": {
192192
"type": "bool",
193-
"defaultValue": true,
193+
"defaultValue": false,
194194
"metadata": {
195195
"description": "Optional. Enable scalability for applicable resources, aligned with the Well Architected Framework recommendations. Defaults to false."
196196
}
@@ -204,7 +204,7 @@
204204
},
205205
"enablePrivateNetworking": {
206206
"type": "bool",
207-
"defaultValue": true,
207+
"defaultValue": false,
208208
"metadata": {
209209
"description": "Optional. Enable private networking for applicable resources, aligned with the Well Architected Framework recommendations. Defaults to false."
210210
}
@@ -277,7 +277,7 @@
277277
"privatelink.services.ai.azure.com",
278278
"[format('privatelink.blob.{0}', environment().suffixes.storage)]",
279279
"[format('privatelink.queue.{0}', environment().suffixes.storage)]",
280-
"privatelink.mongo.cosmos.azure.com",
280+
"privatelink.documents.azure.com",
281281
"privatelink.vaultcore.azure.net",
282282
"privatelink.azurewebsites.net",
283283
"privatelink.search.windows.net"
@@ -384,6 +384,20 @@
384384
"resourceGroup": "[variables('aiFoundryAiServicesResourceGroupName')]",
385385
"name": "[format('{0}/{1}', variables('aiFoundryAiServicesResourceName'), variables('aiFoundryAiProjectResourceName'))]"
386386
},
387+
"searchServiceToAiServicesRoleAssignment": {
388+
"condition": "[not(variables('useExistingAiFoundryAiProject'))]",
389+
"type": "Microsoft.Authorization/roleAssignments",
390+
"apiVersion": "2022-04-01",
391+
"name": "[guid(variables('aiSearchName'), '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd', variables('aiFoundryAiServicesResourceName'))]",
392+
"properties": {
393+
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')]",
394+
"principalId": "[reference('aiSearch').outputs.systemAssignedMIPrincipalId.value]",
395+
"principalType": "ServicePrincipal"
396+
},
397+
"dependsOn": [
398+
"aiSearch"
399+
]
400+
},
387401
"aiSearchFoundryConnection": {
388402
"condition": "[not(variables('useExistingAiFoundryAiProject'))]",
389403
"type": "Microsoft.CognitiveServices/accounts/projects/connections",
@@ -29864,7 +29878,7 @@
2986429878
"_generator": {
2986529879
"name": "bicep",
2986629880
"version": "0.37.4.10188",
29867-
"templateHash": "16971799313952419347"
29881+
"templateHash": "16867891653751120909"
2986829882
}
2986929883
},
2987029884
"parameters": {
@@ -29957,6 +29971,13 @@
2995729971
"description": "Contains AI Endpoint."
2995829972
},
2995929973
"value": "[if(not(empty(variables('existingOpenAIEndpoint'))), variables('existingOpenAIEndpoint'), reference(resourceId('Microsoft.CognitiveServices/accounts', parameters('aiServicesName')), '2025-06-01').endpoints['OpenAI Language Model Instance API'])]"
29974+
},
29975+
"systemAssignedMIPrincipalId": {
29976+
"type": "string",
29977+
"metadata": {
29978+
"description": "Required. Principal ID of the AI project system-assigned managed identity."
29979+
},
29980+
"value": "[reference(resourceId('Microsoft.CognitiveServices/accounts/projects', parameters('aiServicesName'), parameters('name')), '2025-06-01', 'full').identity.principalId]"
2996029981
}
2996129982
}
2996229983
}
@@ -29965,6 +29986,83 @@
2996529986
"aiFoundryAiServices"
2996629987
]
2996729988
},
29989+
"searchServiceToExistingAiServicesRoleAssignment": {
29990+
"condition": "[variables('useExistingAiFoundryAiProject')]",
29991+
"type": "Microsoft.Resources/deployments",
29992+
"apiVersion": "2022-09-01",
29993+
"name": "searchToExistingAiServices-roleAssignment",
29994+
"subscriptionId": "[variables('aiFoundryAiServicesSubscriptionId')]",
29995+
"resourceGroup": "[variables('aiFoundryAiServicesResourceGroupName')]",
29996+
"properties": {
29997+
"expressionEvaluationOptions": {
29998+
"scope": "inner"
29999+
},
30000+
"mode": "Incremental",
30001+
"parameters": {
30002+
"principalId": {
30003+
"value": "[reference('aiSearch').outputs.systemAssignedMIPrincipalId.value]"
30004+
},
30005+
"roleDefinitionId": {
30006+
"value": "5e0bd9bd-7b93-4f28-af87-19fc36ad61bd"
30007+
},
30008+
"targetResourceName": {
30009+
"value": "[variables('aiFoundryAiServicesResourceName')]"
30010+
}
30011+
},
30012+
"template": {
30013+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
30014+
"contentVersion": "1.0.0.0",
30015+
"metadata": {
30016+
"_generator": {
30017+
"name": "bicep",
30018+
"version": "0.37.4.10188",
30019+
"templateHash": "3644919950024112374"
30020+
}
30021+
},
30022+
"parameters": {
30023+
"principalId": {
30024+
"type": "string",
30025+
"metadata": {
30026+
"description": "The principal ID to assign the role to"
30027+
}
30028+
},
30029+
"roleDefinitionId": {
30030+
"type": "string",
30031+
"metadata": {
30032+
"description": "The role definition ID to assign"
30033+
}
30034+
},
30035+
"targetResourceName": {
30036+
"type": "string",
30037+
"metadata": {
30038+
"description": "The name of the target resource"
30039+
}
30040+
}
30041+
},
30042+
"resources": [
30043+
{
30044+
"type": "Microsoft.Authorization/roleAssignments",
30045+
"apiVersion": "2022-04-01",
30046+
"name": "[guid(parameters('principalId'), parameters('roleDefinitionId'), parameters('targetResourceName'))]",
30047+
"properties": {
30048+
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('roleDefinitionId'))]",
30049+
"principalId": "[parameters('principalId')]",
30050+
"principalType": "ServicePrincipal"
30051+
}
30052+
}
30053+
],
30054+
"outputs": {
30055+
"roleAssignmentId": {
30056+
"type": "string",
30057+
"value": "[resourceId('Microsoft.Authorization/roleAssignments', guid(parameters('principalId'), parameters('roleDefinitionId'), parameters('targetResourceName')))]"
30058+
}
30059+
}
30060+
}
30061+
},
30062+
"dependsOn": [
30063+
"aiSearch"
30064+
]
30065+
},
2996830066
"aiSearch": {
2996930067
"type": "Microsoft.Resources/deployments",
2997030068
"apiVersion": "2022-09-01",
@@ -30000,9 +30098,7 @@
3000030098
},
3000130099
"managedIdentities": {
3000230100
"value": {
30003-
"userAssignedResourceIds": [
30004-
"[reference('userAssignedIdentity').outputs.resourceId.value]"
30005-
]
30101+
"systemAssigned": true
3000630102
}
3000730103
},
3000830104
"networkRuleSet": {
@@ -30020,9 +30116,24 @@
3002030116
"roleAssignments": {
3002130117
"value": [
3002230118
{
30023-
"roleDefinitionIdOrName": "Search Index Data Contributor",
30119+
"roleDefinitionIdOrName": "1407120a-92aa-4202-b7e9-c0e197c71c8f",
3002430120
"principalId": "[reference('userAssignedIdentity').outputs.principalId.value]",
3002530121
"principalType": "ServicePrincipal"
30122+
},
30123+
{
30124+
"roleDefinitionIdOrName": "7ca78c08-252a-4471-8644-bb5ff32d4ba0",
30125+
"principalId": "[reference('userAssignedIdentity').outputs.principalId.value]",
30126+
"principalType": "ServicePrincipal"
30127+
},
30128+
{
30129+
"roleDefinitionIdOrName": "1407120a-92aa-4202-b7e9-c0e197c71c8f",
30130+
"principalId": "[reference('aiFoundryAiServicesProject').outputs.systemAssignedMIPrincipalId.value]",
30131+
"principalType": "ServicePrincipal"
30132+
},
30133+
{
30134+
"roleDefinitionIdOrName": "7ca78c08-252a-4471-8644-bb5ff32d4ba0",
30135+
"principalId": "[reference('aiFoundryAiServicesProject').outputs.systemAssignedMIPrincipalId.value]",
30136+
"principalType": "ServicePrincipal"
3002630137
}
3002730138
]
3002830139
},
@@ -32321,6 +32432,7 @@
3232132432
}
3232232433
},
3232332434
"dependsOn": [
32435+
"aiFoundryAiServicesProject",
3232432436
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').searchService)]",
3232532437
"logAnalyticsWorkspace",
3232632438
"network",
@@ -42134,11 +42246,11 @@
4213442246
},
4213542247
{
4213642248
"name": "AZURE-SEARCH-SERVICE",
42137-
"value": "[take(format('avm.res.cognitive-search-services.{0}', variables('aiSearchName')), 64)]"
42249+
"value": "[reference('aiSearch').outputs.name.value]"
4213842250
},
4213942251
{
4214042252
"name": "AZURE-SEARCH-ENDPOINT",
42141-
"value": "[format('https://{0}.search.windows.net', take(format('avm.res.cognitive-search-services.{0}', variables('aiSearchName')), 64))]"
42253+
"value": "[format('https://{0}.search.windows.net', reference('aiSearch').outputs.name.value)]"
4214242254
},
4214342255
{
4214442256
"name": "AZURE-OPENAI-EMBEDDING-MODEL",
@@ -45863,7 +45975,6 @@
4586345975
"type": "Microsoft.Resources/deployments",
4586445976
"apiVersion": "2022-09-01",
4586545977
"name": "[take(format('module.web-sites.{0}', variables('webSiteResourceName')), 64)]",
45866-
"resourceGroup": "[resourceGroup().name]",
4586745978
"properties": {
4586845979
"expressionEvaluationOptions": {
4586945980
"scope": "inner"
@@ -45906,7 +46017,7 @@
4590646017
"SCM_DO_BUILD_DURING_DEPLOYMENT": "true",
4590746018
"DOCKER_REGISTRY_SERVER_URL": "[format('https://{0}.azurecr.io', parameters('acrName'))]",
4590846019
"AUTH_ENABLED": "false",
45909-
"AZURE_SEARCH_SERVICE": "[take(format('avm.res.cognitive-search-services.{0}', variables('aiSearchName')), 64)]",
46020+
"AZURE_SEARCH_SERVICE": "[reference('aiSearch').outputs.name.value]",
4591046021
"AZURE_SEARCH_INDEX": "pdf_index",
4591146022
"AZURE_SEARCH_USE_SEMANTIC_SEARCH": "False",
4591246023
"AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG": "my-semantic-config",
@@ -45954,8 +46065,9 @@
4595446065
"vnetRouteAllEnabled": "[if(parameters('enablePrivateNetworking'), createObject('value', true()), createObject('value', false()))]",
4595546066
"vnetImagePullEnabled": "[if(parameters('enablePrivateNetworking'), createObject('value', true()), createObject('value', false()))]",
4595646067
"virtualNetworkSubnetId": "[if(parameters('enablePrivateNetworking'), createObject('value', reference('network').outputs.subnetWebResourceId.value), createObject('value', null()))]",
45957-
"publicNetworkAccess": "[if(parameters('enablePrivateNetworking'), createObject('value', 'Disabled'), createObject('value', 'Enabled'))]",
45958-
"privateEndpoints": "[if(parameters('enablePrivateNetworking'), createObject('value', createArray(createObject('name', format('pep-{0}', variables('webSiteResourceName')), 'customNetworkInterfaceName', format('nic-{0}', variables('webSiteResourceName')), 'privateDnsZoneGroup', createObject('privateDnsZoneGroupConfigs', createArray(createObject('privateDnsZoneResourceId', reference(format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').appService)).outputs.resourceId.value))), 'service', 'sites', 'subnetResourceId', reference('network').outputs.subnetPrivateEndpointsResourceId.value))), createObject('value', null()))]"
46068+
"publicNetworkAccess": {
46069+
"value": "Enabled"
46070+
}
4595946071
},
4596046072
"template": {
4596146073
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
@@ -47941,7 +48053,6 @@
4794148053
"aiFoundryAiServicesProject",
4794248054
"aiSearch",
4794348055
"applicationInsights",
47944-
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').appService)]",
4794548056
"cosmosDB",
4794648057
"existingAiFoundryAiServicesProject",
4794748058
"logAnalyticsWorkspace",
@@ -48020,7 +48131,7 @@
4802048131
"metadata": {
4802148132
"description": "Contains AI Search Service Name"
4802248133
},
48023-
"value": "[take(format('avm.res.cognitive-search-services.{0}', variables('aiSearchName')), 64)]"
48134+
"value": "[reference('aiSearch').outputs.name.value]"
4802448135
},
4802548136
"azureSearchConnectionName": {
4802648137
"type": "string",
@@ -48161,6 +48272,13 @@
4816148272
"description": "Contains Application Environment."
4816248273
},
4816348274
"value": "Prod"
48275+
},
48276+
"azureClientId": {
48277+
"type": "string",
48278+
"metadata": {
48279+
"description": "Contains User Assigned Identity Client ID"
48280+
},
48281+
"value": "[reference('userAssignedIdentity').outputs.clientId.value]"
4816448282
}
4816548283
}
4816648284
}

infra/modules/ai-project.bicep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ output apiEndpoint string = aiProject!.properties.endpoints['AI Foundry API']
5252
output aoaiEndpoint string = !empty(existingOpenAIEndpoint)
5353
? existingOpenAIEndpoint
5454
: cogServiceReference.properties.endpoints['OpenAI Language Model Instance API']
55+
56+
@description('Required. Principal ID of the AI project system-assigned managed identity.')
57+
output systemAssignedMIPrincipalId string = aiProject.identity.principalId

0 commit comments

Comments
 (0)