Skip to content

Commit 1b4272b

Browse files
enabled system managed identity
1 parent ccc7e37 commit 1b4272b

File tree

5 files changed

+128
-8
lines changed

5 files changed

+128
-8
lines changed

infra/deploy_ai_foundry.bicep

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Creates Azure dependent resources for Azure AI studio
22
param solutionName string
33
param solutionLocation string
4-
param keyVaultName string
4+
param keyVaultName string=''
55
param cuLocation string
66
param deploymentType string
77
param gptModelName string
@@ -10,7 +10,7 @@ param azureOpenAIApiVersion string
1010
param gptDeploymentCapacity int
1111
param embeddingModel string
1212
param embeddingDeploymentCapacity int
13-
param managedIdentityObjectId string
13+
param managedIdentityObjectId string=''
1414
param existingLogAnalyticsWorkspaceId string = ''
1515
param azureExistingAIProjectResourceId string = ''
1616

@@ -116,6 +116,15 @@ resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' =
116116
}
117117
}
118118

119+
module existing_aiServicesModule 'existing_foundry_project.bicep' = if (!empty(azureExistingAIProjectResourceId)) {
120+
name: 'existing_foundry_project'
121+
scope: resourceGroup(existingAIServiceSubscription, existingAIServiceResourceGroup)
122+
params: {
123+
aiServicesName: existingAIServicesName
124+
aiProjectName: existingAIProjectName
125+
}
126+
}
127+
119128
resource aiServices_CU 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
120129
name: aiServicesName_cu
121130
location: location_cu
@@ -225,6 +234,7 @@ resource aiUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing =
225234
name: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
226235
}
227236

237+
228238
resource assignFoundryRoleToMI 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (empty(azureExistingAIProjectResourceId)) {
229239
name: guid(resourceGroup().id, aiServices.id, aiUser.id)
230240
scope: aiServices
@@ -234,7 +244,6 @@ resource assignFoundryRoleToMI 'Microsoft.Authorization/roleAssignments@2022-04-
234244
principalType: 'ServicePrincipal'
235245
}
236246
}
237-
238247
module assignFoundryRoleToMIExisting 'deploy_foundry_role_assignment.bicep' = if (!empty(azureExistingAIProjectResourceId)) {
239248
name: 'assignFoundryRoleToMI'
240249
scope: resourceGroup(existingAIServiceSubscription, existingAIServiceResourceGroup)
@@ -244,6 +253,15 @@ module assignFoundryRoleToMIExisting 'deploy_foundry_role_assignment.bicep' = if
244253
aiServicesName: !empty(azureExistingAIProjectResourceId) ? existingAIServicesName : aiServicesName
245254
aiProjectName: !empty(azureExistingAIProjectResourceId) ? existingAIProjectName : aiProjectName
246255
principalId: managedIdentityObjectId
256+
aiLocation: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.location : solutionLocation
257+
aiKind: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.kind : 'AIServices'
258+
aiSkuName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.skuName : 'S0'
259+
customSubDomainName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.customSubDomainName : aiServicesName
260+
publicNetworkAccess: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.publicNetworkAccess : 'Enabled'
261+
enableSystemAssignedIdentity: true
262+
defaultNetworkAction: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.defaultNetworkAction : 'Allow'
263+
vnetRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.vnetRules : []
264+
ipRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.ipRules : []
247265
}
248266
}
249267

@@ -270,6 +288,15 @@ module assignOpenAIRoleToAISearch 'deploy_foundry_role_assignment.bicep' = {
270288
aiServicesName: !empty(azureExistingAIProjectResourceId) ? existingAIServicesName : aiServicesName
271289
aiProjectName: !empty(azureExistingAIProjectResourceId) ? existingAIProjectName : aiProjectName
272290
principalId: aiSearch.identity.principalId
291+
aiLocation: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.location : solutionLocation
292+
aiKind: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.kind : 'AIServices'
293+
aiSkuName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.skuName : 'S0'
294+
customSubDomainName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.customSubDomainName : aiServicesName
295+
publicNetworkAccess: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.publicNetworkAccess : 'Enabled'
296+
enableSystemAssignedIdentity: true
297+
defaultNetworkAction: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.defaultNetworkAction : 'Allow'
298+
vnetRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.vnetRules : []
299+
ipRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.ipRules : []
273300
}
274301
}
275302

