From d6733c2511c84e2730b4bc45bb7a27096dce51c6 Mon Sep 17 00:00:00 2001 From: Pamela Fox Date: Fri, 24 Apr 2026 15:00:53 -0700 Subject: [PATCH] fix: move Log Analytics Reader role to ai-project.bicep The role assignment was inside the applicationInsights module, which is gated on shouldCreateAppInsights. After the first azd up, the App Insights connection string output gets saved as an azd env var, which flows back into existingApplicationInsightsConnectionString on subsequent provisions. This makes shouldCreateAppInsights=false, so the entire module--including the role assignment--is skipped on re-provision. Move the role assignment to ai-project.bicep conditioned on enableMonitoring, which is always true when monitoring is active regardless of whether App Insights was freshly created or pre-existing. --- infra/core/ai/ai-project.bicep | 16 +++++++++++++++- infra/core/monitor/applicationinsights.bicep | 16 ---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/infra/core/ai/ai-project.bicep b/infra/core/ai/ai-project.bicep index 0e01670..0b88ef8 100644 --- a/infra/core/ai/ai-project.bicep +++ b/infra/core/ai/ai-project.bicep @@ -99,7 +99,6 @@ module applicationInsights '../monitor/applicationinsights.bicep' = if (shouldCr tags: tags name: 'appi-${resourceToken}' logAnalyticsWorkspaceId: logAnalytics.outputs.id - projectMIPrincipalId: aiAccount::project.identity.principalId } } @@ -202,6 +201,21 @@ module aiConnections './connection.bicep' = [for (connection, index) in connecti } }] +// Log Analytics Reader for the Foundry Project managed identity. +// Required for continuous evaluation to query Application Insights traces. +// This must NOT be gated on shouldCreateAppInsights, because after first deploy +// the App Insights outputs get saved as azd env vars, making shouldCreateAppInsights=false +// on subsequent provisions and skipping the entire applicationInsights module. +resource projectLogAnalyticsReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (enableMonitoring) { + name: guid(subscription().id, resourceGroup().id, aiAccount::project.name, '73c42c96-874c-492b-b04d-ab87d138a893') + properties: { + principalId: aiAccount::project.identity.principalId + principalType: 'ServicePrincipal' + // Log Analytics Reader + roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + } +} + // Azure AI User for the developer, scoped to the Foundry Project. // Project scope is sufficient for creating/running agents and calling models via the project endpoint. resource localUserAzureAIUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { diff --git a/infra/core/monitor/applicationinsights.bicep b/infra/core/monitor/applicationinsights.bicep index 18b6176..f8c1e8a 100644 --- a/infra/core/monitor/applicationinsights.bicep +++ b/infra/core/monitor/applicationinsights.bicep @@ -5,9 +5,6 @@ param location string = resourceGroup().location param tags object = {} param logAnalyticsWorkspaceId string -@description('Optional. Principal ID of the Foundry Project managed identity to grant Log Analytics Reader.') -param projectMIPrincipalId string = '' - resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { name: name location: location @@ -28,19 +25,6 @@ module applicationInsightsDashboard 'applicationinsights-dashboard.bicep' = if ( } } -// Log Analytics Reader for the Foundry Project managed identity. -// Required for running evaluations on traces generated by agents. -resource logAnalyticsReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (!empty(projectMIPrincipalId)) { - scope: applicationInsights - name: guid(applicationInsights.id, projectMIPrincipalId, '73c42c96-874c-492b-b04d-ab87d138a893') - properties: { - principalId: projectMIPrincipalId - principalType: 'ServicePrincipal' - // Log Analytics Reader - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') - } -} - output connectionString string = applicationInsights.properties.ConnectionString output id string = applicationInsights.id output instrumentationKey string = applicationInsights.properties.InstrumentationKey