@@ -9,6 +9,7 @@ param gptDeploymentCapacity int
99param embeddingModel string
1010param embeddingDeploymentCapacity int
1111param existingLogAnalyticsWorkspaceId string = ''
12+ param azureExistingAIProjectResourceId string = ''
1213
1314// Load the abbrevations file required to name the azure resources.
1415var abbrs = loadJsonContent ('./abbreviations.json' )
@@ -52,6 +53,31 @@ var existingLawSubscription = useExisting ? split(existingLogAnalyticsWorkspaceI
5253var existingLawResourceGroup = useExisting ? split (existingLogAnalyticsWorkspaceId , '/' )[4 ] : ''
5354var existingLawName = useExisting ? split (existingLogAnalyticsWorkspaceId , '/' )[8 ] : ''
5455
56+ var existingOpenAIEndpoint = !empty (azureExistingAIProjectResourceId )
57+ ? format ('https://{0}.openai.azure.com/' , split (azureExistingAIProjectResourceId , '/' )[8 ])
58+ : ''
59+ var existingProjEndpoint = !empty (azureExistingAIProjectResourceId )
60+ ? format (
61+ 'https://{0}.services.ai.azure.com/api/projects/{1}' ,
62+ split (azureExistingAIProjectResourceId , '/' )[8 ],
63+ split (azureExistingAIProjectResourceId , '/' )[10 ]
64+ )
65+ : ''
66+ var existingAIFoundryName = !empty (azureExistingAIProjectResourceId )
67+ ? split (azureExistingAIProjectResourceId , '/' )[8 ]
68+ : ''
69+ var existingAIProjectName = !empty (azureExistingAIProjectResourceId )
70+ ? split (azureExistingAIProjectResourceId , '/' )[10 ]
71+ : ''
72+ var existingAIServiceSubscription = !empty (azureExistingAIProjectResourceId )
73+ ? split (azureExistingAIProjectResourceId , '/' )[2 ]
74+ : ''
75+ var existingAIServiceResourceGroup = !empty (azureExistingAIProjectResourceId )
76+ ? split (azureExistingAIProjectResourceId , '/' )[4 ]
77+ : ''
78+ var aiSearchConnectionName = 'foundry-search-connection-${solutionName }'
79+ var aiAppInsightConnectionName = 'foundry-app-insights-connection-${solutionName }'
80+
5581resource existingLogAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' existing = if (useExisting ) {
5682 name : existingLawName
5783 scope : resourceGroup (existingLawSubscription , existingLawResourceGroup )
@@ -69,25 +95,6 @@ resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2023-09-01' = if
6995 }
7096}
7197
72- // resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
73- // name: applicationInsightsName
74- // location: location
75- // kind: 'web'
76- // properties: {
77- // Application_Type: 'web'
78- // DisableIpMasking: false
79- // DisableLocalAuth: false
80- // Flow_Type: 'Bluefield'
81- // ForceCustomerStorageForProfiler: false
82- // ImmediatePurgeDataOn30Days: true
83- // IngestionMode: 'ApplicationInsights'
84- // publicNetworkAccessForIngestion: 'Enabled'
85- // publicNetworkAccessForQuery: 'Disabled'
86- // Request_Source: 'rest'
87- // WorkspaceResourceId: logAnalytics.id
88- // }
89- // }
90-
9198resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
9299 name : applicationInsightsName
93100 location : location
@@ -100,7 +107,7 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
100107 }
101108}
102109
103- resource aiFoundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
110+ resource aiFoundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = if ( empty ( azureExistingAIProjectResourceId )) {
104111 name : aiFoundryName
105112 location : location
106113 sku : {
@@ -123,7 +130,7 @@ resource aiFoundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
123130 }
124131}
125132
126- resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = {
133+ resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = if ( empty ( azureExistingAIProjectResourceId )) {
127134 parent : aiFoundry
128135 name : aiProjectName
129136 location : location
@@ -138,7 +145,7 @@ resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04
138145
139146@batchSize (1 )
140147resource aiFModelDeployments 'Microsoft.CognitiveServices/accounts/deployments@2023-05-01' = [
141- for aiModeldeployment in aiModelDeployments : {
148+ for aiModeldeployment in aiModelDeployments : if ( empty ( azureExistingAIProjectResourceId )) {
142149 parent : aiFoundry
143150 name : aiModeldeployment .name
144151 properties : {
@@ -185,8 +192,8 @@ resource aiSearch 'Microsoft.Search/searchServices@2025-02-01-preview' = {
185192 }
186193}
187194
188- resource aiSearchFoundryConnection 'Microsoft.CognitiveServices/accounts/connections@2025-04-01-preview' ={
189- name : 'foundry-search-connection'
195+ resource aiSearchFoundryConnection 'Microsoft.CognitiveServices/accounts/connections@2025-04-01-preview' = if ( empty ( azureExistingAIProjectResourceId )) {
196+ name : aiSearchConnectionName
190197 parent : aiFoundry
191198 properties : {
192199 category : 'CognitiveSearch'
@@ -201,18 +208,56 @@ resource aiSearchFoundryConnection 'Microsoft.CognitiveServices/accounts/connect
201208 }
202209}
203210
211+ module existing_AIProject_SearchConnectionModule 'deploy_aifp_aisearch_connection.bicep' = if (!empty (azureExistingAIProjectResourceId )) {
212+ name : 'aiProjectSearchConnectionDeployment'
213+ scope : resourceGroup (existingAIServiceSubscription , existingAIServiceResourceGroup )
214+ params : {
215+ existingAIProjectName : existingAIProjectName
216+ existingAIFoundryName : existingAIFoundryName
217+ aiSearchName : aiSearchName
218+ aiSearchResourceId : aiSearch .id
219+ aiSearchLocation : aiSearch .location
220+ aiSearchConnectionName : aiSearchConnectionName
221+ }
222+ }
223+
224+ resource cognitiveServicesOpenAIUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
225+ name : '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'
226+ }
227+
228+ module assignOpenAIRoleToAISearch 'deploy_foundry_role_assignment.bicep' = {
229+ name : 'assignOpenAIRoleToAISearch'
230+ scope : resourceGroup (existingAIServiceSubscription , existingAIServiceResourceGroup )
231+ params : {
232+ roleDefinitionId : cognitiveServicesOpenAIUser .id
233+ roleAssignmentName : guid (resourceGroup ().id , aiSearch .id , cognitiveServicesOpenAIUser .id , 'openai-foundry' )
234+ aiFoundryName : !empty (azureExistingAIProjectResourceId ) ? existingAIFoundryName : aiFoundryName
235+ aiProjectName : !empty (azureExistingAIProjectResourceId ) ? existingAIProjectName : aiProjectName
236+ principalId : aiSearch .identity .principalId
237+ }
238+ }
239+
204240@description ('This is the built-in Search Index Data Reader role.' )
205241resource searchIndexDataReaderRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
206242 scope : aiSearch
207243 name : '1407120a-92aa-4202-b7e9-c0e197c71c8f'
208244}
209245
210- resource searchIndexDataReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
211- name : guid (aiSearch .id , aiFoundry .id , searchIndexDataReaderRoleDefinition .id )
246+ resource searchIndexDataReaderRoleAssignmentToAIFP 'Microsoft.Authorization/roleAssignments@2022-04-01' = if ( empty ( azureExistingAIProjectResourceId )) {
247+ name : guid (aiSearch .id , aiFoundryProject .id , searchIndexDataReaderRoleDefinition .id )
212248 scope : aiSearch
213249 properties : {
214250 roleDefinitionId : searchIndexDataReaderRoleDefinition .id
215- principalId : aiFoundry .identity .principalId
251+ principalId : aiFoundryProject .identity .principalId
252+ principalType : 'ServicePrincipal'
253+ }
254+ }
255+ resource assignSearchIndexDataReaderToExistingAiProject 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty (azureExistingAIProjectResourceId )) {
256+ name : guid (resourceGroup ().id , existingAIProjectName , searchIndexDataReaderRoleDefinition .id , 'Existing' )
257+ scope : aiSearch
258+ properties : {
259+ roleDefinitionId : searchIndexDataReaderRoleDefinition .id
260+ principalId : assignOpenAIRoleToAISearch .outputs .aiProjectPrincipalId
216261 principalType : 'ServicePrincipal'
217262 }
218263}
@@ -223,18 +268,28 @@ resource searchServiceContributorRoleDefinition 'Microsoft.Authorization/roleDef
223268 name : '7ca78c08-252a-4471-8644-bb5ff32d4ba0'
224269}
225270
226- resource searchServiceContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
227- name : guid (aiSearch .id , aiFoundry .id , searchServiceContributorRoleDefinition .id )
271+ resource searchServiceContributorRoleAssignmentToAIFP 'Microsoft.Authorization/roleAssignments@2022-04-01' = if ( empty ( azureExistingAIProjectResourceId )) {
272+ name : guid (aiSearch .id , aiFoundryProject .id , searchServiceContributorRoleDefinition .id )
228273 scope : aiSearch
229274 properties : {
230275 roleDefinitionId : searchServiceContributorRoleDefinition .id
231- principalId : aiFoundry .identity .principalId
276+ principalId : aiFoundryProject .identity .principalId
232277 principalType : 'ServicePrincipal'
233278 }
234279}
235280
236- resource appInsightsFoundryConnection 'Microsoft.CognitiveServices/accounts/connections@2025-04-01-preview' = {
237- name : 'foundry-app-insights-connection'
281+ resource searchServiceContributorRoleAssignmentExisting 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty (azureExistingAIProjectResourceId )) {
282+ name : guid (resourceGroup ().id , existingAIProjectName , searchServiceContributorRoleDefinition .id , 'Existing' )
283+ scope : aiSearch
284+ properties : {
285+ roleDefinitionId : searchServiceContributorRoleDefinition .id
286+ principalId : assignOpenAIRoleToAISearch .outputs .aiProjectPrincipalId
287+ principalType : 'ServicePrincipal'
288+ }
289+ }
290+
291+ resource appInsightsFoundryConnection 'Microsoft.CognitiveServices/accounts/connections@2025-04-01-preview' = if (empty (azureExistingAIProjectResourceId )) {
292+ name : aiAppInsightConnectionName
238293 parent : aiFoundry
239294 properties : {
240295 category : 'AppInsights'
@@ -251,14 +306,6 @@ resource appInsightsFoundryConnection 'Microsoft.CognitiveServices/accounts/conn
251306 }
252307}
253308
254- // resource azureOpenAIApiKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
255- // parent: keyVault
256- // name: 'AZURE-OPENAI-KEY'
257- // properties: {
258- // value: aiFoundry.listKeys().key1 //aiServices_m.listKeys().key1
259- // }
260- // }
261-
262309resource azureOpenAIApiVersionEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
263310 parent : keyVault
264311 name : 'AZURE-OPENAI-PREVIEW-API-VERSION'
@@ -271,7 +318,10 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-
271318 parent : keyVault
272319 name : 'AZURE-OPENAI-ENDPOINT'
273320 properties : {
274- value : aiFoundry .properties .endpoints ['OpenAI Language Model Instance API' ] //aiServices_m.properties.endpoint
321+ // value: aiFoundry.properties.endpoints['OpenAI Language Model Instance API'] //aiServices_m.properties.endpoint
322+ value : !empty (existingOpenAIEndpoint )
323+ ? existingOpenAIEndpoint
324+ : aiFoundry .properties .endpoints ['OpenAI Language Model Instance API' ]
275325 }
276326}
277327
@@ -283,14 +333,6 @@ resource azureOpenAIEmbeddingModelEntry 'Microsoft.KeyVault/vaults/secrets@2021-
283333 }
284334}
285335
286- // resource azureSearchAdminKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
287- // parent: keyVault
288- // name: 'AZURE-SEARCH-KEY'
289- // properties: {
290- // value: aiSearch.listAdminKeys().primaryKey
291- // }
292- // }
293-
294336resource azureSearchServiceEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
295337 parent : keyVault
296338 name : 'AZURE-SEARCH-ENDPOINT'
@@ -310,21 +352,27 @@ resource azureSearchIndexEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-pre
310352output keyvaultName string = keyvaultName
311353output keyvaultId string = keyVault .id
312354
313- output aiFoundryProjectEndpoint string = aiFoundryProject .properties .endpoints ['AI Foundry API' ]
314- output aiServicesTarget string = aiFoundry .properties .endpoint //aiServices_m.properties.endpoint
315- output aoaiEndpoint string = aiFoundry .properties .endpoints ['OpenAI Language Model Instance API' ] //aiServices_m.properties.endpoint
316- output aiFoundryName string = aiFoundryName //aiServicesName_m
317- output aiFoundryId string = aiFoundry .id //aiServices_m.id
355+ output resourceGroupNameFoundry string = !empty (existingAIServiceResourceGroup )
356+ ? existingAIServiceResourceGroup
357+ : resourceGroup ().name
358+ output aiFoundryProjectEndpoint string = !empty (existingProjEndpoint )
359+ ? existingProjEndpoint
360+ : aiFoundryProject .properties .endpoints ['AI Foundry API' ]
361+ output aoaiEndpoint string = !empty (existingOpenAIEndpoint )
362+ ? existingOpenAIEndpoint
363+ : aiFoundry .properties .endpoints ['OpenAI Language Model Instance API' ] //aiServices_m.properties.endpoint
364+ output aiFoundryName string = !empty (existingAIFoundryName ) ? existingAIFoundryName : aiFoundryName //aiServicesName_m
318365
319366output aiSearchName string = aiSearchName
320367output aiSearchId string = aiSearch .id
321368output aiSearchTarget string = 'https://${aiSearch .name }.search.windows.net'
322369output aiSearchService string = aiSearch .name
323- output aiFoundryProjectName string = aiFoundryProject .name
370+ output aiFoundryProjectName string = ! empty ( existingAIProjectName ) ? existingAIProjectName : aiFoundryProject .name
324371
325372output applicationInsightsId string = applicationInsights .id
326373output logAnalyticsWorkspaceResourceName string = useExisting ? existingLogAnalyticsWorkspace .name : logAnalytics .name
327374output logAnalyticsWorkspaceResourceGroup string = useExisting ? existingLawResourceGroup : resourceGroup ().name
328375
329-
330376output applicationInsightsConnectionString string = applicationInsights .properties .ConnectionString
377+
378+ output aiSearchFoundryConnectionName string = aiSearchConnectionName
0 commit comments