@@ -470,7 +497,6 @@ resource azureLocatioEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview
470497
value: solutionLocation
471498
}
472499
}
473-
474500
output keyvaultName string = keyvaultName
475501
output keyvaultId string = keyVault.id
476502
output aiServicesTarget string = !empty(existingOpenAIEndpoint) ? existingOpenAIEndpoint : aiServices.properties.endpoints['OpenAI Language Model Instance API'] //aiServices_m.properties.endpoint

infra/deploy_backend_docker.bicep

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ param aiServicesName string
1414
param useLocalBuild string
1515
param azureExistingAIProjectResourceId string = ''
1616
param aiSearchName string
17+
param aideploymentsLocation string
1718
var existingAIServiceSubscription = !empty(azureExistingAIProjectResourceId) ? split(azureExistingAIProjectResourceId, '/')[2] : subscription().subscriptionId
1819
var existingAIServiceResourceGroup = !empty(azureExistingAIProjectResourceId) ? split(azureExistingAIProjectResourceId, '/')[4] : resourceGroup().name
1920
var existingAIServicesName = !empty(azureExistingAIProjectResourceId) ? split(azureExistingAIProjectResourceId, '/')[8] : ''
21+
var existingAIProjectName = !empty(azureExistingAIProjectResourceId) ? split(azureExistingAIProjectResourceId, '/')[10] : ''
2022

2123
var imageName = 'DOCKER|${acrName}.azurecr.io/km-api:${imageTag}'
2224
param name string
@@ -165,6 +167,15 @@ resource aiUser 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing =
165167
name: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
166168
}
167169

170+
module existing_aiServicesModule 'existing_foundry_project.bicep' = if (!empty(azureExistingAIProjectResourceId)) {
171+
name: 'existing_foundry_project'
172+
scope: resourceGroup(existingAIServiceSubscription, existingAIServiceResourceGroup)
173+
params: {
174+
aiServicesName: existingAIServicesName
175+
aiProjectName: existingAIProjectName
176+
}
177+
}
178+
168179
module assignAiUserRoleToAiProject 'deploy_foundry_role_assignment.bicep' = {
169180
name: 'assignAiUserRoleToAiProject'
170181
scope: resourceGroup(existingAIServiceSubscription, existingAIServiceResourceGroup)
@@ -173,6 +184,16 @@ module assignAiUserRoleToAiProject 'deploy_foundry_role_assignment.bicep' = {
173184
roleDefinitionId: aiUser.id
174185
roleAssignmentName: guid(appService.name, aiServices.id, aiUser.id)
175186
aiServicesName: !empty(azureExistingAIProjectResourceId) ? existingAIServicesName : aiServicesName
187+
aiProjectName: !empty(azureExistingAIProjectResourceId) ? split(azureExistingAIProjectResourceId, '/')[10] : ''
188+
aiLocation: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.location : aideploymentsLocation
189+
aiKind: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.kind : 'AIServices'
190+
aiSkuName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.skuName : 'S0'
191+
customSubDomainName: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.customSubDomainName : aiServicesName
192+
publicNetworkAccess: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.publicNetworkAccess : 'Enabled'
193+
enableSystemAssignedIdentity: true
194+
defaultNetworkAction: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.defaultNetworkAction : 'Allow'
195+
vnetRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.vnetRules : []
196+
ipRules: !empty(azureExistingAIProjectResourceId) ? existing_aiServicesModule.outputs.ipRules : []
176197
}
177198
}
178199

infra/deploy_foundry_role_assignment.bicep

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,52 @@ param roleDefinitionId string
33
param roleAssignmentName string = ''
44
param aiServicesName string
55
param aiProjectName string = ''
6+
param aiLocation string=''
7+
param aiKind string=''
8+
param aiSkuName string=''
9+
param enableSystemAssignedIdentity bool = true
10+
param customSubDomainName string = ''
11+
param publicNetworkAccess string = ''
12+
param defaultNetworkAction string
13+
param vnetRules array = []
14+
param ipRules array = []
615

