Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions content-gen/infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,9 @@ var useExistingAiFoundryAiProject = !empty(azureExistingAIProjectResourceId)
var aiFoundryAiServicesResourceGroupName = useExistingAiFoundryAiProject
? split(azureExistingAIProjectResourceId, '/')[4]
: 'rg-${solutionSuffix}'
// var aiFoundryAiServicesSubscriptionId = useExistingAiFoundryAiProject
// ? split(azureExistingAIProjectResourceId, '/')[2]
// : subscription().id
var aiFoundryAiServicesSubscriptionId = useExistingAiFoundryAiProject
? split(azureExistingAIProjectResourceId, '/')[2]
: subscription().subscriptionId
var aiFoundryAiServicesResourceName = useExistingAiFoundryAiProject
? split(azureExistingAIProjectResourceId, '/')[8]
: 'aif-${solutionSuffix}'
Expand Down Expand Up @@ -572,6 +572,17 @@ var aiFoundryAiProjectEndpoint = useExistingAiFoundryAiProject
? 'https://${aiFoundryAiServicesResourceName}.services.ai.azure.com/api/projects/${aiFoundryAiProjectResourceName}'
: aiFoundryAiServicesProject!.outputs.apiEndpoint

// ========== Role Assignments for Existing AI Services ========== //
module existingAiServicesRoleAssignments 'modules/deploy_foundry_role_assignment.bicep' = if (useExistingAiFoundryAiProject) {
name: take('module.foundry-role-assignment.${aiFoundryAiServicesResourceName}', 64)
scope: resourceGroup(aiFoundryAiServicesSubscriptionId, aiFoundryAiServicesResourceGroupName)
params: {
aiServicesName: aiFoundryAiServicesResourceName
principalId: userAssignedIdentity.outputs.principalId
principalType: 'ServicePrincipal'
}
}

// ========== AI Search ========== //
module aiSearch 'br/public:avm/res/search/search-service:0.11.1' = {
name: take('avm.res.search.search-service.${aiSearchName}', 64)
Expand Down
84 changes: 84 additions & 0 deletions content-gen/infra/modules/deploy_foundry_role_assignment.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// ========== existing-ai-services-roles.bicep ========== //
// Module to assign RBAC roles to managed identity on an existing AI Services account
// This is required when reusing an existing AI Foundry project from a different resource group

@description('Required. The principal ID of the managed identity to grant access.')
param principalId string

@description('Required. The name of the existing AI Services account.')
param aiServicesName string

@description('Optional. The name of the existing AI Project.')
param aiProjectName string = ''

@description('Optional. The principal type of the identity.')
@allowed([
'Device'
'ForeignGroup'
'Group'
'ServicePrincipal'
'User'
])
param principalType string = 'ServicePrincipal'

// ========== Role Definitions ========== //

// Azure AI User role - for AI Foundry project access (used by AIProjectClient for image generation)
resource azureAiUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
name: '53ca6127-db72-4b80-b1b0-d745d6d5456d'
}

// Cognitive Services OpenAI User role - for chat completions (used by AzureOpenAIChatClient)
resource cognitiveServicesOpenAiUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
name: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd'
}

// ========== Existing Resources ========== //

// Reference the existing AI Services account
resource existingAiServices 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = {
name: aiServicesName
}

// Reference the existing AI Project (if provided)
resource existingAiProject 'Microsoft.CognitiveServices/accounts/projects@2025-04-01-preview' existing = if (!empty(aiProjectName)) {
name: aiProjectName
parent: existingAiServices
}

// ========== Role Assignments ========== //

// Azure AI User role assignment - same as reference accelerator
// Required for AIProjectClient (used for image generation in Foundry mode)
resource assignAzureAiUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(existingAiServices.id, principalId, azureAiUserRole.id)
scope: existingAiServices
properties: {
roleDefinitionId: azureAiUserRole.id
principalId: principalId
principalType: principalType
}
}

// Cognitive Services OpenAI User role assignment
// Required for AzureOpenAIChatClient (used for chat completions)
resource assignCognitiveServicesOpenAiUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(existingAiServices.id, principalId, cognitiveServicesOpenAiUserRole.id)
scope: existingAiServices
properties: {
roleDefinitionId: cognitiveServicesOpenAiUserRole.id
principalId: principalId
principalType: principalType
}
}

// ========== Outputs ========== //

@description('The resource ID of the existing AI Services account.')
output aiServicesResourceId string = existingAiServices.id

@description('The endpoint of the existing AI Services account.')
output aiServicesEndpoint string = existingAiServices.properties.endpoint

@description('The principal ID of the existing AI Project (if provided).')
output aiProjectPrincipalId string = !empty(aiProjectName) ? existingAiProject.identity.principalId : ''