7-
resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = {
16+
// AI Services with Identity (enabled only if flag is true)
17+
resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = if (enableSystemAssignedIdentity) {
818
name: aiServicesName
19+
location: aiLocation
20+
kind: aiKind
21+
sku: {
22+
name: aiSkuName
23+
}
24+
identity: {
25+
type: 'SystemAssigned'
26+
}
27+
properties: {
28+
allowProjectManagement: true
29+
customSubDomainName: customSubDomainName
30+
networkAcls: {
31+
defaultAction: defaultNetworkAction
32+
virtualNetworkRules: vnetRules
33+
ipRules: ipRules
34+
}
35+
publicNetworkAccess: publicNetworkAccess
36+
37+
}
938
}
1039

11-
resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' existing = if (!empty(aiProjectName)) {
40+
// AI Project with Identity (only if name provided and flag is true)
41+
resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' = if (!empty(aiProjectName) && enableSystemAssignedIdentity) {
1242
name: aiProjectName
1343
parent: aiServices
44+
location: aiLocation
45+
identity: {
46+
type: 'SystemAssigned'
47+
}
48+
properties: {}
1449
}
1550

51+
// Role Assignment to AI Services
1652
resource roleAssignmentToFoundry 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
1753
name: roleAssignmentName
1854
scope: aiServices
@@ -22,5 +58,6 @@ resource roleAssignmentToFoundry 'Microsoft.Authorization/roleAssignments@2022-0
2258
}
2359
}
2460

61+
// Outputs
2562
output aiServicesPrincipalId string = aiServices.identity.principalId
26-
output aiProjectPrincipalId string = !empty(aiProjectName) ? aiProject.identity.principalId : ''
63+
output aiProjectPrincipalId string = !empty(aiProjectName) ? aiProject.identity.principalId : ''
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@description('Name of the existing Azure AI Services account')
2+
param aiServicesName string
3+
4+
@description('Name of the existing AI Project under the AI Services account')
5+
param aiProjectName string
6+
7+
resource aiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = {
8+
name: aiServicesName
9+
}
10+
11+
resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' existing = {
12+
name: aiProjectName
13+
parent: aiServices
14+
}
15+
16+
17+
18+
// Outputs: AI Services Account
19+
output location string = aiServices.location
20+
output skuName string = aiServices.sku.name
21+
output kind string = aiServices.kind
22+
output allowProjectManagement bool = aiServices.properties.allowProjectManagement
23+
output customSubDomainName string = aiServices.properties.customSubDomainName
24+
output publicNetworkAccess string = aiServices.properties.publicNetworkAccess
25+
output defaultNetworkAction string = aiServices.properties.networkAcls.defaultAction
26+
output ipRules array = aiServices.properties.networkAcls.ipRules
27+
output vnetRules array = aiServices.properties.networkAcls.virtualNetworkRules
28+
29+
// Outputs: AI Project
30+
31+
output projectLocation string = aiProject.location
32+
output projectKind string = aiProject.kind
33+
output projectProvisioningState string = aiProject.properties.provisioningState
34+
// output projectDisplayName string = aiProject.properties.displayName
35+
// output projectDescription string = aiProject.properties.description

infra/main.bicep

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ module aifoundry 'deploy_ai_foundry.bicep' = {
134134
embeddingDeploymentCapacity: embeddingDeploymentCapacity
135135
managedIdentityObjectId: managedIdentityModule.outputs.managedIdentityOutput.objectId
136136
existingLogAnalyticsWorkspaceId: existingLogAnalyticsWorkspaceId
137-
azureExistingAIProjectResourceId: azureExistingAIProjectResourceId
137+
azureExistingAIProjectResourceId: azureExistingAIProjectResourceId
138138

139139
}
140140
scope: resourceGroup(resourceGroup().name)
@@ -219,6 +219,7 @@ module backend_docker 'deploy_backend_docker.bicep' = {
219219
params: {
220220
name: 'api-${solutionPrefix}'
221221
solutionLocation: solutionLocation
222+
aideploymentsLocation: aiDeploymentsLocation
222223
imageTag: imageTag
223224
acrName: acrName
224225
appServicePlanId: hostingplan.outputs.name

0 commit comments

Comments
 (0)