From e2dd7b0bbbfce47b8945c8affa18b9b246d379ea Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Wed, 6 Aug 2025 12:36:40 +0200 Subject: [PATCH 01/29] New version following agreed standards and compliant with AVM WAF configuration --- infra/main.bicep | 2060 +++++++---------- infra/main.parameters.json | 120 +- infra/main.waf.parameters.json | 42 + infra/modules/ai-services.bicep | 630 +++++ infra/modules/web-sites.bicep | 368 +++ infra/modules/web-sites.config.bicep | 91 + .../{ => 00-older}/deploy_ai_foundry.bicep | 0 .../old/{ => 00-older}/deploy_keyvault.bicep | 0 .../deploy_managed_identity.bicep | 0 .../old/{ => 00-older}/macae-continer-oc.json | 0 infra/old/{ => 00-older}/macae-continer.json | 0 infra/old/{ => 00-older}/macae-dev.bicep | 0 .../old/{ => 00-older}/macae-large.bicepparam | 0 .../old/{ => 00-older}/macae-mini.bicepparam | 0 infra/old/{ => 00-older}/macae.bicep | 0 infra/old/{ => 00-older}/main.bicep | 0 infra/old/{ => 00-older}/main2.bicep | 0 infra/old/{ => 00-older}/resources.bicep | 0 infra/{ => old/08-2025}/abbreviations.json | 0 infra/{ => old/08-2025}/bicepconfig.json | 0 infra/old/08-2025/main.bicep | 1720 ++++++++++++++ infra/old/08-2025/main.parameters.json | 102 + .../08-2025}/modules/account/main.bicep | 0 .../account/modules/dependencies.bicep | 0 .../account/modules/keyVaultExport.bicep | 0 .../modules/account/modules/project.bicep | 0 infra/{ => old/08-2025}/modules/ai-hub.bicep | 0 .../modules/container-app-environment.bicep | 0 .../modules/fetch-container-image.bicep | 0 infra/{ => old/08-2025}/modules/role.bicep | 0 30 files changed, 3862 insertions(+), 1271 deletions(-) create mode 100644 infra/main.waf.parameters.json create mode 100644 infra/modules/ai-services.bicep create mode 100644 infra/modules/web-sites.bicep create mode 100644 infra/modules/web-sites.config.bicep rename infra/old/{ => 00-older}/deploy_ai_foundry.bicep (100%) rename infra/old/{ => 00-older}/deploy_keyvault.bicep (100%) rename infra/old/{ => 00-older}/deploy_managed_identity.bicep (100%) rename infra/old/{ => 00-older}/macae-continer-oc.json (100%) rename infra/old/{ => 00-older}/macae-continer.json (100%) rename infra/old/{ => 00-older}/macae-dev.bicep (100%) rename infra/old/{ => 00-older}/macae-large.bicepparam (100%) rename infra/old/{ => 00-older}/macae-mini.bicepparam (100%) rename infra/old/{ => 00-older}/macae.bicep (100%) rename infra/old/{ => 00-older}/main.bicep (100%) rename infra/old/{ => 00-older}/main2.bicep (100%) rename infra/old/{ => 00-older}/resources.bicep (100%) rename infra/{ => old/08-2025}/abbreviations.json (100%) rename infra/{ => old/08-2025}/bicepconfig.json (100%) create mode 100644 infra/old/08-2025/main.bicep create mode 100644 infra/old/08-2025/main.parameters.json rename infra/{ => old/08-2025}/modules/account/main.bicep (100%) rename infra/{ => old/08-2025}/modules/account/modules/dependencies.bicep (100%) rename infra/{ => old/08-2025}/modules/account/modules/keyVaultExport.bicep (100%) rename infra/{ => old/08-2025}/modules/account/modules/project.bicep (100%) rename infra/{ => old/08-2025}/modules/ai-hub.bicep (100%) rename infra/{ => old/08-2025}/modules/container-app-environment.bicep (100%) rename infra/{ => old/08-2025}/modules/fetch-container-image.bicep (100%) rename infra/{ => old/08-2025}/modules/role.bicep (100%) diff --git a/infra/main.bicep b/infra/main.bicep index 8ee54772d..fc3cb1689 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -1,303 +1,256 @@ -metadata name = 'Multi-Agent Custom Automation Engine' -metadata description = 'This module contains the resources required to deploy the Multi-Agent Custom Automation Engine solution accelerator for both Sandbox environments and WAF aligned environments.' - -@description('Set to true if you want to deploy WAF-aligned infrastructure.') -param useWafAlignedArchitecture bool - -@description('Use this parameter to use an existing AI project resource ID') -param existingFoundryProjectResourceId string = '' - -@description('Required. Name of the environment to deploy the solution into.') -param environmentName string - -@description('Required. Location for all Resources except AI Foundry.') -param solutionLocation string = resourceGroup().location - -@description('Optional. Enable/Disable usage telemetry for module.') -param enableTelemetry bool = true +// // ========== main.bicep ========== // +targetScope = 'resourceGroup' -param existingLogAnalyticsWorkspaceId string = '' +metadata name = 'Multi-Agent Custom Automation Engine' +metadata description = '''This module contains the resources required to deploy the [Multi-Agent Custom Automation Engine solution accelerator](https://github.com/microsoft/Multi-Agent-Custom-Automation-Engine-Solution-Accelerator) for both Sandbox environments and WAF aligned environments. + +> **Note:** This module is not intended for broad, generic use, as it was designed by the Commercial Solution Areas CTO team, as a Microsoft Solution Accelerator. Feature requests and bug fix requests are welcome if they support the needs of this organization but may not be incorporated if they aim to make this module more generic than what it needs to be for its primary use case. This module will likely be updated to leverage AVM resource modules in the future. This may result in breaking changes in upcoming versions when these features are implemented. +''' + +@description('Optional. A unique application/solution name for all resources in this deployment. This should be 3-16 characters long.') +@minLength(3) +@maxLength(16) +param solutionName string = 'macae' + +@maxLength(5) +@description('Optional. A unique text value for the solution. This is used to ensure resource names are unique for global resources. Defaults to a 5-character substring of the unique string generated from the subscription ID, resource group name, and solution name.') +param solutionUniqueText string = take(uniqueString(subscription().id, resourceGroup().name, solutionName), 5) + +@metadata({ azd: { type: 'location' } }) +@description('Optional. Azure region for all services. Regions are restricted to guarantee compatibility with paired regions and replica locations for data redundancy and failover scenarios based on articles [Azure regions list](https://learn.microsoft.com/azure/reliability/regions-list) and [Azure Database for MySQL Flexible Server - Azure Regions](https://learn.microsoft.com/azure/mysql/flexible-server/overview#azure-regions).') +@allowed([ + 'australiaeast' + 'centralus' + 'eastasia' + 'eastus' + 'eastus2' + 'japaneast' + 'northeurope' + 'southeastasia' + 'westeurope' + 'uksouth' +]) +param location string = 'australiaeast' // Restricting deployment to only supported Azure OpenAI regions validated with GPT-4o model -@metadata({ - azd : { - type: 'location' - usageName : [ - 'OpenAI.GlobalStandard.gpt-4o, 150' - ] - } -}) @allowed(['australiaeast', 'eastus2', 'francecentral', 'japaneast', 'norwayeast', 'swedencentral', 'uksouth', 'westus']) -@description('Azure OpenAI Location') -param aiDeploymentsLocation string - -@minLength(1) -@description('Name of the GPT model to deploy:') -param gptModelName string = 'gpt-4o' - -param gptModelVersion string = '2024-08-06' - -@minLength(1) -@description('GPT model deployment type:') -param modelDeploymentType string = 'GlobalStandard' - -@description('Optional. AI model deployment token capacity.') -param gptModelCapacity int = 150 - -@description('Set the image tag for the container images used in the solution. Default is "latest".') -param imageTag string = 'latest' - -param solutionPrefix string = 'macae-${padLeft(take(toLower(uniqueString(subscription().id, environmentName, resourceGroup().location, resourceGroup().name)), 12), 12, '0')}' +@metadata({ azd: { type: 'location' } }) +@description('Optional. Location for all AI service resources. This should be one of the supported Azure AI Service locations.') +param azureAiServiceLocation string = 'australiaeast' @description('Optional. The tags to apply to all deployed Azure resources.') -param tags object = { - app: solutionPrefix - location: solutionLocation -} +param tags resourceInput<'Microsoft.Resources/resourceGroups@2025-04-01'>.tags = {} -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource.') -param logAnalyticsWorkspaceConfiguration logAnalyticsWorkspaceConfigurationType = { - enabled: true - name: 'log-${solutionPrefix}' - location: solutionLocation - sku: 'PerGB2018' - tags: tags - dataRetentionInDays: useWafAlignedArchitecture ? 365 : 30 - existingWorkspaceResourceId: existingLogAnalyticsWorkspaceId -} +@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.') +param enableMonitoring bool = false -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Application Insights resource.') -param applicationInsightsConfiguration applicationInsightsConfigurationType = { - enabled: true - name: 'appi-${solutionPrefix}' - location: solutionLocation - tags: tags - retentionInDays: useWafAlignedArchitecture ? 365 : 30 -} +@description('Optional. Enable scalability for applicable resources, aligned with the Well Architected Framework recommendations. Defaults to false.') +param enableScalability bool = false -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Managed Identity resource.') -param userAssignedManagedIdentityConfiguration userAssignedManagedIdentityType = { - enabled: true - name: 'id-${solutionPrefix}' - location: solutionLocation - tags: tags -} +@description('Optional. Enable redundancy for applicable resources, aligned with the Well Architected Framework recommendations. Defaults to false.') +param enableRedundancy bool = false -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the backend subnet.') -param networkSecurityGroupBackendConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-backend-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} +@description('Optional. Enable private networking for applicable resources, aligned with the Well Architected Framework recommendations. Defaults to false.') +param enablePrivateNetworking bool = false -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the containers subnet.') -param networkSecurityGroupContainersConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-containers-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} +@secure() +@description('Optional. The user name for the administrator account of the virtual machine. Allows to customize credentials if `enablePrivateNetworking` is set to true.') +param virtualMachineAdminUsername string = take(newGuid(), 20) -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the Bastion subnet.') -param networkSecurityGroupBastionConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-bastion-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} +@description('Optional. The password for the administrator account of the virtual machine. Allows to customize credentials if `enablePrivateNetworking` is set to true.') +@secure() +param virtualMachineAdminPassword string = newGuid() -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the administration subnet.') -param networkSecurityGroupAdministrationConfiguration networkSecurityGroupConfigurationType = { - enabled: true - name: 'nsg-administration-${solutionPrefix}' - location: solutionLocation - tags: tags - securityRules: null //Default value set on module configuration -} +@description('Optional. The Container Registry hostname where the docker images for the backend are located.') +param backendContainerRegistryHostname string = 'biabcontainerreg.azurecr.io' -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine virtual network resource.') -param virtualNetworkConfiguration virtualNetworkConfigurationType = { - enabled: useWafAlignedArchitecture ? true : false - name: 'vnet-${solutionPrefix}' - location: solutionLocation - tags: tags - addressPrefixes: null //Default value set on module configuration - subnets: null //Default value set on module configuration -} +@description('Optional. The Container Image Name to deploy on the backend.') +param backendContainerImageName string = 'macaebackend' -@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine bastion resource.') -param bastionConfiguration bastionConfigurationType = { - enabled: true - name: 'bas-${solutionPrefix}' - location: solutionLocation - tags: tags - sku: 'Standard' - virtualNetworkResourceId: null //Default value set on module configuration - publicIpResourceName: 'pip-bas${solutionPrefix}' -} +@description('Optional. The Container Image Tag to deploy on the backend.') +param backendContainerImageTag string = 'latest_2025-07-22_895' -@description('Optional. Configuration for the Windows virtual machine.') -param virtualMachineConfiguration virtualMachineConfigurationType = { - enabled: true - name: 'vm${solutionPrefix}' - location: solutionLocation - tags: tags - adminUsername: 'adminuser' - adminPassword: useWafAlignedArchitecture? 'P@ssw0rd1234' : guid(solutionPrefix, subscription().subscriptionId) - vmSize: 'Standard_D2s_v3' - subnetResourceId: null //Default value set on module configuration -} +@description('Optional. The Container Registry hostname where the docker images for the frontend are located.') +param frontendContainerRegistryHostname string = 'biabcontainerreg.azurecr.io' -@description('Optional. The configuration to apply for the AI Foundry AI Services resource.') -param aiFoundryAiServicesConfiguration aiServicesConfigurationType = { - enabled: true - name: 'aisa-${solutionPrefix}' - location: aiDeploymentsLocation - sku: 'S0' - deployments: null //Default value set on module configuration - subnetResourceId: null //Default value set on module configuration - modelCapacity: gptModelCapacity -} +@description('Optional. The Container Image Name to deploy on the frontend.') +param frontendContainerImageName string = 'macaefrontend' -@description('Optional. The configuration to apply for the AI Foundry AI Project resource.') -param aiFoundryAiProjectConfiguration aiProjectConfigurationType = { - enabled: true - name: 'aifp-${solutionPrefix}' - location: aiDeploymentsLocation - sku: 'Basic' - tags: tags -} +@description('Optional. The Container Image Tag to deploy on the frontend.') +param frontendContainerImageTag string = 'latest_2025-07-22_895' -@description('Optional. The configuration to apply for the Cosmos DB Account resource.') -param cosmosDbAccountConfiguration cosmosDbAccountConfigurationType = { - enabled: true - name: 'cosmos-${solutionPrefix}' - location: solutionLocation - tags: tags - subnetResourceId: null //Default value set on module configuration - sqlDatabases: null //Default value set on module configuration -} - -@description('Optional. The configuration to apply for the Container App Environment resource.') -param containerAppEnvironmentConfiguration containerAppEnvironmentConfigurationType = { - enabled: true - name: 'cae-${solutionPrefix}' - location: solutionLocation - tags: tags - subnetResourceId: null //Default value set on module configuration -} +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true -@description('Optional. The configuration to apply for the Container App resource.') -param containerAppConfiguration containerAppConfigurationType = { - enabled: true - name: 'ca-${solutionPrefix}' - location: solutionLocation - tags: tags - environmentResourceId: null //Default value set on module configuration - concurrentRequests: '100' - containerCpu: '2.0' - containerMemory: '4.0Gi' - containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' - containerImageName: 'macaebackend' - containerImageTag: imageTag - containerName: 'backend' - ingressTargetPort: 8000 - maxReplicas: 1 - minReplicas: 1 +// ============== // +// Variables // +// ============== // + +var solutionSuffix = '${solutionName}${solutionUniqueText}' + +// Region pairs list based on article in [Azure regions list](https://learn.microsoft.com/azure/reliability/regions-list) +// var azureRegionPairs = { +// australiaeast: 'australiasoutheast' +// centralus: 'eastus2' +// eastasia: 'southeastasia' +// eastus: 'centralus' +// eastus2: 'centralus' +// japaneast: 'japanwest' +// northeurope: 'westeurope' +// southeastasia: 'eastasia' +// uksouth: 'ukwest' +// westeurope: 'northeurope' +// } +// // Paired location calculated based on 'location' parameter. This location will be used by applicable resources if `enableScalability` is set to `true` +// var pairedLocation = azureRegionPairs[location] + +// Region pairs list based on article in [Azure Database for MySQL Flexible Server - Azure Regions](https://learn.microsoft.com/azure/mysql/flexible-server/overview#azure-regions) for supported high availability regions for CosmosDB. +var cosmosDbZoneRedundantHaRegionPairs = { + australiaeast: 'uksouth' //'southeastasia' + centralus: 'eastus2' + eastasia: 'southeastasia' + eastus: 'centralus' + eastus2: 'centralus' + japaneast: 'australiaeast' + northeurope: 'westeurope' + southeastasia: 'eastasia' + uksouth: 'westeurope' + westeurope: 'northeurope' } - -@description('Optional. The configuration to apply for the Web Server Farm resource.') -param webServerFarmConfiguration webServerFarmConfigurationType = { - enabled: true - name: 'asp-${solutionPrefix}' - location: solutionLocation - skuName: useWafAlignedArchitecture? 'P1v3' : 'B2' - skuCapacity: useWafAlignedArchitecture ? 3 : 1 - tags: tags +// Paired location calculated based on 'location' parameter. This location will be used by applicable resources if `enableScalability` is set to `true` +var cosmosDbHaLocation = cosmosDbZoneRedundantHaRegionPairs[location] + +// Replica regions list based on article in [Azure regions list](https://learn.microsoft.com/azure/reliability/regions-list) and [Enhance resilience by replicating your Log Analytics workspace across regions](https://learn.microsoft.com/azure/azure-monitor/logs/workspace-replication#supported-regions) for supported regions for Log Analytics Workspace. +var replicaRegionPairs = { + australiaeast: 'australiasoutheast' + centralus: 'westus' + eastasia: 'japaneast' + eastus: 'centralus' + eastus2: 'centralus' + japaneast: 'eastasia' + northeurope: 'westeurope' + southeastasia: 'eastasia' + uksouth: 'westeurope' + westeurope: 'northeurope' } +var replicaLocation = replicaRegionPairs[location] -@description('Optional. The configuration to apply for the Web Server Farm resource.') -param webSiteConfiguration webSiteConfigurationType = { - enabled: true - name: 'app-${solutionPrefix}' - location: solutionLocation - containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' - containerImageName: 'macaefrontend' - containerImageTag: imageTag - containerName: 'backend' - tags: tags - environmentResourceId: null //Default value set on module configuration -} +// ============== // +// Resources // +// ============== // -// ========== Resource Group Tag ========== // -resource resourceGroupTags 'Microsoft.Resources/tags@2021-04-01' = { - name: 'default' +#disable-next-line no-deployments-resources +resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { + name: '46d3xbcp.ptn.sa-multiagentcustauteng.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' properties: { - tags: { - ...tags - TemplateName: 'Macae' + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } } } } // ========== Log Analytics Workspace ========== // // WAF best practices for Log Analytics: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-log-analytics -// Log Analytics configuration defaults -var logAnalyticsWorkspaceEnabled = logAnalyticsWorkspaceConfiguration.?enabled ?? true -var logAnalyticsWorkspaceResourceName = logAnalyticsWorkspaceConfiguration.?name ?? 'log-${solutionPrefix}' -var existingWorkspaceResourceId = logAnalyticsWorkspaceConfiguration.?existingWorkspaceResourceId ?? '' -var useExistingWorkspace = existingWorkspaceResourceId != '' - -module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.11.2' = if (logAnalyticsWorkspaceEnabled && !useExistingWorkspace) { +// WAF PSRules for Log Analytics: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#azure-monitor-logs +var logAnalyticsWorkspaceResourceName = 'log-${solutionSuffix}' +module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.12.0' = if (enableMonitoring) { name: take('avm.res.operational-insights.workspace.${logAnalyticsWorkspaceResourceName}', 64) params: { name: logAnalyticsWorkspaceResourceName - tags: logAnalyticsWorkspaceConfiguration.?tags ?? tags - location: logAnalyticsWorkspaceConfiguration.?location ?? solutionLocation + tags: tags + location: location enableTelemetry: enableTelemetry - skuName: logAnalyticsWorkspaceConfiguration.?sku ?? 'PerGB2018' - dataRetention: logAnalyticsWorkspaceConfiguration.?dataRetentionInDays ?? 365 + skuName: 'PerGB2018' + dataRetention: 365 + features: { enableLogAccessUsingOnlyResourcePermissions: true } diagnosticSettings: [{ useThisWorkspace: true }] + // WAF aligned configuration for Redundancy + dailyQuotaGb: enableRedundancy ? 10 : null //WAF recommendation: 10 GB per day is a good starting point for most workloads + replication: enableRedundancy + ? { + enabled: true + location: replicaLocation + } + : null + // WAF aligned configuration for Private Networking + publicNetworkAccessForIngestion: enablePrivateNetworking ? 'Disabled' : 'Enabled' + publicNetworkAccessForQuery: enablePrivateNetworking ? 'Disabled' : 'Enabled' + dataSources: enablePrivateNetworking + ? [ + { + tags: tags + eventLogName: 'Application' + eventTypes: [ + { + eventType: 'Error' + } + { + eventType: 'Warning' + } + { + eventType: 'Information' + } + ] + kind: 'WindowsEvent' + name: 'applicationEvent' + } + { + counterName: '% Processor Time' + instanceName: '*' + intervalSeconds: 60 + kind: 'WindowsPerformanceCounter' + name: 'windowsPerfCounter1' + objectName: 'Processor' + } + { + kind: 'IISLogs' + name: 'sampleIISLog1' + state: 'OnPremiseEnabled' + } + ] + : null } } -var logAnalyticsWorkspaceId = useExistingWorkspace ? existingWorkspaceResourceId : logAnalyticsWorkspace.outputs.resourceId - // ========== Application Insights ========== // // WAF best practices for Application Insights: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/application-insights -// Application Insights configuration defaults -var applicationInsightsEnabled = applicationInsightsConfiguration.?enabled ?? true -var applicationInsightsResourceName = applicationInsightsConfiguration.?name ?? 'appi-${solutionPrefix}' -module applicationInsights 'br/public:avm/res/insights/component:0.6.0' = if (applicationInsightsEnabled) { +// WAF PSRules for Application Insights: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#application-insights +var applicationInsightsResourceName = 'appi-${solutionSuffix}' +module applicationInsights 'br/public:avm/res/insights/component:0.6.0' = if (enableMonitoring) { name: take('avm.res.insights.component.${applicationInsightsResourceName}', 64) params: { name: applicationInsightsResourceName - workspaceResourceId: logAnalyticsWorkspaceId - location: applicationInsightsConfiguration.?location ?? solutionLocation + tags: tags + location: location enableTelemetry: enableTelemetry - tags: applicationInsightsConfiguration.?tags ?? tags - retentionInDays: applicationInsightsConfiguration.?retentionInDays ?? 365 - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + retentionInDays: 365 kind: 'web' disableIpMasking: false flowType: 'Bluefield' + // WAF aligned configuration for Monitoring + workspaceResourceId: enableMonitoring ? logAnalyticsWorkspace!.outputs.resourceId : '' + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null } } -// ========== User assigned identity Web Site ========== // +// ========== User Assigned Identity ========== // // WAF best practices for identity and access management: https://learn.microsoft.com/en-us/azure/well-architected/security/identity-access -var userAssignedManagedIdentityEnabled = userAssignedManagedIdentityConfiguration.?enabled ?? true -var userAssignedManagedIdentityResourceName = userAssignedManagedIdentityConfiguration.?name ?? 'id-${solutionPrefix}' -module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.1' = if (userAssignedManagedIdentityEnabled) { - name: take('avm.res.managed-identity.user-assigned-identity.${userAssignedManagedIdentityResourceName}', 64) +var userAssignedIdentityResourceName = 'id-${solutionSuffix}' +module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.1' = { + name: take('avm.res.managed-identity.user-assigned-identity.${userAssignedIdentityResourceName}', 64) params: { - name: userAssignedManagedIdentityResourceName - tags: userAssignedManagedIdentityConfiguration.?tags ?? tags - location: userAssignedManagedIdentityConfiguration.?location ?? solutionLocation + name: userAssignedIdentityResourceName + location: location + tags: tags enableTelemetry: enableTelemetry } } @@ -305,79 +258,46 @@ module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-id // ========== Network Security Groups ========== // // WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network // WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking -var networkSecurityGroupBackendEnabled = networkSecurityGroupBackendConfiguration.?enabled ?? true -var networkSecurityGroupBackendResourceName = networkSecurityGroupBackendConfiguration.?name ?? 'nsg-backend-${solutionPrefix}' -module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBackendEnabled) { +var networkSecurityGroupBackendResourceName = 'nsg-${solutionSuffix}-backend' +module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) { name: take('avm.res.network.network-security-group.${networkSecurityGroupBackendResourceName}', 64) params: { name: networkSecurityGroupBackendResourceName - location: networkSecurityGroupBackendConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupBackendConfiguration.?tags ?? tags - enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupBackendConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } - ] - } -} - -var networkSecurityGroupContainersEnabled = networkSecurityGroupContainersConfiguration.?enabled ?? true -var networkSecurityGroupContainersResourceName = networkSecurityGroupContainersConfiguration.?name ?? 'nsg-containers-${solutionPrefix}' -module networkSecurityGroupContainers 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupContainersEnabled) { - name: take('avm.res.network.network-security-group.${networkSecurityGroupContainersResourceName}', 64) - params: { - name: networkSecurityGroupContainersResourceName - location: networkSecurityGroupContainersConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupContainersConfiguration.?tags ?? tags + location: location + tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupContainersConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + securityRules: [ + { + name: 'deny-hop-outbound' + properties: { + access: 'Deny' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + direction: 'Outbound' + priority: 200 + protocol: 'Tcp' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + } + } ] } } -var networkSecurityGroupBastionEnabled = networkSecurityGroupBastionConfiguration.?enabled ?? true -var networkSecurityGroupBastionResourceName = networkSecurityGroupBastionConfiguration.?name ?? 'nsg-bastion-${solutionPrefix}' -module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBastionEnabled) { +var networkSecurityGroupBastionResourceName = 'nsg-${solutionSuffix}-bastion' +module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) { name: take('avm.res.network.network-security-group.${networkSecurityGroupBastionResourceName}', 64) params: { name: networkSecurityGroupBastionResourceName - location: networkSecurityGroupBastionConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupBastionConfiguration.?tags ?? tags + location: location + tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupBastionConfiguration.?securityRules ?? [ + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + securityRules: [ { name: 'AllowHttpsInBound' properties: { @@ -524,33 +444,92 @@ module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-g } } -var networkSecurityGroupAdministrationEnabled = networkSecurityGroupAdministrationConfiguration.?enabled ?? true -var networkSecurityGroupAdministrationResourceName = networkSecurityGroupAdministrationConfiguration.?name ?? 'nsg-administration-${solutionPrefix}' -module networkSecurityGroupAdministration 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupAdministrationEnabled) { +var networkSecurityGroupAdministrationResourceName = 'nsg-${solutionSuffix}-administration' +module networkSecurityGroupAdministration 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) { name: take('avm.res.network.network-security-group.${networkSecurityGroupAdministrationResourceName}', 64) params: { name: networkSecurityGroupAdministrationResourceName - location: networkSecurityGroupAdministrationConfiguration.?location ?? solutionLocation - tags: networkSecurityGroupAdministrationConfiguration.?tags ?? tags + location: location + tags: tags + enableTelemetry: enableTelemetry + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + securityRules: [ + { + name: 'deny-hop-outbound' + properties: { + access: 'Deny' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + direction: 'Outbound' + priority: 200 + protocol: 'Tcp' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + } + } + ] + } +} + +var networkSecurityGroupContainersResourceName = 'nsg-${solutionSuffix}-containers' +module networkSecurityGroupContainers 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) { + name: take('avm.res.network.network-security-group.${networkSecurityGroupContainersResourceName}', 64) + params: { + name: networkSecurityGroupContainersResourceName + location: location + tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - securityRules: networkSecurityGroupAdministrationConfiguration.?securityRules ?? [ - // { - // name: 'DenySshRdpOutbound' //Azure Bastion - // properties: { - // priority: 200 - // access: 'Deny' - // protocol: '*' - // direction: 'Outbound' - // sourceAddressPrefix: 'VirtualNetwork' - // sourcePortRange: '*' - // destinationAddressPrefix: '*' - // destinationPortRanges: [ - // '3389' - // '22' - // ] - // } - // } + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + securityRules: [ + { + name: 'deny-hop-outbound' + properties: { + access: 'Deny' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + direction: 'Outbound' + priority: 200 + protocol: 'Tcp' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + } + } + ] + } +} + +var networkSecurityGroupWebsiteResourceName = 'nsg-${solutionSuffix}-website' +module networkSecurityGroupWebsite 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) { + name: take('avm.res.network.network-security-group.${networkSecurityGroupWebsiteResourceName}', 64) + params: { + name: networkSecurityGroupWebsiteResourceName + location: location + tags: tags + enableTelemetry: enableTelemetry + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + securityRules: [ + { + name: 'deny-hop-outbound' + properties: { + access: 'Deny' + destinationAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + direction: 'Outbound' + priority: 200 + protocol: 'Tcp' + sourceAddressPrefix: 'VirtualNetwork' + sourcePortRange: '*' + } + } ] } } @@ -558,34 +537,35 @@ module networkSecurityGroupAdministration 'br/public:avm/res/network/network-sec // ========== Virtual Network ========== // // WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network // WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking -var virtualNetworkEnabled = virtualNetworkConfiguration.?enabled ?? true -var virtualNetworkResourceName = virtualNetworkConfiguration.?name ?? 'vnet-${solutionPrefix}' -module virtualNetwork 'br/public:avm/res/network/virtual-network:0.6.1' = if (virtualNetworkEnabled) { +var virtualNetworkResourceName = 'vnet-${solutionSuffix}' +module virtualNetwork 'br/public:avm/res/network/virtual-network:0.7.0' = if (enablePrivateNetworking) { name: take('avm.res.network.virtual-network.${virtualNetworkResourceName}', 64) params: { name: virtualNetworkResourceName - location: virtualNetworkConfiguration.?location ?? solutionLocation - tags: virtualNetworkConfiguration.?tags ?? tags + location: location + tags: tags enableTelemetry: enableTelemetry - addressPrefixes: virtualNetworkConfiguration.?addressPrefixes ?? ['10.0.0.0/8'] - subnets: virtualNetworkConfiguration.?subnets ?? [ + addressPrefixes: ['10.0.0.0/8'] + subnets: [ { name: 'backend' addressPrefix: '10.0.0.0/27' //defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access - networkSecurityGroupResourceId: networkSecurityGroupBackend.outputs.resourceId + networkSecurityGroupResourceId: networkSecurityGroupBackend!.outputs.resourceId } { name: 'administration' addressPrefix: '10.0.0.32/27' - networkSecurityGroupResourceId: networkSecurityGroupAdministration.outputs.resourceId + networkSecurityGroupResourceId: networkSecurityGroupAdministration!.outputs.resourceId + //defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access + //natGatewayResourceId: natGateway.outputs.resourceId } { // For Azure Bastion resources deployed on or after November 2, 2021, the minimum AzureBastionSubnet size is /26 or larger (/25, /24, etc.). // https://learn.microsoft.com/en-us/azure/bastion/configuration-settings#subnet name: 'AzureBastionSubnet' //This exact name is required for Azure Bastion addressPrefix: '10.0.0.64/26' - networkSecurityGroupResourceId: networkSecurityGroupBastion.outputs.resourceId + networkSecurityGroupResourceId: networkSecurityGroupBastion!.outputs.resourceId } { // If you use your own vnw, you need to provide a subnet that is dedicated exclusively to the Container App environment you deploy. This subnet isn't available to other services @@ -593,67 +573,218 @@ module virtualNetwork 'br/public:avm/res/network/virtual-network:0.6.1' = if (vi name: 'containers' addressPrefix: '10.0.2.0/23' //subnet of size /23 is required for container app delegation: 'Microsoft.App/environments' - networkSecurityGroupResourceId: networkSecurityGroupContainers.outputs.resourceId - privateEndpointNetworkPolicies: 'Disabled' + networkSecurityGroupResourceId: networkSecurityGroupContainers!.outputs.resourceId + privateEndpointNetworkPolicies: 'Enabled' + privateLinkServiceNetworkPolicies: 'Enabled' + } + { + // If you use your own vnw, you need to provide a subnet that is dedicated exclusively to the App Environment you deploy. This subnet isn't available to other services + // https://learn.microsoft.com/en-us/azure/app-service/overview-vnet-integration#subnet-requirements + name: 'webserverfarm' + addressPrefix: '10.0.4.0/27' //When you're creating subnets in Azure portal as part of integrating with the virtual network, a minimum size of /27 is required + delegation: 'Microsoft.Web/serverfarms' + networkSecurityGroupResourceId: networkSecurityGroupWebsite!.outputs.resourceId + privateEndpointNetworkPolicies: 'Enabled' privateLinkServiceNetworkPolicies: 'Enabled' } ] } } -var bastionEnabled = bastionConfiguration.?enabled ?? true -var bastionResourceName = bastionConfiguration.?name ?? 'bas-${solutionPrefix}' +var bastionResourceName = 'bas-${solutionSuffix}' // ========== Bastion host ========== // // WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network // WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking -module bastionHost 'br/public:avm/res/network/bastion-host:0.6.1' = if (virtualNetworkEnabled && bastionEnabled) { +module bastionHost 'br/public:avm/res/network/bastion-host:0.7.0' = if (enablePrivateNetworking) { name: take('avm.res.network.bastion-host.${bastionResourceName}', 64) params: { name: bastionResourceName - location: bastionConfiguration.?location ?? solutionLocation - skuName: bastionConfiguration.?sku ?? 'Standard' + location: location + skuName: 'Standard' enableTelemetry: enableTelemetry - tags: bastionConfiguration.?tags ?? tags - virtualNetworkResourceId: bastionConfiguration.?virtualNetworkResourceId ?? virtualNetwork.?outputs.?resourceId + tags: tags + virtualNetworkResourceId: virtualNetwork!.?outputs.?resourceId publicIPAddressObject: { - name: bastionConfiguration.?publicIpResourceName ?? 'pip-bas${solutionPrefix}' - zones: [] + name: 'pip-bas${solutionSuffix}' + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + tags: tags } - disableCopyPaste: false + disableCopyPaste: true enableFileCopy: false - enableIpConnect: true - enableShareableLink: true + enableIpConnect: false + enableShareableLink: false + scaleUnits: 4 + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null } } // ========== Virtual machine ========== // // WAF best practices for virtual machines: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-machines -var virtualMachineEnabled = virtualMachineConfiguration.?enabled ?? true -var virtualMachineResourceName = virtualMachineConfiguration.?name ?? 'vm${solutionPrefix}' -module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.13.0' = if (virtualNetworkEnabled && virtualMachineEnabled) { - name: take('avm.res.compute.virtual-machine.${virtualMachineResourceName}', 64) +var maintenanceConfigurationResourceName = 'mc-${solutionSuffix}' +module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-configuration:0.3.1' = if (enablePrivateNetworking) { + name: take('avm.res.compute.virtual-machine.${maintenanceConfigurationResourceName}', 64) params: { - name: virtualMachineResourceName - computerName: take(virtualMachineResourceName, 15) - location: virtualMachineConfiguration.?location ?? solutionLocation - tags: virtualMachineConfiguration.?tags ?? tags + name: maintenanceConfigurationResourceName + location: location + tags: tags enableTelemetry: enableTelemetry - vmSize: virtualMachineConfiguration.?vmSize ?? 'Standard_D2s_v3' - adminUsername: virtualMachineConfiguration.?adminUsername ?? 'adminuser' - adminPassword: virtualMachineConfiguration.?adminPassword ?? guid(solutionPrefix, subscription().subscriptionId) - nicConfigurations: [ - { - name: 'nic-${virtualMachineResourceName}' - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - ipConfigurations: [ + extensionProperties: { + InGuestPatchMode: 'User' + } + maintenanceScope: 'InGuestPatch' + maintenanceWindow: { + startDateTime: '2024-06-16 00:00' + duration: '03:55' + timeZone: 'W. Europe Standard Time' + recurEvery: '1Day' + } + visibility: 'Custom' + installPatches: { + rebootSetting: 'IfRequired' + windowsParameters: { + classificationsToInclude: [ + 'Critical' + 'Security' + ] + } + linuxParameters: { + classificationsToInclude: [ + 'Critical' + 'Security' + ] + } + } + } +} + +var dataCollectionRulesResourceName = 'dcr-${solutionSuffix}' +module windowsVmDataCollectionRules 'br/public:avm/res/insights/data-collection-rule:0.6.1' = if (enablePrivateNetworking && enableMonitoring) { + name: take('avm.res.insights.data-collection-rule.${dataCollectionRulesResourceName}', 64) + params: { + name: dataCollectionRulesResourceName + tags: tags + enableTelemetry: enableTelemetry + location: location + dataCollectionRuleProperties: { + kind: 'Windows' + dataSources: { + performanceCounters: [ { - name: '${virtualMachineResourceName}-nic01-ipconfig01' - subnetResourceId: virtualMachineConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[1] - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + streams: [ + 'Microsoft-Perf' + ] + samplingFrequencyInSeconds: 60 + counterSpecifiers: [ + '\\Processor Information(_Total)\\% Processor Time' + '\\Processor Information(_Total)\\% Privileged Time' + '\\Processor Information(_Total)\\% User Time' + '\\Processor Information(_Total)\\Processor Frequency' + '\\System\\Processes' + '\\Process(_Total)\\Thread Count' + '\\Process(_Total)\\Handle Count' + '\\System\\System Up Time' + '\\System\\Context Switches/sec' + '\\System\\Processor Queue Length' + '\\Memory\\% Committed Bytes In Use' + '\\Memory\\Available Bytes' + '\\Memory\\Committed Bytes' + '\\Memory\\Cache Bytes' + '\\Memory\\Pool Paged Bytes' + '\\Memory\\Pool Nonpaged Bytes' + '\\Memory\\Pages/sec' + '\\Memory\\Page Faults/sec' + '\\Process(_Total)\\Working Set' + '\\Process(_Total)\\Working Set - Private' + '\\LogicalDisk(_Total)\\% Disk Time' + '\\LogicalDisk(_Total)\\% Disk Read Time' + '\\LogicalDisk(_Total)\\% Disk Write Time' + '\\LogicalDisk(_Total)\\% Idle Time' + '\\LogicalDisk(_Total)\\Disk Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Read Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Write Bytes/sec' + '\\LogicalDisk(_Total)\\Disk Transfers/sec' + '\\LogicalDisk(_Total)\\Disk Reads/sec' + '\\LogicalDisk(_Total)\\Disk Writes/sec' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Transfer' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Read' + '\\LogicalDisk(_Total)\\Avg. Disk sec/Write' + '\\LogicalDisk(_Total)\\Avg. Disk Queue Length' + '\\LogicalDisk(_Total)\\Avg. Disk Read Queue Length' + '\\LogicalDisk(_Total)\\Avg. Disk Write Queue Length' + '\\LogicalDisk(_Total)\\% Free Space' + '\\LogicalDisk(_Total)\\Free Megabytes' + '\\Network Interface(*)\\Bytes Total/sec' + '\\Network Interface(*)\\Bytes Sent/sec' + '\\Network Interface(*)\\Bytes Received/sec' + '\\Network Interface(*)\\Packets/sec' + '\\Network Interface(*)\\Packets Sent/sec' + '\\Network Interface(*)\\Packets Received/sec' + '\\Network Interface(*)\\Packets Outbound Errors' + '\\Network Interface(*)\\Packets Received Errors' + ] + name: 'perfCounterDataSource60' } ] } - ] + destinations: { + logAnalytics: [ + { + workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId + name: 'la--1264800308' + } + ] + } + dataFlows: [ + { + streams: [ + 'Microsoft-Perf' + ] + destinations: [ + 'la--1264800308' + ] + transformKql: 'source' + outputStream: 'Microsoft-Perf' + } + ] + } + } +} + +var proximityPlacementGroupResourceName = 'ppg-${solutionSuffix}' +module proximityPlacementGroup 'br/public:avm/res/compute/proximity-placement-group:0.4.0' = if (enablePrivateNetworking) { + name: take('avm.res.compute.proximity-placement-group.${proximityPlacementGroupResourceName}', 64) + params: { + name: proximityPlacementGroupResourceName + location: location + tags: tags + enableTelemetry: enableTelemetry + availabilityZone: virtualMachineAvailabilityZone + intent: { vmSizes: [virtualMachineSize] } + } +} + +var virtualMachineResourceName = 'vm-${solutionSuffix}' +var virtualMachineAvailabilityZone = 1 +var virtualMachineSize = 'Standard_D2s_v3' +module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.17.0' = if (enablePrivateNetworking) { + name: take('avm.res.compute.virtual-machine.${virtualMachineResourceName}', 64) + params: { + name: virtualMachineResourceName + location: location + tags: tags + enableTelemetry: enableTelemetry + computerName: take(virtualMachineResourceName, 15) + osType: 'Windows' + vmSize: virtualMachineSize + adminUsername: virtualMachineAdminUsername + adminPassword: virtualMachineAdminPassword + patchMode: 'AutomaticByPlatform' + bypassPlatformSafetyChecksOnUserSchedule: true + maintenanceConfigurationResourceId: maintenanceConfiguration!.outputs.resourceId + enableAutomaticUpdates: true + encryptionAtHost: false + availabilityZone: virtualMachineAvailabilityZone + proximityPlacementGroupResourceId: proximityPlacementGroup!.outputs.resourceId imageReference: { publisher: 'microsoft-dsvm' offer: 'dsvm-win-2022' @@ -662,20 +793,70 @@ module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.13.0' = if (v } osDisk: { name: 'osdisk-${virtualMachineResourceName}' + caching: 'ReadWrite' createOption: 'FromImage' - managedDisk: { - storageAccountType: 'Standard_LRS' - } + deleteOption: 'Delete' diskSizeGB: 128 - caching: 'ReadWrite' + managedDisk: { storageAccountType: 'Premium_LRS' } } - osType: 'Windows' - encryptionAtHost: false //The property 'securityProfile.encryptionAtHost' is not valid because the 'Microsoft.Compute/EncryptionAtHost' feature is not enabled for this subscription. - zone: 0 + nicConfigurations: [ + { + name: 'nic-${virtualMachineResourceName}' + //networkSecurityGroupResourceId: virtualMachineConfiguration.?nicConfigurationConfiguration.networkSecurityGroupResourceId + //nicSuffix: 'nic-${virtualMachineResourceName}' + tags: tags + deleteOption: 'Delete' + diagnosticSettings: enableMonitoring //WAF aligned configuration for Monitoring + ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] + : null + ipConfigurations: [ + { + name: '${virtualMachineResourceName}-nic01-ipconfig01' + subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[1] + diagnosticSettings: enableMonitoring //WAF aligned configuration for Monitoring + ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] + : null + } + ] + } + ] extensionAadJoinConfig: { enabled: true + tags: tags typeHandlerVersion: '1.0' } + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: 'true' + Exclusions: {} + RealtimeProtectionEnabled: 'true' + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + tags: tags + } + //WAF aligned configuration for Monitoring + extensionMonitoringAgentConfig: enableMonitoring + ? { + dataCollectionRuleAssociations: [ + { + dataCollectionRuleResourceId: windowsVmDataCollectionRules!.outputs.resourceId + name: 'send-${logAnalyticsWorkspace!.outputs.name}' + } + ] + enabled: true + tags: tags + } + : null + extensionNetworkWatcherAgentConfig: { + enabled: true + tags: tags + } } } @@ -689,9 +870,9 @@ var openAiPrivateDnsZones = { } module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for zone in objectKeys(openAiPrivateDnsZones): if (virtualNetworkEnabled && aiFoundryAIservicesEnabled) { + for zone in objectKeys(openAiPrivateDnsZones): if (enablePrivateNetworking) { name: take( - 'avm.res.network.private-dns-zone.ai-services.${uniqueString(aiFoundryAiServicesResourceName,zone)}.${solutionPrefix}', + 'avm.res.network.private-dns-zone.ai-services.${uniqueString(aiFoundryAiServicesResourceName,zone)}.${solutionSuffix}', 64 ) params: { @@ -700,8 +881,8 @@ module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7 enableTelemetry: enableTelemetry virtualNetworkLinks: [ { - name: 'vnetlink-${split(zone, '.')[1]}' - virtualNetworkResourceId: virtualNetwork.outputs.resourceId + name: take('vnetlink-${virtualNetworkResourceName}-${split(zone, '.')[1]}', 80) + virtualNetworkResourceId: virtualNetwork!.outputs.resourceId } ] } @@ -709,55 +890,69 @@ module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7 ] // NOTE: Required version 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' not available in AVM -var useExistingFoundryProject = !empty(existingFoundryProjectResourceId) -var existingAiFoundryName = useExistingFoundryProject?split( existingFoundryProjectResourceId,'/')[8]:'' -var aiFoundryAiServicesResourceName = useExistingFoundryProject? existingAiFoundryName : aiFoundryAiServicesConfiguration.?name ?? 'aisa-${solutionPrefix}' -var aiFoundryAIservicesEnabled = aiFoundryAiServicesConfiguration.?enabled ?? true +var aiFoundryAiServicesResourceName = 'aif-${solutionSuffix}' +var aiFoundryAiServicesAiProjectResourceName = 'proj-${solutionSuffix}' +var aiFoundryAIservicesEnabled = true var aiFoundryAiServicesModelDeployment = { format: 'OpenAI' - name: gptModelName - version: gptModelVersion + name: 'gpt-4o' + version: '2024-08-06' sku: { - name: modelDeploymentType - //Curently the capacity is set to 140 for opinanal performance. - capacity: aiFoundryAiServicesConfiguration.?modelCapacity ?? gptModelCapacity + name: 'GlobalStandard' + //Currently the capacity is set to 140 for optimal performance. + capacity: 140 } raiPolicyName: 'Microsoft.Default' } -module aiFoundryAiServices 'modules/account/main.bicep' = if (aiFoundryAIservicesEnabled) { +//TODO: update to AVM module when AI Projects and AI Projects RBAC are supported +module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservicesEnabled) { name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) params: { name: aiFoundryAiServicesResourceName - tags: aiFoundryAiServicesConfiguration.?tags ?? tags - location: aiFoundryAiServicesConfiguration.?location ?? aiDeploymentsLocation - enableTelemetry: enableTelemetry - projectName: 'aifp-${solutionPrefix}' - projectDescription: 'aifp-${solutionPrefix}' - existingFoundryProjectResourceId: existingFoundryProjectResourceId - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - sku: aiFoundryAiServicesConfiguration.?sku ?? 'S0' + location: azureAiServiceLocation + tags: tags + projectName: aiFoundryAiServicesAiProjectResourceName + projectDescription: 'AI Foundry Project' + sku: 'S0' kind: 'AIServices' - disableLocalAuth: true //Should be set to true for WAF aligned configuration + disableLocalAuth: true customSubDomainName: aiFoundryAiServicesResourceName apiProperties: { //staticsEnabled: false } - allowProjectManagement: true - managedIdentities: { - systemAssigned: true - } - publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' networkAcls: { - bypass: 'AzureServices' - defaultAction: (virtualNetworkEnabled) ? 'Deny' : 'Allow' + defaultAction: 'Allow' + virtualNetworkRules: [] + ipRules: [] } - privateEndpoints: virtualNetworkEnabled && !useExistingFoundryProject + managedIdentities: { userAssignedResourceIds: [userAssignedIdentity!.outputs.resourceId] } //To create accounts or projects, you must enable a managed identity on your resource + roleAssignments: [ + { + roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' // Azure AI Developer + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' // Cognitive Services OpenAI User + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + } + ] + // WAF aligned configuration for Monitoring + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' + privateEndpoints: enablePrivateNetworking ? ([ { name: 'pep-${aiFoundryAiServicesResourceName}' customNetworkInterfaceName: 'nic-${aiFoundryAiServicesResourceName}' - subnetResourceId: aiFoundryAiServicesConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[0] + subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] privateDnsZoneGroup: { privateDnsZoneGroupConfigs: map(objectKeys(openAiPrivateDnsZones), zone => { name: replace(zone, '.', '-') @@ -766,8 +961,8 @@ module aiFoundryAiServices 'modules/account/main.bicep' = if (aiFoundryAIservice } } ]) - : [] - deployments: aiFoundryAiServicesConfiguration.?deployments ?? [ + : [] + deployments: [ { name: aiFoundryAiServicesModelDeployment.name model: { @@ -785,81 +980,74 @@ module aiFoundryAiServices 'modules/account/main.bicep' = if (aiFoundryAIservice } } -// AI Foundry: AI Project -// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -var existingAiFounryProjectName = useExistingFoundryProject ? last(split( existingFoundryProjectResourceId,'/')) : '' -var aiFoundryAiProjectName = useExistingFoundryProject ? existingAiFounryProjectName : aiFoundryAiProjectConfiguration.?name ?? 'aifp-${solutionPrefix}' - -var useExistingResourceId = !empty(existingFoundryProjectResourceId) +//Role assignments for AI Project +module resourceRoleAssignmentAiServicesAiProjectAiUser 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.2' = { + name: 'avm.ptn.authorization.resource-role-assignment.${uniqueString(aiFoundryAiServicesAiProjectResourceName,containerAppResourceName,'Azure AI User')}' + params: { + roleName: 'Azure AI User' + roleDefinitionId: '53ca6127-db72-4b80-b1b0-d745d6d5456d' + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + resourceId: aiFoundryAiServices.outputs.aiProjectResourceId + enableTelemetry: enableTelemetry + } +} -module cogServiceRoleAssignmentsNew './modules/role.bicep' = if(!useExistingResourceId) { +module resourceRoleAssignmentAiServicesAiProjectAiDeveloper 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.2' = { + name: 'avm.ptn.authorization.resource-role-assignment.${uniqueString(aiFoundryAiServicesAiProjectResourceName,containerAppResourceName,'Azure AI Developer')}' params: { - name: 'new-${guid(containerApp.name, aiFoundryAiServices.outputs.resourceId)}' - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - aiServiceName: aiFoundryAiServices.outputs.name + roleName: 'Azure AI Developer' + roleDefinitionId: '64702f94-c441-49e6-a78b-ef80e0188fee' + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + resourceId: aiFoundryAiServices.outputs.aiProjectResourceId + enableTelemetry: enableTelemetry } - scope: resourceGroup(subscription().subscriptionId, resourceGroup().name) } -module cogServiceRoleAssignmentsExisting './modules/role.bicep' = if(useExistingResourceId) { +module resourceRoleAssignmentAiServicesAiProjectCognitiveServicesOpenAiUser 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.2' = { + name: 'avm.ptn.authorization.resource-role-assignment.${uniqueString(aiFoundryAiServicesAiProjectResourceName,containerAppResourceName,'Cognitive Services OpenAI User')}' params: { - name: 'reuse-${guid(containerApp.name, aiFoundryAiServices.outputs.aiProjectInfo.resourceId)}' - principalId: containerApp.outputs.?systemAssignedMIPrincipalId! - aiServiceName: aiFoundryAiServices.outputs.name + roleName: 'Cognitive Services OpenAI User' + roleDefinitionId: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + resourceId: aiFoundryAiServices.outputs.aiProjectResourceId + enableTelemetry: enableTelemetry } - scope: resourceGroup( split(existingFoundryProjectResourceId, '/')[2], split(existingFoundryProjectResourceId, '/')[4]) } // ========== Cosmos DB ========== // // WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db -module privateDnsZonesCosmosDb 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (virtualNetworkEnabled) { - name: take('avm.res.network.private-dns-zone.cosmos-db.${solutionPrefix}', 64) +module privateDnsZonesCosmosDb 'br/public:avm/res/network/private-dns-zone:0.7.1' = if (enablePrivateNetworking) { + name: take('avm.res.network.private-dns-zone.cosmos-db.${solutionSuffix}', 64) params: { name: 'privatelink.documents.azure.com' enableTelemetry: enableTelemetry virtualNetworkLinks: [ { - name: 'vnetlink-cosmosdb' - virtualNetworkResourceId: virtualNetwork.outputs.resourceId + name: take('vnetlink-${virtualNetworkResourceName}-documents', 80) + virtualNetworkResourceId: virtualNetwork!.outputs.resourceId } ] tags: tags } } -var cosmosDbAccountEnabled = cosmosDbAccountConfiguration.?enabled ?? true -var cosmosDbResourceName = cosmosDbAccountConfiguration.?name ?? 'cosmos-${solutionPrefix}' +var cosmosDbResourceName = 'cosmos-${solutionSuffix}' var cosmosDbDatabaseName = 'macae' var cosmosDbDatabaseMemoryContainerName = 'memory' -module cosmosDb 'br/public:avm/res/document-db/database-account:0.12.0' = if (cosmosDbAccountEnabled) { + +//TODO: update to latest version of AVM module +module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { name: take('avm.res.document-db.database-account.${cosmosDbResourceName}', 64) params: { // Required parameters - name: cosmosDbAccountConfiguration.?name ?? 'cosmos-${solutionPrefix}' - location: cosmosDbAccountConfiguration.?location ?? solutionLocation - tags: cosmosDbAccountConfiguration.?tags ?? tags + name: cosmosDbResourceName + location: location + tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - databaseAccountOfferType: 'Standard' - enableFreeTier: false - networkRestrictions: { - networkAclBypass: 'None' - publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' - } - privateEndpoints: virtualNetworkEnabled - ? [ - { - name: 'pep-${cosmosDbResourceName}' - customNetworkInterfaceName: 'nic-${cosmosDbResourceName}' - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesCosmosDb.outputs.resourceId }] - } - service: 'Sql' - subnetResourceId: cosmosDbAccountConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[0] - } - ] - : [] - sqlDatabases: concat(cosmosDbAccountConfiguration.?sqlDatabases ?? [], [ + sqlDatabases: [ { name: cosmosDbDatabaseName containers: [ @@ -873,92 +1061,184 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.12.0' = if (co } ] } - ]) - locations: [ - { - locationName: cosmosDbAccountConfiguration.?location ?? solutionLocation - failoverPriority: 0 - isZoneRedundant: false - } - ] - capabilitiesToAdd: [ - 'EnableServerless' - ] - sqlRoleAssignmentsPrincipalIds: [ - containerApp.outputs.?systemAssignedMIPrincipalId ] - sqlRoleDefinitions: [ + dataPlaneRoleDefinitions: [ { - // Replace this with built-in role definition Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor - roleType: 'CustomRole' + // Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor roleName: 'Cosmos DB SQL Data Contributor' - name: 'cosmos-db-sql-data-contributor' - dataAction: [ + dataActions: [ 'Microsoft.DocumentDB/databaseAccounts/readMetadata' 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' ] + assignments: [{ principalId: userAssignedIdentity.outputs.principalId }] } ] + // WAF aligned configuration for Monitoring + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + // WAF aligned configuration for Private Networking + networkRestrictions: { + networkAclBypass: 'None' + publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' + } + privateEndpoints: enablePrivateNetworking + ? [ + { + name: 'pep-${cosmosDbResourceName}' + customNetworkInterfaceName: 'nic-${cosmosDbResourceName}' + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesCosmosDb!.outputs.resourceId }] + } + service: 'Sql' + subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] + } + ] + : [] + // WAF aligned configuration for Redundancy + zoneRedundant: enableRedundancy ? true : false + capabilitiesToAdd: enableRedundancy ? null : ['EnableServerless'] + automaticFailover: enableRedundancy ? true : false + failoverLocations: enableRedundancy + ? [ + { + failoverPriority: 0 + isZoneRedundant: true + locationName: location + } + { + failoverPriority: 1 + isZoneRedundant: true + locationName: cosmosDbHaLocation + } + ] + : [ + { + locationName: location + failoverPriority: 0 + } + ] } } // ========== Backend Container App Environment ========== // // WAF best practices for container apps: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-container-apps -var containerAppEnvironmentEnabled = containerAppEnvironmentConfiguration.?enabled ?? true -var containerAppEnvironmentResourceName = containerAppEnvironmentConfiguration.?name ?? 'cae-${solutionPrefix}' -module containerAppEnvironment 'modules/container-app-environment.bicep' = if (containerAppEnvironmentEnabled) { - name: take('module.container-app-environment.${containerAppEnvironmentResourceName}', 64) +// PSRule for Container App: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#container-app +var containerAppEnvironmentResourceName = 'cae-${solutionSuffix}' +module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2' = { + name: take('avm.res.app.managed-environment.${containerAppEnvironmentResourceName}', 64) params: { name: containerAppEnvironmentResourceName - tags: containerAppEnvironmentConfiguration.?tags ?? tags - location: containerAppEnvironmentConfiguration.?location ?? solutionLocation - logAnalyticsResourceId: logAnalyticsWorkspaceId - publicNetworkAccess: 'Enabled' - zoneRedundant: false - applicationInsightsConnectionString: applicationInsights.outputs.connectionString + location: location + tags: tags + enableTelemetry: enableTelemetry + // WAF aligned configuration for Private Networking + publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' + internal: enablePrivateNetworking ? true : false + infrastructureSubnetResourceId: enablePrivateNetworking ? virtualNetwork.?outputs.?subnetResourceIds[3] : null + // WAF aligned configuration for Monitoring + appLogsConfiguration: enableMonitoring + ? { + destination: 'log-analytics' + logAnalyticsConfiguration: { + customerId: logAnalyticsWorkspace!.outputs.logAnalyticsWorkspaceId + sharedKey: logAnalyticsWorkspace!.outputs.primarySharedKey + } + } + : null + appInsightsConnectionString: enableMonitoring ? applicationInsights!.outputs.connectionString : null + // WAF aligned configuration for Redundancy + zoneRedundant: enableRedundancy ? true : false + infrastructureResourceGroupName: enableRedundancy ? '${resourceGroup().name}-infra' : null + workloadProfiles: enableRedundancy + ? [ + { + maximumCount: 3 + minimumCount: 3 + name: 'CAW01' + workloadProfileType: 'D4' + } + ] + : [ + { + name: 'Consumption' + workloadProfileType: 'Consumption' + } + ] + } +} + +// Private DNS Zone Group for Container App Environment Private Endpoint +module privateDnsZonesContainerAppEnvironment 'br/public:avm/res/network/private-dns-zone:0.7.1' = if (enablePrivateNetworking) { + name: take('avm.res.network.private-dns-zone.app-environment.${solutionSuffix}', 64) + params: { + name: 'privatelink.${toLower(replace(containerAppEnvironment.outputs.location,' ',''))}.azurecontainerapps.io' enableTelemetry: enableTelemetry - subnetResourceId: virtualNetworkEnabled - ? containerAppEnvironmentConfiguration.?subnetResourceId ?? virtualNetwork.?outputs.?subnetResourceIds[3] ?? '' - : '' + virtualNetworkLinks: [{ virtualNetworkResourceId: virtualNetwork!.outputs.resourceId }] + tags: tags + } +} + +// Private Endpoint for Container App Environment +var privateEndpointContainerAppEnvironmentService = 'managedEnvironments' +module privateEndpointContainerAppEnvironment 'br:mcr.microsoft.com/bicep/avm/res/network/private-endpoint:0.11.0' = if (enablePrivateNetworking) { + name: take('avm.res.network.private-endpoint.app-environment.${solutionSuffix}', 64) + params: { + name: 'pep-${containerAppEnvironmentResourceName}' + location: location + tags: tags + enableTelemetry: enableTelemetry + subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] + customNetworkInterfaceName: 'nic-${containerAppEnvironmentResourceName}' + privateLinkServiceConnections: [ + { + name: '${last(split(containerAppEnvironment.outputs.resourceId, '/'))}-${privateEndpointContainerAppEnvironmentService}-0' + + properties: { + groupIds: [privateEndpointContainerAppEnvironmentService] + privateLinkServiceId: containerAppEnvironment.outputs.resourceId + } + } + ] + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [ + { privateDnsZoneResourceId: privateDnsZonesContainerAppEnvironment!.outputs.resourceId } + ] + } } } // ========== Backend Container App Service ========== // // WAF best practices for container apps: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-container-apps -var containerAppEnabled = containerAppConfiguration.?enabled ?? true -var containerAppResourceName = containerAppConfiguration.?name ?? 'ca-${solutionPrefix}' -module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (containerAppEnabled) { +// PSRule for Container App: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#container-app +var containerAppResourceName = 'ca-${solutionSuffix}' +module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { name: take('avm.res.app.container-app.${containerAppResourceName}', 64) params: { name: containerAppResourceName - tags: containerAppConfiguration.?tags ?? tags - location: containerAppConfiguration.?location ?? solutionLocation + tags: tags + location: location enableTelemetry: enableTelemetry - environmentResourceId: containerAppConfiguration.?environmentResourceId ?? containerAppEnvironment.outputs.resourceId - managedIdentities: { - systemAssigned: true //Replace with user assigned identity - userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] - } - ingressTargetPort: containerAppConfiguration.?ingressTargetPort ?? 8000 + environmentResourceId: containerAppEnvironment.outputs.resourceId + managedIdentities: { userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] } + ingressTargetPort: 8000 ingressExternal: true activeRevisionsMode: 'Single' corsPolicy: { allowedOrigins: [ - 'https://${webSiteName}.azurewebsites.net' - 'http://${webSiteName}.azurewebsites.net' + 'https://${webSiteResourceName}.azurewebsites.net' + 'http://${webSiteResourceName}.azurewebsites.net' ] } + // WAF aligned configuration for Scalability scaleSettings: { - //TODO: Make maxReplicas and minReplicas parameterized - maxReplicas: containerAppConfiguration.?maxReplicas ?? 1 - minReplicas: containerAppConfiguration.?minReplicas ?? 1 + maxReplicas: enableScalability ? 3 : 1 + minReplicas: enableScalability ? 2 : 1 rules: [ { name: 'http-scaler' http: { metadata: { - concurrentRequests: containerAppConfiguration.?concurrentRequests ?? '100' + concurrentRequests: '100' } } } @@ -966,12 +1246,29 @@ module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (container } containers: [ { - name: containerAppConfiguration.?containerName ?? 'backend' - image: '${containerAppConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}/${containerAppConfiguration.?containerImageName ?? 'macaebackend'}:${containerAppConfiguration.?containerImageTag ?? 'latest'}' + name: 'backend' + image: '${backendContainerRegistryHostname}/${backendContainerImageName}:${backendContainerImageTag}' + //TODO: configure probes for container app + // probes: [ + // { + // httpGet: { + // httpHeaders: [ + // { + // name: 'Custom-Header' + // value: 'Awesome' + // } + // ] + // path: '/health' + // port: 8080 + // } + // initialDelaySeconds: 3 + // periodSeconds: 3 + // type: 'Liveness' + // } + // ] resources: { - //TODO: Make cpu and memory parameterized - cpu: containerAppConfiguration.?containerCpu ?? '2.0' - memory: containerAppConfiguration.?containerMemory ?? '4.0Gi' + cpu: '2.0' + memory: '4.0Gi' } env: [ { @@ -1004,11 +1301,11 @@ module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (container } { name: 'APPLICATIONINSIGHTS_INSTRUMENTATION_KEY' - value: applicationInsights.outputs.instrumentationKey + value: enableMonitoring ? applicationInsights!.outputs.instrumentationKey : '' } { name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' - value: applicationInsights.outputs.connectionString + value: enableMonitoring ? applicationInsights!.outputs.connectionString : '' } { name: 'AZURE_AI_SUBSCRIPTION_ID' @@ -1020,79 +1317,111 @@ module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (container } { name: 'AZURE_AI_PROJECT_NAME' - value: aiFoundryAiProjectName + value: aiFoundryAiServicesAiProjectResourceName } { name: 'FRONTEND_SITE_NAME' - value: 'https://${webSiteName}.azurewebsites.net' + value: 'https://${webSiteResourceName}.azurewebsites.net' } { name: 'AZURE_AI_AGENT_ENDPOINT' - value: aiFoundryAiServices.outputs.aiProjectInfo.apiEndpoint + value: aiFoundryAiServices.outputs.aiProjectApiEndpoint } { name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' value: aiFoundryAiServicesModelDeployment.name } - { - name: 'APP_ENV' - value: 'Prod' - } ] } ] } } -var webServerFarmEnabled = webServerFarmConfiguration.?enabled ?? true -var webServerFarmResourceName = webServerFarmConfiguration.?name ?? 'asp-${solutionPrefix}' - // ========== Frontend server farm ========== // -// WAF best practices for web app service: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps -module webServerFarm 'br/public:avm/res/web/serverfarm:0.4.1' = if (webServerFarmEnabled) { +// WAF best practices for Web Application Services: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps +// PSRule for Web Server Farm: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#app-service +var webServerFarmResourceName = 'asp-${solutionSuffix}' +module webServerFarm 'br/public:avm/res/web/serverfarm:0.5.0' = { name: take('avm.res.web.serverfarm.${webServerFarmResourceName}', 64) params: { name: webServerFarmResourceName tags: tags - location: webServerFarmConfiguration.?location ?? solutionLocation - skuName: webServerFarmConfiguration.?skuName ?? 'P1v3' - skuCapacity: webServerFarmConfiguration.?skuCapacity ?? 3 + enableTelemetry: enableTelemetry + location: location reserved: true - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] kind: 'linux' - zoneRedundant: false //TODO: make it zone redundant for waf aligned + // WAF aligned configuration for Monitoring + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + // WAF aligned configuration for Scalability + skuName: enableScalability || enableRedundancy ? 'P1v3' : 'B3' + skuCapacity: enableScalability ? 3 : 1 + // WAF aligned configuration for Redundancy + zoneRedundant: enableRedundancy ? true : false } } // ========== Frontend web site ========== // // WAF best practices for web app service: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps -var webSiteEnabled = webSiteConfiguration.?enabled ?? true +// PSRule for Web Server Farm: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#app-service +// Private DNS Zone Group for Web App Service Private Endpoint +module privateDnsZonesWebApp 'br/public:avm/res/network/private-dns-zone:0.7.1' = if (enablePrivateNetworking) { + name: take('avm.res.network.private-dns-zone.web-app.${solutionSuffix}', 64) + params: { + name: 'privatelink.azurewebsites.net' + enableTelemetry: enableTelemetry + virtualNetworkLinks: [{ virtualNetworkResourceId: virtualNetwork!.outputs.resourceId }] + tags: tags + } +} -var webSiteName = 'app-${solutionPrefix}' -module webSite 'br/public:avm/res/web/site:0.15.1' = if (webSiteEnabled) { - name: take('avm.res.web.site.${webSiteName}', 64) +//NOTE: AVM module adds 1 MB of overhead to the template. Keeping vanilla resource to save template size. +var webSiteResourceName = 'app-${solutionSuffix}' +module webSite 'modules/web-sites.bicep' = { + name: take('module.web-sites.${webSiteResourceName}', 64) params: { - name: webSiteName - tags: webSiteConfiguration.?tags ?? tags - location: webSiteConfiguration.?location ?? solutionLocation + name: webSiteResourceName + tags: tags + location: location kind: 'app,linux,container' - enableTelemetry: enableTelemetry - serverFarmResourceId: webSiteConfiguration.?environmentResourceId ?? webServerFarm.?outputs.resourceId - appInsightResourceId: applicationInsights.outputs.resourceId - diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] - publicNetworkAccess: 'Enabled' //TODO: use Azure Front Door WAF or Application Gateway WAF instead + serverFarmResourceId: webServerFarm.?outputs.resourceId siteConfig: { - linuxFxVersion: 'DOCKER|${webSiteConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}/${webSiteConfiguration.?containerImageName ?? 'macaefrontend'}:${webSiteConfiguration.?containerImageTag ?? 'latest'}' - } - appSettingsKeyValuePairs: { - SCM_DO_BUILD_DURING_DEPLOYMENT: 'true' - DOCKER_REGISTRY_SERVER_URL: 'https://${webSiteConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}' - WEBSITES_PORT: '3000' - WEBSITES_CONTAINER_START_TIME_LIMIT: '1800' // 30 minutes, adjust as needed - BACKEND_API_URL: 'https://${containerApp.outputs.fqdn}' - AUTH_ENABLED: 'false' - APP_ENV: 'Prod' + linuxFxVersion: 'DOCKER|${frontendContainerRegistryHostname}/${frontendContainerImageName}:${frontendContainerImageTag}' + minTlsVersion: '1.2' } + configs: [ + { + name: 'appsettings' + properties: { + SCM_DO_BUILD_DURING_DEPLOYMENT: 'true' + DOCKER_REGISTRY_SERVER_URL: 'https://${frontendContainerRegistryHostname}' + WEBSITES_PORT: '3000' + WEBSITES_CONTAINER_START_TIME_LIMIT: '1800' // 30 minutes, adjust as needed + BACKEND_API_URL: 'https://${containerApp.outputs.fqdn}' + AUTH_ENABLED: 'false' + } + // WAF aligned configuration for Monitoring + applicationInsightResourceId: enableMonitoring ? applicationInsights!.outputs.resourceId : null + } + ] + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + // WAF aligned configuration for Private Networking + vnetRouteAllEnabled: enablePrivateNetworking ? true : false + vnetImagePullEnabled: enablePrivateNetworking ? true : false + virtualNetworkSubnetId: enablePrivateNetworking ? virtualNetwork!.outputs.subnetResourceIds[4] : null + publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' + privateEndpoints: enablePrivateNetworking + ? [ + { + name: 'pep-${webSiteResourceName}' + customNetworkInterfaceName: 'nic-${webSiteResourceName}' + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesWebApp!.outputs.resourceId }] + } + service: 'sites' + subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] + } + ] + : null } } @@ -1100,621 +1429,8 @@ module webSite 'br/public:avm/res/web/site:0.15.1' = if (webSiteEnabled) { // Outputs // // ============ // -// Add your outputs here +@description('The resource group the resources were deployed into.') +output resourceGroupName string = resourceGroup().name @description('The default url of the website to connect to the Multi-Agent Custom Automation Engine solution.') output webSiteDefaultHostname string = webSite.outputs.defaultHostname - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource configuration.') -type logAnalyticsWorkspaceConfigurationType = { - @description('Optional. If the Log Analytics Workspace resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Log Analytics Workspace resource.') - @maxLength(63) - name: string? - - @description('Optional. Location for the Log Analytics Workspace resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to for the Log Analytics Workspace resource.') - tags: object? - - @description('Optional. The SKU for the Log Analytics Workspace resource.') - sku: ('CapacityReservation' | 'Free' | 'LACluster' | 'PerGB2018' | 'PerNode' | 'Premium' | 'Standalone' | 'Standard')? - - @description('Optional. The number of days to retain the data in the Log Analytics Workspace. If empty, it will be set to 365 days.') - @maxValue(730) - dataRetentionInDays: int? - - @description('Optional: Existing Log Analytics Workspace Resource ID') - existingWorkspaceResourceId: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Application Insights resource configuration.') -type applicationInsightsConfigurationType = { - @description('Optional. If the Application Insights resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Application Insights resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Application Insights resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Application Insights resource.') - tags: object? - - @description('Optional. The retention of Application Insights data in days. If empty, Standard will be used.') - retentionInDays: (120 | 180 | 270 | 30 | 365 | 550 | 60 | 730 | 90)? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Application User Assigned Managed Identity resource configuration.') -type userAssignedManagedIdentityType = { - @description('Optional. If the User Assigned Managed Identity resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the User Assigned Managed Identity resource.') - @maxLength(128) - name: string? - - @description('Optional. Location for the User Assigned Managed Identity resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the User Assigned Managed Identity resource.') - tags: object? -} - -@export() -import { securityRuleType } from 'br/public:avm/res/network/network-security-group:0.5.1' -@description('The type for the Multi-Agent Custom Automation Engine Network Security Group resource configuration.') -type networkSecurityGroupConfigurationType = { - @description('Optional. If the Network Security Group resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Network Security Group resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Network Security Group resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Network Security Group resource.') - tags: object? - - @description('Optional. The security rules to set for the Network Security Group resource.') - securityRules: securityRuleType[]? -} - -@export() -@description('The type for the Multi-Agent Custom Automation virtual network resource configuration.') -type virtualNetworkConfigurationType = { - @description('Optional. If the Virtual Network resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Virtual Network resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Virtual Network resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Virtual Network resource.') - tags: object? - - @description('Optional. An array of 1 or more IP Addresses prefixes for the Virtual Network resource.') - addressPrefixes: string[]? - - @description('Optional. An array of 1 or more subnets for the Virtual Network resource.') - subnets: subnetType[]? -} - -import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -type subnetType = { - @description('Optional. The Name of the subnet resource.') - name: string - - @description('Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty.') - addressPrefix: string? - - @description('Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty.') - addressPrefixes: string[]? - - @description('Optional. Application gateway IP configurations of virtual network resource.') - applicationGatewayIPConfigurations: object[]? - - @description('Optional. The delegation to enable on the subnet.') - delegation: string? - - @description('Optional. The resource ID of the NAT Gateway to use for the subnet.') - natGatewayResourceId: string? - - @description('Optional. The resource ID of the network security group to assign to the subnet.') - networkSecurityGroupResourceId: string? - - @description('Optional. enable or disable apply network policies on private endpoint in the subnet.') - privateEndpointNetworkPolicies: ('Disabled' | 'Enabled' | 'NetworkSecurityGroupEnabled' | 'RouteTableEnabled')? - - @description('Optional. enable or disable apply network policies on private link service in the subnet.') - privateLinkServiceNetworkPolicies: ('Disabled' | 'Enabled')? - - @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType[]? - - @description('Optional. The resource ID of the route table to assign to the subnet.') - routeTableResourceId: string? - - @description('Optional. An array of service endpoint policies.') - serviceEndpointPolicies: object[]? - - @description('Optional. The service endpoints to enable on the subnet.') - serviceEndpoints: string[]? - - @description('Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet.') - defaultOutboundAccess: bool? - - @description('Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty.') - sharingScope: ('DelegatedServices' | 'Tenant')? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Bastion resource configuration.') -type bastionConfigurationType = { - @description('Optional. If the Bastion resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Bastion resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Bastion resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Bastion resource.') - tags: object? - - @description('Optional. The SKU for the Bastion resource.') - sku: ('Basic' | 'Developer' | 'Premium' | 'Standard')? - - @description('Optional. The Virtual Network resource id where the Bastion resource should be deployed.') - virtualNetworkResourceId: string? - - @description('Optional. The name of the Public Ip resource created to connect to Bastion.') - publicIpResourceName: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine virtual machine resource configuration.') -type virtualMachineConfigurationType = { - @description('Optional. If the Virtual Machine resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Virtual Machine resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the Virtual Machine resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Virtual Machine resource.') - tags: object? - - @description('Optional. Specifies the size for the Virtual Machine resource.') - vmSize: ( - | 'Basic_A0' - | 'Basic_A1' - | 'Basic_A2' - | 'Basic_A3' - | 'Basic_A4' - | 'Standard_A0' - | 'Standard_A1' - | 'Standard_A2' - | 'Standard_A3' - | 'Standard_A4' - | 'Standard_A5' - | 'Standard_A6' - | 'Standard_A7' - | 'Standard_A8' - | 'Standard_A9' - | 'Standard_A10' - | 'Standard_A11' - | 'Standard_A1_v2' - | 'Standard_A2_v2' - | 'Standard_A4_v2' - | 'Standard_A8_v2' - | 'Standard_A2m_v2' - | 'Standard_A4m_v2' - | 'Standard_A8m_v2' - | 'Standard_B1s' - | 'Standard_B1ms' - | 'Standard_B2s' - | 'Standard_B2ms' - | 'Standard_B4ms' - | 'Standard_B8ms' - | 'Standard_D1' - | 'Standard_D2' - | 'Standard_D3' - | 'Standard_D4' - | 'Standard_D11' - | 'Standard_D12' - | 'Standard_D13' - | 'Standard_D14' - | 'Standard_D1_v2' - | 'Standard_D2_v2' - | 'Standard_D3_v2' - | 'Standard_D4_v2' - | 'Standard_D5_v2' - | 'Standard_D2_v3' - | 'Standard_D4_v3' - | 'Standard_D8_v3' - | 'Standard_D16_v3' - | 'Standard_D32_v3' - | 'Standard_D64_v3' - | 'Standard_D2s_v3' - | 'Standard_D4s_v3' - | 'Standard_D8s_v3' - | 'Standard_D16s_v3' - | 'Standard_D32s_v3' - | 'Standard_D64s_v3' - | 'Standard_D11_v2' - | 'Standard_D12_v2' - | 'Standard_D13_v2' - | 'Standard_D14_v2' - | 'Standard_D15_v2' - | 'Standard_DS1' - | 'Standard_DS2' - | 'Standard_DS3' - | 'Standard_DS4' - | 'Standard_DS11' - | 'Standard_DS12' - | 'Standard_DS13' - | 'Standard_DS14' - | 'Standard_DS1_v2' - | 'Standard_DS2_v2' - | 'Standard_DS3_v2' - | 'Standard_DS4_v2' - | 'Standard_DS5_v2' - | 'Standard_DS11_v2' - | 'Standard_DS12_v2' - | 'Standard_DS13_v2' - | 'Standard_DS14_v2' - | 'Standard_DS15_v2' - | 'Standard_DS13-4_v2' - | 'Standard_DS13-2_v2' - | 'Standard_DS14-8_v2' - | 'Standard_DS14-4_v2' - | 'Standard_E2_v3' - | 'Standard_E4_v3' - | 'Standard_E8_v3' - | 'Standard_E16_v3' - | 'Standard_E32_v3' - | 'Standard_E64_v3' - | 'Standard_E2s_v3' - | 'Standard_E4s_v3' - | 'Standard_E8s_v3' - | 'Standard_E16s_v3' - | 'Standard_E32s_v3' - | 'Standard_E64s_v3' - | 'Standard_E32-16_v3' - | 'Standard_E32-8s_v3' - | 'Standard_E64-32s_v3' - | 'Standard_E64-16s_v3' - | 'Standard_F1' - | 'Standard_F2' - | 'Standard_F4' - | 'Standard_F8' - | 'Standard_F16' - | 'Standard_F1s' - | 'Standard_F2s' - | 'Standard_F4s' - | 'Standard_F8s' - | 'Standard_F16s' - | 'Standard_F2s_v2' - | 'Standard_F4s_v2' - | 'Standard_F8s_v2' - | 'Standard_F16s_v2' - | 'Standard_F32s_v2' - | 'Standard_F64s_v2' - | 'Standard_F72s_v2' - | 'Standard_G1' - | 'Standard_G2' - | 'Standard_G3' - | 'Standard_G4' - | 'Standard_G5' - | 'Standard_GS1' - | 'Standard_GS2' - | 'Standard_GS3' - | 'Standard_GS4' - | 'Standard_GS5' - | 'Standard_GS4-8' - | 'Standard_GS4-4' - | 'Standard_GS5-16' - | 'Standard_GS5-8' - | 'Standard_H8' - | 'Standard_H16' - | 'Standard_H8m' - | 'Standard_H16m' - | 'Standard_H16r' - | 'Standard_H16mr' - | 'Standard_L4s' - | 'Standard_L8s' - | 'Standard_L16s' - | 'Standard_L32s' - | 'Standard_M64s' - | 'Standard_M64ms' - | 'Standard_M128s' - | 'Standard_M128ms' - | 'Standard_M64-32ms' - | 'Standard_M64-16ms' - | 'Standard_M128-64ms' - | 'Standard_M128-32ms' - | 'Standard_NC6' - | 'Standard_NC12' - | 'Standard_NC24' - | 'Standard_NC24r' - | 'Standard_NC6s_v2' - | 'Standard_NC12s_v2' - | 'Standard_NC24s_v2' - | 'Standard_NC24rs_v2' - | 'Standard_NC6s_v3' - | 'Standard_NC12s_v3' - | 'Standard_NC24s_v3' - | 'Standard_NC24rs_v3' - | 'Standard_ND6s' - | 'Standard_ND12s' - | 'Standard_ND24s' - | 'Standard_ND24rs' - | 'Standard_NV6' - | 'Standard_NV12' - | 'Standard_NV24')? - - @description('Optional. The username for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') - adminUsername: string? - - @description('Optional. The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') - @secure() - adminPassword: string? - - @description('Optional. The resource ID of the subnet where the Virtual Machine resource should be deployed.') - subnetResourceId: string? -} - -@export() -import { deploymentType } from 'br/public:avm/res/cognitive-services/account:0.10.2' -@description('The type for the Multi-Agent Custom Automation Engine AI Services resource configuration.') -type aiServicesConfigurationType = { - @description('Optional. If the AI Services resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the AI Services resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the AI Services resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the AI Services resource.') - tags: object? - - @description('Optional. The SKU of the AI Services resource. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') - sku: ( - | 'C2' - | 'C3' - | 'C4' - | 'F0' - | 'F1' - | 'S' - | 'S0' - | 'S1' - | 'S10' - | 'S2' - | 'S3' - | 'S4' - | 'S5' - | 'S6' - | 'S7' - | 'S8' - | 'S9')? - - @description('Optional. The resource Id of the subnet where the AI Services private endpoint should be created.') - subnetResourceId: string? - - @description('Optional. The model deployments to set for the AI Services resource.') - deployments: deploymentType[]? - - @description('Optional. The capacity to set for AI Services GTP model.') - modelCapacity: int? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine AI Foundry AI Project resource configuration.') -type aiProjectConfigurationType = { - @description('Optional. If the AI Project resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the AI Project resource.') - @maxLength(90) - name: string? - - @description('Optional. Location for the AI Project resource deployment.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The SKU of the AI Project resource.') - sku: ('Basic' | 'Free' | 'Standard' | 'Premium')? - - @description('Optional. The tags to set for the AI Project resource.') - tags: object? -} - -import { sqlDatabaseType } from 'br/public:avm/res/document-db/database-account:0.13.0' -@export() -@description('The type for the Multi-Agent Custom Automation Engine Cosmos DB Account resource configuration.') -type cosmosDbAccountConfigurationType = { - @description('Optional. If the Cosmos DB Account resource should be deployed or not.') - enabled: bool? - @description('Optional. The name of the Cosmos DB Account resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Cosmos DB Account resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Cosmos DB Account resource.') - tags: object? - - @description('Optional. The resource Id of the subnet where the Cosmos DB Account private endpoint should be created.') - subnetResourceId: string? - - @description('Optional. The SQL databases configuration for the Cosmos DB Account resource.') - sqlDatabases: sqlDatabaseType[]? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Container App Environment resource configuration.') -type containerAppEnvironmentConfigurationType = { - @description('Optional. If the Container App Environment resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Container App Environment resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Container App Environment resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Container App Environment resource.') - tags: object? - - @description('Optional. The resource Id of the subnet where the Container App Environment private endpoint should be created.') - subnetResourceId: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Container App resource configuration.') -type containerAppConfigurationType = { - @description('Optional. If the Container App resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Container App resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Container App resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Container App resource.') - tags: object? - - @description('Optional. The resource Id of the Container App Environment where the Container App should be created.') - environmentResourceId: string? - - @description('Optional. The maximum number of replicas of the Container App.') - maxReplicas: int? - - @description('Optional. The minimum number of replicas of the Container App.') - minReplicas: int? - - @description('Optional. The ingress target port of the Container App.') - ingressTargetPort: int? - - @description('Optional. The concurrent requests allowed for the Container App.') - concurrentRequests: string? - - @description('Optional. The name given to the Container App.') - containerName: string? - - @description('Optional. The container registry domain of the container image to be used by the Container App. Default to `biabcontainerreg.azurecr.io`') - containerImageRegistryDomain: string? - - @description('Optional. The name of the container image to be used by the Container App.') - containerImageName: string? - - @description('Optional. The tag of the container image to be used by the Container App.') - containerImageTag: string? - - @description('Optional. The CPU reserved for the Container App. Defaults to 2.0') - containerCpu: string? - - @description('Optional. The Memory reserved for the Container App. Defaults to 4.0Gi') - containerMemory: string? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Entra ID Application resource configuration.') -type entraIdApplicationConfigurationType = { - @description('Optional. If the Entra ID Application for website authentication should be deployed or not.') - enabled: bool? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Web Server Farm resource configuration.') -type webServerFarmConfigurationType = { - @description('Optional. If the Web Server Farm resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Web Server Farm resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Web Server Farm resource.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Web Server Farm resource.') - tags: object? - - @description('Optional. The name of th SKU that will determine the tier, size and family for the Web Server Farm resource. This defaults to P1v3 to leverage availability zones.') - skuName: string? - - @description('Optional. Number of workers associated with the App Service Plan. This defaults to 3, to leverage availability zones.') - skuCapacity: int? -} - -@export() -@description('The type for the Multi-Agent Custom Automation Engine Web Site resource configuration.') -type webSiteConfigurationType = { - @description('Optional. If the Web Site resource should be deployed or not.') - enabled: bool? - - @description('Optional. The name of the Web Site resource.') - @maxLength(60) - name: string? - - @description('Optional. Location for the Web Site resource deployment.') - @metadata({ azd: { type: 'location' } }) - location: string? - - @description('Optional. The tags to set for the Web Site resource.') - tags: object? - - @description('Optional. The resource Id of the Web Site Environment where the Web Site should be created.') - environmentResourceId: string? - - @description('Optional. The name given to the Container App.') - containerName: string? - - @description('Optional. The container registry domain of the container image to be used by the Web Site. Default to `biabcontainerreg.azurecr.io`') - containerImageRegistryDomain: string? - - @description('Optional. The name of the container image to be used by the Web Site.') - containerImageName: string? - - @description('Optional. The tag of the container image to be used by the Web Site.') - containerImageTag: string? -} diff --git a/infra/main.parameters.json b/infra/main.parameters.json index 16b465617..c52f902ee 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -1,102 +1,24 @@ { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "aiModelDeployments": { - "value": [ - { - "name": "gpt", - "model": { - "name": "gpt-4o", - "version": "2024-08-06", - "format": "OpenAI" - }, - "sku": { - "name": "GlobalStandard", - "capacity": 140 - } - } - ] - }, - "environmentName": { - "value": "${AZURE_ENV_NAME}" - }, - "solutionLocation": { - "value": "${AZURE_LOCATION}" - }, - "aiDeploymentsLocation": { - "value": "${AZURE_ENV_OPENAI_LOCATION}" - }, - "modelDeploymentType": { - "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" - }, - "gptModelName": { - "value": "${AZURE_ENV_MODEL_NAME}" - }, - "gptModelVersion": { - "value": "${AZURE_ENV_MODEL_VERSION}" - }, - "gptModelCapacity": { - "value": "${AZURE_ENV_MODEL_CAPACITY}" - }, - "existingFoundryProjectResourceId": { - "value": "${AZURE_ENV_FOUNDRY_PROJECT_ID}" - }, - "imageTag": { - "value": "${AZURE_ENV_IMAGE_TAG}" - }, - "enableTelemetry": { - "value": "${AZURE_ENV_ENABLE_TELEMETRY}" - }, - "existingLogAnalyticsWorkspaceId": { - "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" - }, - "backendExists": { - "value": "${SERVICE_BACKEND_RESOURCE_EXISTS=false}" - }, - "backendDefinition": { - "value": { - "settings": [ - { - "name": "", - "value": "${VAR}", - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment." - }, - { - "name": "", - "value": "${VAR_S}", - "secret": true, - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment." - } - ] - } - }, - "frontendExists": { - "value": "${SERVICE_FRONTEND_RESOURCE_EXISTS=false}" - }, - "frontendDefinition": { - "value": { - "settings": [ - { - "name": "", - "value": "${VAR}", - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment." - }, - { - "name": "", - "value": "${VAR_S}", - "secret": true, - "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", - "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment." - } - ] - } - }, - "principalId": { - "value": "${AZURE_PRINCIPAL_ID}" - } + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "solutionName": { + "value": "${AZURE_ENV_NAME}" + }, + "location": { + "value": "${AZURE_LOCATION}" + }, + "azureAiServiceLocation": { + "value": "${AZURE_ENV_OPENAI_LOCATION}" + }, + "backendContainerImageTag": { + "value": "${AZURE_ENV_IMAGE_TAG}" + }, + "frontendContainerImageTag": { + "value": "${AZURE_ENV_IMAGE_TAG}" + }, + "enableTelemetry": { + "value": "${AZURE_ENV_ENABLE_TELEMETRY}" } + } } \ No newline at end of file diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json new file mode 100644 index 000000000..c4b7d5ddc --- /dev/null +++ b/infra/main.waf.parameters.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "solutionName": { + "value": "${AZURE_ENV_NAME}" + }, + "solutionLocation": { + "value": "${AZURE_LOCATION}" + }, + "location": { + "value": "${AZURE_LOCATION}" + }, + "azureAiServiceLocation": { + "value": "${AZURE_ENV_OPENAI_LOCATION}" + }, + "backendContainerImageTag": { + "value": "${AZURE_ENV_IMAGE_TAG}" + }, + "frontendContainerImageTag": { + "value": "${AZURE_ENV_IMAGE_TAG}" + }, + "enableTelemetry": { + "value": "${AZURE_ENV_ENABLE_TELEMETRY}" + }, + "enableMonitoring": { + "value": true + }, + "enablePrivateNetworking": { + "value": true + }, + "enableScalability": { + "value": true + }, + "virtualMachineAdminUsername": { + "value": "${AZURE_ENV_VM_ADMIN_USERNAME}" + }, + "virtualMachineAdminPassword": { + "value": "${AZURE_ENV_VM_ADMIN_PASSWORD}" + } + } +} \ No newline at end of file diff --git a/infra/modules/ai-services.bicep b/infra/modules/ai-services.bicep new file mode 100644 index 000000000..a3472bb07 --- /dev/null +++ b/infra/modules/ai-services.bicep @@ -0,0 +1,630 @@ +metadata name = 'Cognitive Services' +metadata description = 'This module deploys a Cognitive Service.' + +@description('Required. The name of Cognitive Services account.') +param name string + +@description('Required. Kind of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') +@allowed([ + 'AIServices' + 'AnomalyDetector' + 'CognitiveServices' + 'ComputerVision' + 'ContentModerator' + 'ContentSafety' + 'ConversationalLanguageUnderstanding' + 'CustomVision.Prediction' + 'CustomVision.Training' + 'Face' + 'FormRecognizer' + 'HealthInsights' + 'ImmersiveReader' + 'Internal.AllInOne' + 'LUIS' + 'LUIS.Authoring' + 'LanguageAuthoring' + 'MetricsAdvisor' + 'OpenAI' + 'Personalizer' + 'QnAMaker.v2' + 'SpeechServices' + 'TextAnalytics' + 'TextTranslation' +]) +param kind string + +@description('Required. The name of the AI Foundry project to create.') +param projectName string + +@description('Required. The description of the AI Foundry project to create.') +param projectDescription string + +@description('Optional. SKU of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') +@allowed([ + 'C2' + 'C3' + 'C4' + 'F0' + 'F1' + 'S' + 'S0' + 'S1' + 'S10' + 'S2' + 'S3' + 'S4' + 'S5' + 'S6' + 'S7' + 'S8' + 'S9' +]) +param sku string = 'S0' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingFullType[]? + +@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkAcls are not set.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string? + +@description('Conditional. Subdomain name used for token-based authentication. Required if \'networkAcls\' or \'privateEndpoints\' are set.') +param customSubDomainName string? + +@description('Optional. A collection of rules governing the accessibility from specific network locations.') +param networkAcls object? + +@description('Optional. The network injection subnet resource Id for the Cognitive Services account. This allows to use the AI Services account with a virtual network.') +param networkInjectionSubnetResourceId string? + +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointSingleServiceType[]? + +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The lock settings of the service.') +param lock lockType? + +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType[]? + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. List of allowed FQDN.') +param allowedFqdnList array? + +@description('Optional. The API properties for special APIs.') +param apiProperties object? + +@description('Optional. Allow only Azure AD authentication. Should be enabled for security reasons.') +param disableLocalAuth bool = true + +import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The customer managed key definition.') +param customerManagedKey customerManagedKeyType? + +@description('Optional. The flag to enable dynamic throttling.') +param dynamicThrottlingEnabled bool = false + +@secure() +@description('Optional. Resource migration token.') +param migrationToken string? + +@description('Optional. Restore a soft-deleted cognitive service at deployment time. Will fail if no such soft-deleted resource exists.') +param restore bool = false + +@description('Optional. Restrict outbound network access.') +param restrictOutboundNetworkAccess bool = true + +@description('Optional. The storage accounts for this resource.') +param userOwnedStorage array? + +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentityAllType? + +@description('Optional. Array of deployments about cognitive service accounts to create.') +param deployments deploymentType[]? + +var enableReferencedModulesTelemetry = false + +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), + {}, + (cur, next) => union(cur, next) +) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } +var identity = !empty(managedIdentities) + ? { + type: (managedIdentities.?systemAssigned ?? false) + ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null + +var builtInRoleNames = { + 'Cognitive Services Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + ) + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + ) + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5c4089e1-6d96-4d2f-b296-c1bc7137275f' + ) + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '88424f51-ebe7-446f-bc41-7fa16989e96c' + ) + 'Cognitive Services Custom Vision Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '93586559-c37d-4a6b-ba08-b9f0940c2d73' + ) + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + ) + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b59867f0-fa02-499b-be73-45a86b5b3e1c' + ) + 'Cognitive Services Face Recognizer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9894cab4-e18a-44aa-828b-cb588cd6f2d7' + ) + 'Cognitive Services Immersive Reader User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b2de6794-95db-4659-8781-7e080d3f2b9d' + ) + 'Cognitive Services Language Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f07febfe-79bc-46b1-8b37-790e26e6e498' + ) + 'Cognitive Services Language Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7628b7b8-a8b2-4cdc-b46f-e9b35248918e' + ) + 'Cognitive Services Language Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8' + ) + 'Cognitive Services LUIS Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f72c8140-2111-481c-87ff-72b910f6e3f8' + ) + 'Cognitive Services LUIS Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18e81cdc-4e98-4e29-a639-e7d10c5a6226' + ) + 'Cognitive Services LUIS Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '6322a993-d5c9-4bed-b113-e49bbea25b27' + ) + 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'cb43c632-a144-4ec5-977c-e80c4affc34a' + ) + 'Cognitive Services Metrics Advisor User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3b20f47b-3825-43cb-8114-4bd2201156a8' + ) + 'Cognitive Services OpenAI Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a001fd3d-188f-4b5d-821b-7da978bf7442' + ) + 'Cognitive Services OpenAI User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + ) + 'Cognitive Services QnA Maker Editor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f4cc2bf9-21be-47a1-bdf1-5c5804381025' + ) + 'Cognitive Services QnA Maker Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '466ccd10-b268-4a11-b098-b4849f024126' + ) + 'Cognitive Services Speech Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0e75ca1e-0464-4b4d-8b93-68208a576181' + ) + 'Cognitive Services Speech User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2dc8367-1007-4938-bd23-fe263f013447' + ) + 'Cognitive Services User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a97b65f3-24c7-4388-baec-2e87135dc908' + ) + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) +} + +var formattedRoleAssignments = [ + for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { + roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( + roleAssignment.roleDefinitionIdOrName, + '/providers/Microsoft.Authorization/roleDefinitions/' + ) + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) + }) +] + +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2024-11-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split(customerManagedKey.?keyVaultResourceId!, '/')) + scope: resourceGroup( + split(customerManagedKey.?keyVaultResourceId!, '/')[2], + split(customerManagedKey.?keyVaultResourceId!, '/')[4] + ) + + resource cMKKey 'keys@2024-11-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName! + } +} + +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId!, '/')) + scope: resourceGroup( + split(customerManagedKey.?userAssignedIdentityResourceId!, '/')[2], + split(customerManagedKey.?userAssignedIdentityResourceId!, '/')[4] + ) +} + +resource cognitiveService 'Microsoft.CognitiveServices/accounts@2025-06-01' = { + name: name + kind: kind + identity: identity + location: location + tags: tags + sku: { + name: sku + } + properties: { + customSubDomainName: customSubDomainName + allowProjectManagement: true + networkAcls: !empty(networkAcls ?? {}) + ? { + defaultAction: networkAcls.?defaultAction + virtualNetworkRules: networkAcls.?virtualNetworkRules ?? [] + ipRules: networkAcls.?ipRules ?? [] + } + : null + publicNetworkAccess: publicNetworkAccess != null + ? publicNetworkAccess + : (!empty(networkAcls) ? 'Enabled' : 'Disabled') + allowedFqdnList: allowedFqdnList + apiProperties: apiProperties + disableLocalAuth: disableLocalAuth + #disable-next-line BCP036 + networkInjections: networkInjectionSubnetResourceId != null + ? [ + { + scenario: 'agent' + subnetArmId: networkInjectionSubnetResourceId + useMicrosoftManagedNetwork: false + } + ] + : null + // true is not supported today + encryption: !empty(customerManagedKey) + ? { + keySource: 'Microsoft.KeyVault' + keyVaultProperties: { + identityClientId: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') + ? cMKUserAssignedIdentity!.properties.clientId + : null + keyVaultUri: cMKKeyVault!.properties.vaultUri + keyName: customerManagedKey!.keyName + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') + ? customerManagedKey!.?keyVersion + : last(split(cMKKeyVault::cMKKey!.properties.keyUriWithVersion, '/')) + } + } + : null + migrationToken: migrationToken + restore: restore + restrictOutboundNetworkAccess: restrictOutboundNetworkAccess + userOwnedStorage: userOwnedStorage + dynamicThrottlingEnabled: dynamicThrottlingEnabled + } +} + +@batchSize(1) +resource cognitiveService_deployments 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = [ + for (deployment, index) in (deployments ?? []): { + parent: cognitiveService + name: deployment.?name ?? '${name}-deployments' + properties: { + model: deployment.model + raiPolicyName: deployment.?raiPolicyName + versionUpgradeOption: deployment.?versionUpgradeOption + } + sku: deployment.?sku ?? { + name: sku + capacity: sku.?capacity + tier: sku.?tier + size: sku.?size + family: sku.?family + } + } +] + +resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' = { + parent: cognitiveService + name: projectName + tags: tags + location: location + identity: { + type: 'SystemAssigned' + } + properties: { + description: projectDescription + displayName: projectName + } +} + +resource cognitiveService_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' + ? 'Cannot delete resource or child resources.' + : 'Cannot delete or modify the resource or child resources.' + } + scope: cognitiveService +} + +#disable-next-line use-recent-api-versions +resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: cognitiveService + } +] + +module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: take('${uniqueString(deployment().name, location)}-cognitiveService-PrivateEndpoint-${index}', 64) + scope: resourceGroup( + split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[2], + split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[4] + ) + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + privateLinkServiceConnections: privateEndpoint.?isManualConnection != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + } + } + ] + : null + manualPrivateLinkServiceConnections: privateEndpoint.?isManualConnection == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: enableReferencedModulesTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } + } +] + +resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (formattedRoleAssignments ?? []): { + name: roleAssignment.?name ?? guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) + properties: { + roleDefinitionId: roleAssignment.roleDefinitionId + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: cognitiveService + } +] + +@description('The name of the cognitive services account.') +output name string = cognitiveService.name + +@description('The resource ID of the cognitive services account.') +output resourceId string = cognitiveService.id + +@description('The resource ID of AI project.') +output aiProjectResourceId string = aiFoundryProject.id + +@description('The endpoint to connect to the AI Project API') +output aiProjectApiEndpoint string = aiFoundryProject.properties.endpoints['AI Foundry API'] + +@description('The resource group the cognitive services account was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The service endpoint of the cognitive services account.') +output endpoint string = cognitiveService.properties.endpoint + +@description('All endpoints available for the cognitive services account, types depends on the cognitive service kind.') +output endpoints endpointType = cognitiveService.properties.endpoints + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string? = cognitiveService.?identity.?principalId + +@description('The location the resource was deployed into.') +output location string = cognitiveService.location + +@description('The private endpoints of the congitive services account.') +output privateEndpoints privateEndpointOutputType[] = [ + for (pe, index) in (privateEndpoints ?? []): { + name: cognitiveService_privateEndpoints[index].outputs.name + resourceId: cognitiveService_privateEndpoints[index].outputs.resourceId + groupId: cognitiveService_privateEndpoints[index].outputs.?groupId! + customDnsConfigs: cognitiveService_privateEndpoints[index].outputs.customDnsConfigs + networkInterfaceResourceIds: cognitiveService_privateEndpoints[index].outputs.networkInterfaceResourceIds + } +] + +// ================ // +// Definitions // +// ================ // + +@export() +@description('The type for the private endpoint output.') +type privateEndpointOutputType = { + @description('The name of the private endpoint.') + name: string + + @description('The resource ID of the private endpoint.') + resourceId: string + + @description('The group Id for the private endpoint Group.') + groupId: string? + + @description('The custom DNS configurations of the private endpoint.') + customDnsConfigs: { + @description('FQDN that resolves to private endpoint IP address.') + fqdn: string? + + @description('A list of private IP addresses of the private endpoint.') + ipAddresses: string[] + }[] + + @description('The IDs of the network interfaces associated with the private endpoint.') + networkInterfaceResourceIds: string[] +} + +@export() +@description('The type for a cognitive services account deployment.') +type deploymentType = { + @description('Optional. Specify the name of cognitive service account deployment.') + name: string? + + @description('Required. Properties of Cognitive Services account deployment model.') + model: { + @description('Required. The name of Cognitive Services account deployment model.') + name: string + + @description('Required. The format of Cognitive Services account deployment model.') + format: string + + @description('Required. The version of Cognitive Services account deployment model.') + version: string + } + + @description('Optional. The resource model definition representing SKU.') + sku: { + @description('Required. The name of the resource model definition representing SKU.') + name: string + + @description('Optional. The capacity of the resource model definition representing SKU.') + capacity: int? + + @description('Optional. The tier of the resource model definition representing SKU.') + tier: string? + + @description('Optional. The size of the resource model definition representing SKU.') + size: string? + + @description('Optional. The family of the resource model definition representing SKU.') + family: string? + }? + + @description('Optional. The name of RAI policy.') + raiPolicyName: string? + + @description('Optional. The version upgrade option.') + versionUpgradeOption: string? +} + +@export() +@description('The type for a cognitive services account endpoint.') +type endpointType = { + @description('Type of the endpoint.') + name: string? + @description('The endpoint URI.') + endpoint: string? +} + +@export() +@description('The type of the secrets exported to the provided Key Vault.') +type secretsExportConfigurationType = { + @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') + keyVaultResourceId: string + + @description('Optional. The name for the accessKey1 secret to create.') + accessKey1Name: string? + + @description('Optional. The name for the accessKey2 secret to create.') + accessKey2Name: string? +} diff --git a/infra/modules/web-sites.bicep b/infra/modules/web-sites.bicep new file mode 100644 index 000000000..520f33669 --- /dev/null +++ b/infra/modules/web-sites.bicep @@ -0,0 +1,368 @@ +@description('Required. Name of the site.') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Required. Type of site to deploy.') +@allowed([ + 'functionapp' // function app windows os + 'functionapp,linux' // function app linux os + 'functionapp,workflowapp' // logic app workflow + 'functionapp,workflowapp,linux' // logic app docker container + 'functionapp,linux,container' // function app linux container + 'functionapp,linux,container,azurecontainerapps' // function app linux container azure container apps + 'app,linux' // linux web app + 'app' // windows web app + 'linux,api' // linux api app + 'api' // windows api app + 'app,linux,container' // linux container app + 'app,container,windows' // windows container app +]) +param kind string + +@description('Required. The resource ID of the app service plan to use for the site.') +param serverFarmResourceId string + +@description('Optional. Azure Resource Manager ID of the customers selected Managed Environment on which to host this app.') +param managedEnvironmentId string? + +@description('Optional. Configures a site to accept only HTTPS requests. Issues redirect for HTTP requests.') +param httpsOnly bool = true + +@description('Optional. If client affinity is enabled.') +param clientAffinityEnabled bool = true + +@description('Optional. The resource ID of the app service environment to use for this resource.') +param appServiceEnvironmentResourceId string? + +import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentityAllType? + +@description('Optional. The resource ID of the assigned identity to be used to access a key vault with.') +param keyVaultAccessIdentityResourceId string? + +@description('Optional. Checks if Customer provided storage account is required.') +param storageAccountRequired bool = false + +@description('Optional. Azure Resource Manager ID of the Virtual network and subnet to be joined by Regional VNET Integration. This must be of the form /subscriptions/{subscriptionName}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{subnetName}.') +param virtualNetworkSubnetId string? + +@description('Optional. To enable accessing content over virtual network.') +param vnetContentShareEnabled bool = false + +@description('Optional. To enable pulling image over Virtual Network.') +param vnetImagePullEnabled bool = false + +@description('Optional. Virtual Network Route All enabled. This causes all outbound traffic to have Virtual Network Security Groups and User Defined Routes applied.') +param vnetRouteAllEnabled bool = false + +@description('Optional. Stop SCM (KUDU) site when the app is stopped.') +param scmSiteAlsoStopped bool = false + +@description('Optional. The site config object. The defaults are set to the following values: alwaysOn: true, minTlsVersion: \'1.2\', ftpsState: \'FtpsOnly\'.') +param siteConfig resourceInput<'Microsoft.Web/sites@2024-04-01'>.properties.siteConfig = { + alwaysOn: true + minTlsVersion: '1.2' + ftpsState: 'FtpsOnly' +} + +@description('Optional. The web site config.') +param configs appSettingsConfigType[]? + +@description('Optional. The Function App configuration object.') +param functionAppConfig resourceInput<'Microsoft.Web/sites@2024-04-01'>.properties.functionAppConfig? + +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointSingleServiceType[]? + +@description('Optional. Tags of the resource.') +param tags object? + +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingFullType[]? + +@description('Optional. To enable client certificate authentication (TLS mutual authentication).') +param clientCertEnabled bool = false + +@description('Optional. Client certificate authentication comma-separated exclusion paths.') +param clientCertExclusionPaths string? + +@description(''' +Optional. This composes with ClientCertEnabled setting. +- ClientCertEnabled=false means ClientCert is ignored. +- ClientCertEnabled=true and ClientCertMode=Required means ClientCert is required. +- ClientCertEnabled=true and ClientCertMode=Optional means ClientCert is optional or accepted. +''') +@allowed([ + 'Optional' + 'OptionalInteractiveUser' + 'Required' +]) +param clientCertMode string = 'Optional' + +@description('Optional. If specified during app creation, the app is cloned from a source app.') +param cloningInfo resourceInput<'Microsoft.Web/sites@2024-04-01'>.properties.cloningInfo? + +@description('Optional. Size of the function container.') +param containerSize int? + +@description('Optional. Maximum allowed daily memory-time quota (applicable on dynamic apps only).') +param dailyMemoryTimeQuota int? + +@description('Optional. Setting this value to false disables the app (takes the app offline).') +param enabled bool = true + +@description('Optional. Hostname SSL states are used to manage the SSL bindings for app\'s hostnames.') +param hostNameSslStates resourceInput<'Microsoft.Web/sites@2024-04-01'>.properties.hostNameSslStates? + +@description('Optional. Hyper-V sandbox.') +param hyperV bool = false + +@description('Optional. Site redundancy mode.') +@allowed([ + 'ActiveActive' + 'Failover' + 'GeoRedundant' + 'Manual' + 'None' +]) +param redundancyMode string = 'None' + +@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string? + +@description('Optional. End to End Encryption Setting.') +param e2eEncryptionEnabled bool? + +@description('Optional. Property to configure various DNS related settings for a site.') +param dnsConfiguration resourceInput<'Microsoft.Web/sites@2024-04-01'>.properties.dnsConfiguration? + +@description('Optional. Specifies the scope of uniqueness for the default hostname during resource creation.') +@allowed([ + 'NoReuse' + 'ResourceGroupReuse' + 'SubscriptionReuse' + 'TenantReuse' +]) +param autoGeneratedDomainNameLabelScope string? + +var formattedUserAssignedIdentities = reduce( + map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), + {}, + (cur, next) => union(cur, next) +) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) + ? { + type: (managedIdentities.?systemAssigned ?? false) + ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') + : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : 'None') + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null + } + : null + +resource app 'Microsoft.Web/sites@2024-04-01' = { + name: name + location: location + kind: kind + tags: tags + identity: identity + properties: { + managedEnvironmentId: !empty(managedEnvironmentId) ? managedEnvironmentId : null + serverFarmId: serverFarmResourceId + clientAffinityEnabled: clientAffinityEnabled + httpsOnly: httpsOnly + hostingEnvironmentProfile: !empty(appServiceEnvironmentResourceId) + ? { + id: appServiceEnvironmentResourceId + } + : null + storageAccountRequired: storageAccountRequired + keyVaultReferenceIdentity: keyVaultAccessIdentityResourceId + virtualNetworkSubnetId: virtualNetworkSubnetId + siteConfig: siteConfig + functionAppConfig: functionAppConfig + clientCertEnabled: clientCertEnabled + clientCertExclusionPaths: clientCertExclusionPaths + clientCertMode: clientCertMode + cloningInfo: cloningInfo + containerSize: containerSize + dailyMemoryTimeQuota: dailyMemoryTimeQuota + enabled: enabled + hostNameSslStates: hostNameSslStates + hyperV: hyperV + redundancyMode: redundancyMode + publicNetworkAccess: !empty(publicNetworkAccess) + ? any(publicNetworkAccess) + : (!empty(privateEndpoints) ? 'Disabled' : 'Enabled') + vnetContentShareEnabled: vnetContentShareEnabled + vnetImagePullEnabled: vnetImagePullEnabled + vnetRouteAllEnabled: vnetRouteAllEnabled + scmSiteAlsoStopped: scmSiteAlsoStopped + endToEndEncryptionEnabled: e2eEncryptionEnabled + dnsConfiguration: dnsConfiguration + autoGeneratedDomainNameLabelScope: autoGeneratedDomainNameLabelScope + } +} + +module app_config 'web-sites.config.bicep' = [ + for (config, index) in (configs ?? []): { + name: '${uniqueString(deployment().name, location)}-Site-Config-${index}' + params: { + appName: app.name + name: config.name + applicationInsightResourceId: config.?applicationInsightResourceId + storageAccountResourceId: config.?storageAccountResourceId + storageAccountUseIdentityAuthentication: config.?storageAccountUseIdentityAuthentication + properties: config.?properties + currentAppSettings: config.?retainCurrentAppSettings ?? true && config.name == 'appsettings' + ? list('${app.id}/config/appsettings', '2023-12-01').properties + : {} + } + } +] + +#disable-next-line use-recent-api-versions +resource app_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: app + } +] + +module app_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-app-PrivateEndpoint-${index}' + scope: resourceGroup( + split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[2], + split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[4] + ) + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' + privateLinkServiceConnections: privateEndpoint.?isManualConnection != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' + properties: { + privateLinkServiceId: app.id + groupIds: [ + privateEndpoint.?service ?? 'sites' + ] + } + } + ] + : null + manualPrivateLinkServiceConnections: privateEndpoint.?isManualConnection == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(app.id, '/'))}-${privateEndpoint.?service ?? 'sites'}-${index}' + properties: { + privateLinkServiceId: app.id + groupIds: [ + privateEndpoint.?service ?? 'sites' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: false //As per https://azure.github.io/Azure-Verified-Modules/spec/BCPFR7/ + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? null + privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } + } +] + +@description('The name of the site.') +output name string = app.name + +@description('The resource ID of the site.') +output resourceId string = app.id + +@description('The resource group the site was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string? = app.?identity.?principalId + +@description('The location the resource was deployed into.') +output location string = app.location + +@description('Default hostname of the app.') +output defaultHostname string = app.properties.defaultHostName + +@description('Unique identifier that verifies the custom domains assigned to the app. Customer will add this ID to a txt record for verification.') +output customDomainVerificationId string = app.properties.customDomainVerificationId + +@description('The outbound IP addresses of the app.') +output outboundIpAddresses string = app.properties.outboundIpAddresses + +// ================ // +// Definitions // +// ================ // +@export() +@description('The type of an app settings configuration.') +type appSettingsConfigType = { + @description('Required. The type of config.') + name: 'appsettings' + + @description('Optional. If the provided storage account requires Identity based authentication (\'allowSharedKeyAccess\' is set to false). When set to true, the minimum role assignment required for the App Service Managed Identity to the storage account is \'Storage Blob Data Owner\'.') + storageAccountUseIdentityAuthentication: bool? + + @description('Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions.') + storageAccountResourceId: string? + + @description('Optional. Resource ID of the application insight to leverage for this resource.') + applicationInsightResourceId: string? + + @description('Optional. The retain the current app settings. Defaults to true.') + retainCurrentAppSettings: bool? + + @description('Optional. The app settings key-value pairs except for AzureWebJobsStorage, AzureWebJobsDashboard, APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING.') + properties: { + @description('Required. An app settings key-value pair.') + *: string + }? +} diff --git a/infra/modules/web-sites.config.bicep b/infra/modules/web-sites.config.bicep new file mode 100644 index 000000000..130a9806b --- /dev/null +++ b/infra/modules/web-sites.config.bicep @@ -0,0 +1,91 @@ +metadata name = 'Site App Settings' +metadata description = 'This module deploys a Site App Setting.' + +@description('Conditional. The name of the parent site resource. Required if the template is used in a standalone deployment.') +param appName string + +@description('Required. The name of the config.') +@allowed([ + 'appsettings' + 'authsettings' + 'authsettingsV2' + 'azurestorageaccounts' + 'backup' + 'connectionstrings' + 'logs' + 'metadata' + 'pushsettings' + 'slotConfigNames' + 'web' +]) +param name string + +@description('Optional. The properties of the config. Note: This parameter is highly dependent on the config type, defined by its name.') +param properties object = {} + +// Parameters only relevant for the config type 'appsettings' +@description('Optional. If the provided storage account requires Identity based authentication (\'allowSharedKeyAccess\' is set to false). When set to true, the minimum role assignment required for the App Service Managed Identity to the storage account is \'Storage Blob Data Owner\'.') +param storageAccountUseIdentityAuthentication bool = false + +@description('Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions.') +param storageAccountResourceId string? + +@description('Optional. Resource ID of the application insight to leverage for this resource.') +param applicationInsightResourceId string? + +@description('Optional. The current app settings.') +param currentAppSettings { + @description('Required. The key-values pairs of the current app settings.') + *: string +} = {} + +var azureWebJobsValues = !empty(storageAccountResourceId) && !storageAccountUseIdentityAuthentication + ? { + AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount!.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}' + } + : !empty(storageAccountResourceId) && storageAccountUseIdentityAuthentication + ? { + AzureWebJobsStorage__accountName: storageAccount.name + AzureWebJobsStorage__blobServiceUri: storageAccount!.properties.primaryEndpoints.blob + AzureWebJobsStorage__queueServiceUri: storageAccount!.properties.primaryEndpoints.queue + AzureWebJobsStorage__tableServiceUri: storageAccount!.properties.primaryEndpoints.table + } + : {} + +var appInsightsValues = !empty(applicationInsightResourceId) + ? { + APPLICATIONINSIGHTS_CONNECTION_STRING: applicationInsights!.properties.ConnectionString + } + : {} + +var expandedProperties = union(currentAppSettings, properties, azureWebJobsValues, appInsightsValues) + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(applicationInsightResourceId)) { + name: last(split(applicationInsightResourceId!, '/')) + scope: resourceGroup(split(applicationInsightResourceId!, '/')[2], split(applicationInsightResourceId!, '/')[4]) +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2024-01-01' existing = if (!empty(storageAccountResourceId)) { + name: last(split(storageAccountResourceId!, '/')) + scope: resourceGroup(split(storageAccountResourceId!, '/')[2], split(storageAccountResourceId!, '/')[4]) +} + +resource app 'Microsoft.Web/sites@2023-12-01' existing = { + name: appName +} + +resource config 'Microsoft.Web/sites/config@2024-04-01' = { + parent: app + #disable-next-line BCP225 + name: name + properties: expandedProperties +} + +@description('The name of the site config.') +output name string = config.name + +@description('The resource ID of the site config.') +output resourceId string = config.id + +@description('The resource group the site config was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/infra/old/deploy_ai_foundry.bicep b/infra/old/00-older/deploy_ai_foundry.bicep similarity index 100% rename from infra/old/deploy_ai_foundry.bicep rename to infra/old/00-older/deploy_ai_foundry.bicep diff --git a/infra/old/deploy_keyvault.bicep b/infra/old/00-older/deploy_keyvault.bicep similarity index 100% rename from infra/old/deploy_keyvault.bicep rename to infra/old/00-older/deploy_keyvault.bicep diff --git a/infra/old/deploy_managed_identity.bicep b/infra/old/00-older/deploy_managed_identity.bicep similarity index 100% rename from infra/old/deploy_managed_identity.bicep rename to infra/old/00-older/deploy_managed_identity.bicep diff --git a/infra/old/macae-continer-oc.json b/infra/old/00-older/macae-continer-oc.json similarity index 100% rename from infra/old/macae-continer-oc.json rename to infra/old/00-older/macae-continer-oc.json diff --git a/infra/old/macae-continer.json b/infra/old/00-older/macae-continer.json similarity index 100% rename from infra/old/macae-continer.json rename to infra/old/00-older/macae-continer.json diff --git a/infra/old/macae-dev.bicep b/infra/old/00-older/macae-dev.bicep similarity index 100% rename from infra/old/macae-dev.bicep rename to infra/old/00-older/macae-dev.bicep diff --git a/infra/old/macae-large.bicepparam b/infra/old/00-older/macae-large.bicepparam similarity index 100% rename from infra/old/macae-large.bicepparam rename to infra/old/00-older/macae-large.bicepparam diff --git a/infra/old/macae-mini.bicepparam b/infra/old/00-older/macae-mini.bicepparam similarity index 100% rename from infra/old/macae-mini.bicepparam rename to infra/old/00-older/macae-mini.bicepparam diff --git a/infra/old/macae.bicep b/infra/old/00-older/macae.bicep similarity index 100% rename from infra/old/macae.bicep rename to infra/old/00-older/macae.bicep diff --git a/infra/old/main.bicep b/infra/old/00-older/main.bicep similarity index 100% rename from infra/old/main.bicep rename to infra/old/00-older/main.bicep diff --git a/infra/old/main2.bicep b/infra/old/00-older/main2.bicep similarity index 100% rename from infra/old/main2.bicep rename to infra/old/00-older/main2.bicep diff --git a/infra/old/resources.bicep b/infra/old/00-older/resources.bicep similarity index 100% rename from infra/old/resources.bicep rename to infra/old/00-older/resources.bicep diff --git a/infra/abbreviations.json b/infra/old/08-2025/abbreviations.json similarity index 100% rename from infra/abbreviations.json rename to infra/old/08-2025/abbreviations.json diff --git a/infra/bicepconfig.json b/infra/old/08-2025/bicepconfig.json similarity index 100% rename from infra/bicepconfig.json rename to infra/old/08-2025/bicepconfig.json diff --git a/infra/old/08-2025/main.bicep b/infra/old/08-2025/main.bicep new file mode 100644 index 000000000..8ee54772d --- /dev/null +++ b/infra/old/08-2025/main.bicep @@ -0,0 +1,1720 @@ +metadata name = 'Multi-Agent Custom Automation Engine' +metadata description = 'This module contains the resources required to deploy the Multi-Agent Custom Automation Engine solution accelerator for both Sandbox environments and WAF aligned environments.' + +@description('Set to true if you want to deploy WAF-aligned infrastructure.') +param useWafAlignedArchitecture bool + +@description('Use this parameter to use an existing AI project resource ID') +param existingFoundryProjectResourceId string = '' + +@description('Required. Name of the environment to deploy the solution into.') +param environmentName string + +@description('Required. Location for all Resources except AI Foundry.') +param solutionLocation string = resourceGroup().location + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +param existingLogAnalyticsWorkspaceId string = '' + +// Restricting deployment to only supported Azure OpenAI regions validated with GPT-4o model +@metadata({ + azd : { + type: 'location' + usageName : [ + 'OpenAI.GlobalStandard.gpt-4o, 150' + ] + } +}) +@allowed(['australiaeast', 'eastus2', 'francecentral', 'japaneast', 'norwayeast', 'swedencentral', 'uksouth', 'westus']) +@description('Azure OpenAI Location') +param aiDeploymentsLocation string + +@minLength(1) +@description('Name of the GPT model to deploy:') +param gptModelName string = 'gpt-4o' + +param gptModelVersion string = '2024-08-06' + +@minLength(1) +@description('GPT model deployment type:') +param modelDeploymentType string = 'GlobalStandard' + +@description('Optional. AI model deployment token capacity.') +param gptModelCapacity int = 150 + +@description('Set the image tag for the container images used in the solution. Default is "latest".') +param imageTag string = 'latest' + +param solutionPrefix string = 'macae-${padLeft(take(toLower(uniqueString(subscription().id, environmentName, resourceGroup().location, resourceGroup().name)), 12), 12, '0')}' + +@description('Optional. The tags to apply to all deployed Azure resources.') +param tags object = { + app: solutionPrefix + location: solutionLocation +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource.') +param logAnalyticsWorkspaceConfiguration logAnalyticsWorkspaceConfigurationType = { + enabled: true + name: 'log-${solutionPrefix}' + location: solutionLocation + sku: 'PerGB2018' + tags: tags + dataRetentionInDays: useWafAlignedArchitecture ? 365 : 30 + existingWorkspaceResourceId: existingLogAnalyticsWorkspaceId +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Application Insights resource.') +param applicationInsightsConfiguration applicationInsightsConfigurationType = { + enabled: true + name: 'appi-${solutionPrefix}' + location: solutionLocation + tags: tags + retentionInDays: useWafAlignedArchitecture ? 365 : 30 +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Managed Identity resource.') +param userAssignedManagedIdentityConfiguration userAssignedManagedIdentityType = { + enabled: true + name: 'id-${solutionPrefix}' + location: solutionLocation + tags: tags +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the backend subnet.') +param networkSecurityGroupBackendConfiguration networkSecurityGroupConfigurationType = { + enabled: true + name: 'nsg-backend-${solutionPrefix}' + location: solutionLocation + tags: tags + securityRules: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the containers subnet.') +param networkSecurityGroupContainersConfiguration networkSecurityGroupConfigurationType = { + enabled: true + name: 'nsg-containers-${solutionPrefix}' + location: solutionLocation + tags: tags + securityRules: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the Bastion subnet.') +param networkSecurityGroupBastionConfiguration networkSecurityGroupConfigurationType = { + enabled: true + name: 'nsg-bastion-${solutionPrefix}' + location: solutionLocation + tags: tags + securityRules: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine Network Security Group resource for the administration subnet.') +param networkSecurityGroupAdministrationConfiguration networkSecurityGroupConfigurationType = { + enabled: true + name: 'nsg-administration-${solutionPrefix}' + location: solutionLocation + tags: tags + securityRules: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine virtual network resource.') +param virtualNetworkConfiguration virtualNetworkConfigurationType = { + enabled: useWafAlignedArchitecture ? true : false + name: 'vnet-${solutionPrefix}' + location: solutionLocation + tags: tags + addressPrefixes: null //Default value set on module configuration + subnets: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the Multi-Agent Custom Automation Engine bastion resource.') +param bastionConfiguration bastionConfigurationType = { + enabled: true + name: 'bas-${solutionPrefix}' + location: solutionLocation + tags: tags + sku: 'Standard' + virtualNetworkResourceId: null //Default value set on module configuration + publicIpResourceName: 'pip-bas${solutionPrefix}' +} + +@description('Optional. Configuration for the Windows virtual machine.') +param virtualMachineConfiguration virtualMachineConfigurationType = { + enabled: true + name: 'vm${solutionPrefix}' + location: solutionLocation + tags: tags + adminUsername: 'adminuser' + adminPassword: useWafAlignedArchitecture? 'P@ssw0rd1234' : guid(solutionPrefix, subscription().subscriptionId) + vmSize: 'Standard_D2s_v3' + subnetResourceId: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the AI Foundry AI Services resource.') +param aiFoundryAiServicesConfiguration aiServicesConfigurationType = { + enabled: true + name: 'aisa-${solutionPrefix}' + location: aiDeploymentsLocation + sku: 'S0' + deployments: null //Default value set on module configuration + subnetResourceId: null //Default value set on module configuration + modelCapacity: gptModelCapacity +} + +@description('Optional. The configuration to apply for the AI Foundry AI Project resource.') +param aiFoundryAiProjectConfiguration aiProjectConfigurationType = { + enabled: true + name: 'aifp-${solutionPrefix}' + location: aiDeploymentsLocation + sku: 'Basic' + tags: tags +} + +@description('Optional. The configuration to apply for the Cosmos DB Account resource.') +param cosmosDbAccountConfiguration cosmosDbAccountConfigurationType = { + enabled: true + name: 'cosmos-${solutionPrefix}' + location: solutionLocation + tags: tags + subnetResourceId: null //Default value set on module configuration + sqlDatabases: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the Container App Environment resource.') +param containerAppEnvironmentConfiguration containerAppEnvironmentConfigurationType = { + enabled: true + name: 'cae-${solutionPrefix}' + location: solutionLocation + tags: tags + subnetResourceId: null //Default value set on module configuration +} + +@description('Optional. The configuration to apply for the Container App resource.') +param containerAppConfiguration containerAppConfigurationType = { + enabled: true + name: 'ca-${solutionPrefix}' + location: solutionLocation + tags: tags + environmentResourceId: null //Default value set on module configuration + concurrentRequests: '100' + containerCpu: '2.0' + containerMemory: '4.0Gi' + containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' + containerImageName: 'macaebackend' + containerImageTag: imageTag + containerName: 'backend' + ingressTargetPort: 8000 + maxReplicas: 1 + minReplicas: 1 +} + +@description('Optional. The configuration to apply for the Web Server Farm resource.') +param webServerFarmConfiguration webServerFarmConfigurationType = { + enabled: true + name: 'asp-${solutionPrefix}' + location: solutionLocation + skuName: useWafAlignedArchitecture? 'P1v3' : 'B2' + skuCapacity: useWafAlignedArchitecture ? 3 : 1 + tags: tags +} + +@description('Optional. The configuration to apply for the Web Server Farm resource.') +param webSiteConfiguration webSiteConfigurationType = { + enabled: true + name: 'app-${solutionPrefix}' + location: solutionLocation + containerImageRegistryDomain: 'biabcontainerreg.azurecr.io' + containerImageName: 'macaefrontend' + containerImageTag: imageTag + containerName: 'backend' + tags: tags + environmentResourceId: null //Default value set on module configuration +} + +// ========== Resource Group Tag ========== // +resource resourceGroupTags 'Microsoft.Resources/tags@2021-04-01' = { + name: 'default' + properties: { + tags: { + ...tags + TemplateName: 'Macae' + } + } +} + +// ========== Log Analytics Workspace ========== // +// WAF best practices for Log Analytics: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-log-analytics +// Log Analytics configuration defaults +var logAnalyticsWorkspaceEnabled = logAnalyticsWorkspaceConfiguration.?enabled ?? true +var logAnalyticsWorkspaceResourceName = logAnalyticsWorkspaceConfiguration.?name ?? 'log-${solutionPrefix}' +var existingWorkspaceResourceId = logAnalyticsWorkspaceConfiguration.?existingWorkspaceResourceId ?? '' +var useExistingWorkspace = existingWorkspaceResourceId != '' + +module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.11.2' = if (logAnalyticsWorkspaceEnabled && !useExistingWorkspace) { + name: take('avm.res.operational-insights.workspace.${logAnalyticsWorkspaceResourceName}', 64) + params: { + name: logAnalyticsWorkspaceResourceName + tags: logAnalyticsWorkspaceConfiguration.?tags ?? tags + location: logAnalyticsWorkspaceConfiguration.?location ?? solutionLocation + enableTelemetry: enableTelemetry + skuName: logAnalyticsWorkspaceConfiguration.?sku ?? 'PerGB2018' + dataRetention: logAnalyticsWorkspaceConfiguration.?dataRetentionInDays ?? 365 + diagnosticSettings: [{ useThisWorkspace: true }] + } +} + +var logAnalyticsWorkspaceId = useExistingWorkspace ? existingWorkspaceResourceId : logAnalyticsWorkspace.outputs.resourceId + +// ========== Application Insights ========== // +// WAF best practices for Application Insights: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/application-insights +// Application Insights configuration defaults +var applicationInsightsEnabled = applicationInsightsConfiguration.?enabled ?? true +var applicationInsightsResourceName = applicationInsightsConfiguration.?name ?? 'appi-${solutionPrefix}' +module applicationInsights 'br/public:avm/res/insights/component:0.6.0' = if (applicationInsightsEnabled) { + name: take('avm.res.insights.component.${applicationInsightsResourceName}', 64) + params: { + name: applicationInsightsResourceName + workspaceResourceId: logAnalyticsWorkspaceId + location: applicationInsightsConfiguration.?location ?? solutionLocation + enableTelemetry: enableTelemetry + tags: applicationInsightsConfiguration.?tags ?? tags + retentionInDays: applicationInsightsConfiguration.?retentionInDays ?? 365 + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + kind: 'web' + disableIpMasking: false + flowType: 'Bluefield' + } +} + +// ========== User assigned identity Web Site ========== // +// WAF best practices for identity and access management: https://learn.microsoft.com/en-us/azure/well-architected/security/identity-access +var userAssignedManagedIdentityEnabled = userAssignedManagedIdentityConfiguration.?enabled ?? true +var userAssignedManagedIdentityResourceName = userAssignedManagedIdentityConfiguration.?name ?? 'id-${solutionPrefix}' +module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.1' = if (userAssignedManagedIdentityEnabled) { + name: take('avm.res.managed-identity.user-assigned-identity.${userAssignedManagedIdentityResourceName}', 64) + params: { + name: userAssignedManagedIdentityResourceName + tags: userAssignedManagedIdentityConfiguration.?tags ?? tags + location: userAssignedManagedIdentityConfiguration.?location ?? solutionLocation + enableTelemetry: enableTelemetry + } +} + +// ========== Network Security Groups ========== // +// WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network +// WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking +var networkSecurityGroupBackendEnabled = networkSecurityGroupBackendConfiguration.?enabled ?? true +var networkSecurityGroupBackendResourceName = networkSecurityGroupBackendConfiguration.?name ?? 'nsg-backend-${solutionPrefix}' +module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBackendEnabled) { + name: take('avm.res.network.network-security-group.${networkSecurityGroupBackendResourceName}', 64) + params: { + name: networkSecurityGroupBackendResourceName + location: networkSecurityGroupBackendConfiguration.?location ?? solutionLocation + tags: networkSecurityGroupBackendConfiguration.?tags ?? tags + enableTelemetry: enableTelemetry + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + securityRules: networkSecurityGroupBackendConfiguration.?securityRules ?? [ + // { + // name: 'DenySshRdpOutbound' //Azure Bastion + // properties: { + // priority: 200 + // access: 'Deny' + // protocol: '*' + // direction: 'Outbound' + // sourceAddressPrefix: 'VirtualNetwork' + // sourcePortRange: '*' + // destinationAddressPrefix: '*' + // destinationPortRanges: [ + // '3389' + // '22' + // ] + // } + // } + ] + } +} + +var networkSecurityGroupContainersEnabled = networkSecurityGroupContainersConfiguration.?enabled ?? true +var networkSecurityGroupContainersResourceName = networkSecurityGroupContainersConfiguration.?name ?? 'nsg-containers-${solutionPrefix}' +module networkSecurityGroupContainers 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupContainersEnabled) { + name: take('avm.res.network.network-security-group.${networkSecurityGroupContainersResourceName}', 64) + params: { + name: networkSecurityGroupContainersResourceName + location: networkSecurityGroupContainersConfiguration.?location ?? solutionLocation + tags: networkSecurityGroupContainersConfiguration.?tags ?? tags + enableTelemetry: enableTelemetry + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + securityRules: networkSecurityGroupContainersConfiguration.?securityRules ?? [ + // { + // name: 'DenySshRdpOutbound' //Azure Bastion + // properties: { + // priority: 200 + // access: 'Deny' + // protocol: '*' + // direction: 'Outbound' + // sourceAddressPrefix: 'VirtualNetwork' + // sourcePortRange: '*' + // destinationAddressPrefix: '*' + // destinationPortRanges: [ + // '3389' + // '22' + // ] + // } + // } + ] + } +} + +var networkSecurityGroupBastionEnabled = networkSecurityGroupBastionConfiguration.?enabled ?? true +var networkSecurityGroupBastionResourceName = networkSecurityGroupBastionConfiguration.?name ?? 'nsg-bastion-${solutionPrefix}' +module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupBastionEnabled) { + name: take('avm.res.network.network-security-group.${networkSecurityGroupBastionResourceName}', 64) + params: { + name: networkSecurityGroupBastionResourceName + location: networkSecurityGroupBastionConfiguration.?location ?? solutionLocation + tags: networkSecurityGroupBastionConfiguration.?tags ?? tags + enableTelemetry: enableTelemetry + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + securityRules: networkSecurityGroupBastionConfiguration.?securityRules ?? [ + { + name: 'AllowHttpsInBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'Internet' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 100 + direction: 'Inbound' + } + } + { + name: 'AllowGatewayManagerInBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'GatewayManager' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 110 + direction: 'Inbound' + } + } + { + name: 'AllowLoadBalancerInBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: 'AzureLoadBalancer' + destinationPortRange: '443' + destinationAddressPrefix: '*' + access: 'Allow' + priority: 120 + direction: 'Inbound' + } + } + { + name: 'AllowBastionHostCommunicationInBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationPortRanges: [ + '8080' + '5701' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 130 + direction: 'Inbound' + } + } + { + name: 'DenyAllInBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRange: '*' + destinationAddressPrefix: '*' + access: 'Deny' + priority: 1000 + direction: 'Inbound' + } + } + { + name: 'AllowSshRdpOutBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRanges: [ + '22' + '3389' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 100 + direction: 'Outbound' + } + } + { + name: 'AllowAzureCloudCommunicationOutBound' + properties: { + protocol: 'Tcp' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationPortRange: '443' + destinationAddressPrefix: 'AzureCloud' + access: 'Allow' + priority: 110 + direction: 'Outbound' + } + } + { + name: 'AllowBastionHostCommunicationOutBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: 'VirtualNetwork' + destinationPortRanges: [ + '8080' + '5701' + ] + destinationAddressPrefix: 'VirtualNetwork' + access: 'Allow' + priority: 120 + direction: 'Outbound' + } + } + { + name: 'AllowGetSessionInformationOutBound' + properties: { + protocol: '*' + sourcePortRange: '*' + sourceAddressPrefix: '*' + destinationAddressPrefix: 'Internet' + destinationPortRanges: [ + '80' + '443' + ] + access: 'Allow' + priority: 130 + direction: 'Outbound' + } + } + { + name: 'DenyAllOutBound' + properties: { + protocol: '*' + sourcePortRange: '*' + destinationPortRange: '*' + sourceAddressPrefix: '*' + destinationAddressPrefix: '*' + access: 'Deny' + priority: 1000 + direction: 'Outbound' + } + } + ] + } +} + +var networkSecurityGroupAdministrationEnabled = networkSecurityGroupAdministrationConfiguration.?enabled ?? true +var networkSecurityGroupAdministrationResourceName = networkSecurityGroupAdministrationConfiguration.?name ?? 'nsg-administration-${solutionPrefix}' +module networkSecurityGroupAdministration 'br/public:avm/res/network/network-security-group:0.5.1' = if (virtualNetworkEnabled && networkSecurityGroupAdministrationEnabled) { + name: take('avm.res.network.network-security-group.${networkSecurityGroupAdministrationResourceName}', 64) + params: { + name: networkSecurityGroupAdministrationResourceName + location: networkSecurityGroupAdministrationConfiguration.?location ?? solutionLocation + tags: networkSecurityGroupAdministrationConfiguration.?tags ?? tags + enableTelemetry: enableTelemetry + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + securityRules: networkSecurityGroupAdministrationConfiguration.?securityRules ?? [ + // { + // name: 'DenySshRdpOutbound' //Azure Bastion + // properties: { + // priority: 200 + // access: 'Deny' + // protocol: '*' + // direction: 'Outbound' + // sourceAddressPrefix: 'VirtualNetwork' + // sourcePortRange: '*' + // destinationAddressPrefix: '*' + // destinationPortRanges: [ + // '3389' + // '22' + // ] + // } + // } + ] + } +} + +// ========== Virtual Network ========== // +// WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network +// WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking +var virtualNetworkEnabled = virtualNetworkConfiguration.?enabled ?? true +var virtualNetworkResourceName = virtualNetworkConfiguration.?name ?? 'vnet-${solutionPrefix}' +module virtualNetwork 'br/public:avm/res/network/virtual-network:0.6.1' = if (virtualNetworkEnabled) { + name: take('avm.res.network.virtual-network.${virtualNetworkResourceName}', 64) + params: { + name: virtualNetworkResourceName + location: virtualNetworkConfiguration.?location ?? solutionLocation + tags: virtualNetworkConfiguration.?tags ?? tags + enableTelemetry: enableTelemetry + addressPrefixes: virtualNetworkConfiguration.?addressPrefixes ?? ['10.0.0.0/8'] + subnets: virtualNetworkConfiguration.?subnets ?? [ + { + name: 'backend' + addressPrefix: '10.0.0.0/27' + //defaultOutboundAccess: false TODO: check this configuration for a more restricted outbound access + networkSecurityGroupResourceId: networkSecurityGroupBackend.outputs.resourceId + } + { + name: 'administration' + addressPrefix: '10.0.0.32/27' + networkSecurityGroupResourceId: networkSecurityGroupAdministration.outputs.resourceId + } + { + // For Azure Bastion resources deployed on or after November 2, 2021, the minimum AzureBastionSubnet size is /26 or larger (/25, /24, etc.). + // https://learn.microsoft.com/en-us/azure/bastion/configuration-settings#subnet + name: 'AzureBastionSubnet' //This exact name is required for Azure Bastion + addressPrefix: '10.0.0.64/26' + networkSecurityGroupResourceId: networkSecurityGroupBastion.outputs.resourceId + } + { + // If you use your own vnw, you need to provide a subnet that is dedicated exclusively to the Container App environment you deploy. This subnet isn't available to other services + // https://learn.microsoft.com/en-us/azure/container-apps/networking?tabs=workload-profiles-env%2Cazure-cli#custom-vnw-configuration + name: 'containers' + addressPrefix: '10.0.2.0/23' //subnet of size /23 is required for container app + delegation: 'Microsoft.App/environments' + networkSecurityGroupResourceId: networkSecurityGroupContainers.outputs.resourceId + privateEndpointNetworkPolicies: 'Disabled' + privateLinkServiceNetworkPolicies: 'Enabled' + } + ] + } +} +var bastionEnabled = bastionConfiguration.?enabled ?? true +var bastionResourceName = bastionConfiguration.?name ?? 'bas-${solutionPrefix}' + +// ========== Bastion host ========== // +// WAF best practices for virtual networks: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-network +// WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking +module bastionHost 'br/public:avm/res/network/bastion-host:0.6.1' = if (virtualNetworkEnabled && bastionEnabled) { + name: take('avm.res.network.bastion-host.${bastionResourceName}', 64) + params: { + name: bastionResourceName + location: bastionConfiguration.?location ?? solutionLocation + skuName: bastionConfiguration.?sku ?? 'Standard' + enableTelemetry: enableTelemetry + tags: bastionConfiguration.?tags ?? tags + virtualNetworkResourceId: bastionConfiguration.?virtualNetworkResourceId ?? virtualNetwork.?outputs.?resourceId + publicIPAddressObject: { + name: bastionConfiguration.?publicIpResourceName ?? 'pip-bas${solutionPrefix}' + zones: [] + } + disableCopyPaste: false + enableFileCopy: false + enableIpConnect: true + enableShareableLink: true + } +} + +// ========== Virtual machine ========== // +// WAF best practices for virtual machines: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/virtual-machines +var virtualMachineEnabled = virtualMachineConfiguration.?enabled ?? true +var virtualMachineResourceName = virtualMachineConfiguration.?name ?? 'vm${solutionPrefix}' +module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.13.0' = if (virtualNetworkEnabled && virtualMachineEnabled) { + name: take('avm.res.compute.virtual-machine.${virtualMachineResourceName}', 64) + params: { + name: virtualMachineResourceName + computerName: take(virtualMachineResourceName, 15) + location: virtualMachineConfiguration.?location ?? solutionLocation + tags: virtualMachineConfiguration.?tags ?? tags + enableTelemetry: enableTelemetry + vmSize: virtualMachineConfiguration.?vmSize ?? 'Standard_D2s_v3' + adminUsername: virtualMachineConfiguration.?adminUsername ?? 'adminuser' + adminPassword: virtualMachineConfiguration.?adminPassword ?? guid(solutionPrefix, subscription().subscriptionId) + nicConfigurations: [ + { + name: 'nic-${virtualMachineResourceName}' + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + ipConfigurations: [ + { + name: '${virtualMachineResourceName}-nic01-ipconfig01' + subnetResourceId: virtualMachineConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[1] + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + } + ] + } + ] + imageReference: { + publisher: 'microsoft-dsvm' + offer: 'dsvm-win-2022' + sku: 'winserver-2022' + version: 'latest' + } + osDisk: { + name: 'osdisk-${virtualMachineResourceName}' + createOption: 'FromImage' + managedDisk: { + storageAccountType: 'Standard_LRS' + } + diskSizeGB: 128 + caching: 'ReadWrite' + } + osType: 'Windows' + encryptionAtHost: false //The property 'securityProfile.encryptionAtHost' is not valid because the 'Microsoft.Compute/EncryptionAtHost' feature is not enabled for this subscription. + zone: 0 + extensionAadJoinConfig: { + enabled: true + typeHandlerVersion: '1.0' + } + } +} + +// ========== AI Foundry: AI Services ========== // +// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai +var openAiSubResource = 'account' +var openAiPrivateDnsZones = { + 'privatelink.cognitiveservices.azure.com': openAiSubResource + 'privatelink.openai.azure.com': openAiSubResource + 'privatelink.services.ai.azure.com': openAiSubResource +} + +module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ + for zone in objectKeys(openAiPrivateDnsZones): if (virtualNetworkEnabled && aiFoundryAIservicesEnabled) { + name: take( + 'avm.res.network.private-dns-zone.ai-services.${uniqueString(aiFoundryAiServicesResourceName,zone)}.${solutionPrefix}', + 64 + ) + params: { + name: zone + tags: tags + enableTelemetry: enableTelemetry + virtualNetworkLinks: [ + { + name: 'vnetlink-${split(zone, '.')[1]}' + virtualNetworkResourceId: virtualNetwork.outputs.resourceId + } + ] + } + } +] + +// NOTE: Required version 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' not available in AVM +var useExistingFoundryProject = !empty(existingFoundryProjectResourceId) +var existingAiFoundryName = useExistingFoundryProject?split( existingFoundryProjectResourceId,'/')[8]:'' +var aiFoundryAiServicesResourceName = useExistingFoundryProject? existingAiFoundryName : aiFoundryAiServicesConfiguration.?name ?? 'aisa-${solutionPrefix}' +var aiFoundryAIservicesEnabled = aiFoundryAiServicesConfiguration.?enabled ?? true +var aiFoundryAiServicesModelDeployment = { + format: 'OpenAI' + name: gptModelName + version: gptModelVersion + sku: { + name: modelDeploymentType + //Curently the capacity is set to 140 for opinanal performance. + capacity: aiFoundryAiServicesConfiguration.?modelCapacity ?? gptModelCapacity + } + raiPolicyName: 'Microsoft.Default' +} + +module aiFoundryAiServices 'modules/account/main.bicep' = if (aiFoundryAIservicesEnabled) { + name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) + params: { + name: aiFoundryAiServicesResourceName + tags: aiFoundryAiServicesConfiguration.?tags ?? tags + location: aiFoundryAiServicesConfiguration.?location ?? aiDeploymentsLocation + enableTelemetry: enableTelemetry + projectName: 'aifp-${solutionPrefix}' + projectDescription: 'aifp-${solutionPrefix}' + existingFoundryProjectResourceId: existingFoundryProjectResourceId + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + sku: aiFoundryAiServicesConfiguration.?sku ?? 'S0' + kind: 'AIServices' + disableLocalAuth: true //Should be set to true for WAF aligned configuration + customSubDomainName: aiFoundryAiServicesResourceName + apiProperties: { + //staticsEnabled: false + } + allowProjectManagement: true + managedIdentities: { + systemAssigned: true + } + publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' + networkAcls: { + bypass: 'AzureServices' + defaultAction: (virtualNetworkEnabled) ? 'Deny' : 'Allow' + } + privateEndpoints: virtualNetworkEnabled && !useExistingFoundryProject + ? ([ + { + name: 'pep-${aiFoundryAiServicesResourceName}' + customNetworkInterfaceName: 'nic-${aiFoundryAiServicesResourceName}' + subnetResourceId: aiFoundryAiServicesConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[0] + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: map(objectKeys(openAiPrivateDnsZones), zone => { + name: replace(zone, '.', '-') + privateDnsZoneResourceId: resourceId('Microsoft.Network/privateDnsZones', zone) + }) + } + } + ]) + : [] + deployments: aiFoundryAiServicesConfiguration.?deployments ?? [ + { + name: aiFoundryAiServicesModelDeployment.name + model: { + format: aiFoundryAiServicesModelDeployment.format + name: aiFoundryAiServicesModelDeployment.name + version: aiFoundryAiServicesModelDeployment.version + } + raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName + sku: { + name: aiFoundryAiServicesModelDeployment.sku.name + capacity: aiFoundryAiServicesModelDeployment.sku.capacity + } + } + ] + } +} + +// AI Foundry: AI Project +// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai +var existingAiFounryProjectName = useExistingFoundryProject ? last(split( existingFoundryProjectResourceId,'/')) : '' +var aiFoundryAiProjectName = useExistingFoundryProject ? existingAiFounryProjectName : aiFoundryAiProjectConfiguration.?name ?? 'aifp-${solutionPrefix}' + +var useExistingResourceId = !empty(existingFoundryProjectResourceId) + +module cogServiceRoleAssignmentsNew './modules/role.bicep' = if(!useExistingResourceId) { + params: { + name: 'new-${guid(containerApp.name, aiFoundryAiServices.outputs.resourceId)}' + principalId: containerApp.outputs.?systemAssignedMIPrincipalId! + aiServiceName: aiFoundryAiServices.outputs.name + } + scope: resourceGroup(subscription().subscriptionId, resourceGroup().name) +} + +module cogServiceRoleAssignmentsExisting './modules/role.bicep' = if(useExistingResourceId) { + params: { + name: 'reuse-${guid(containerApp.name, aiFoundryAiServices.outputs.aiProjectInfo.resourceId)}' + principalId: containerApp.outputs.?systemAssignedMIPrincipalId! + aiServiceName: aiFoundryAiServices.outputs.name + } + scope: resourceGroup( split(existingFoundryProjectResourceId, '/')[2], split(existingFoundryProjectResourceId, '/')[4]) +} + +// ========== Cosmos DB ========== // +// WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db +module privateDnsZonesCosmosDb 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (virtualNetworkEnabled) { + name: take('avm.res.network.private-dns-zone.cosmos-db.${solutionPrefix}', 64) + params: { + name: 'privatelink.documents.azure.com' + enableTelemetry: enableTelemetry + virtualNetworkLinks: [ + { + name: 'vnetlink-cosmosdb' + virtualNetworkResourceId: virtualNetwork.outputs.resourceId + } + ] + tags: tags + } +} + +var cosmosDbAccountEnabled = cosmosDbAccountConfiguration.?enabled ?? true +var cosmosDbResourceName = cosmosDbAccountConfiguration.?name ?? 'cosmos-${solutionPrefix}' +var cosmosDbDatabaseName = 'macae' +var cosmosDbDatabaseMemoryContainerName = 'memory' +module cosmosDb 'br/public:avm/res/document-db/database-account:0.12.0' = if (cosmosDbAccountEnabled) { + name: take('avm.res.document-db.database-account.${cosmosDbResourceName}', 64) + params: { + // Required parameters + name: cosmosDbAccountConfiguration.?name ?? 'cosmos-${solutionPrefix}' + location: cosmosDbAccountConfiguration.?location ?? solutionLocation + tags: cosmosDbAccountConfiguration.?tags ?? tags + enableTelemetry: enableTelemetry + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + databaseAccountOfferType: 'Standard' + enableFreeTier: false + networkRestrictions: { + networkAclBypass: 'None' + publicNetworkAccess: virtualNetworkEnabled ? 'Disabled' : 'Enabled' + } + privateEndpoints: virtualNetworkEnabled + ? [ + { + name: 'pep-${cosmosDbResourceName}' + customNetworkInterfaceName: 'nic-${cosmosDbResourceName}' + privateDnsZoneGroup: { + privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesCosmosDb.outputs.resourceId }] + } + service: 'Sql' + subnetResourceId: cosmosDbAccountConfiguration.?subnetResourceId ?? virtualNetwork.outputs.subnetResourceIds[0] + } + ] + : [] + sqlDatabases: concat(cosmosDbAccountConfiguration.?sqlDatabases ?? [], [ + { + name: cosmosDbDatabaseName + containers: [ + { + name: cosmosDbDatabaseMemoryContainerName + paths: [ + '/session_id' + ] + kind: 'Hash' + version: 2 + } + ] + } + ]) + locations: [ + { + locationName: cosmosDbAccountConfiguration.?location ?? solutionLocation + failoverPriority: 0 + isZoneRedundant: false + } + ] + capabilitiesToAdd: [ + 'EnableServerless' + ] + sqlRoleAssignmentsPrincipalIds: [ + containerApp.outputs.?systemAssignedMIPrincipalId + ] + sqlRoleDefinitions: [ + { + // Replace this with built-in role definition Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor + roleType: 'CustomRole' + roleName: 'Cosmos DB SQL Data Contributor' + name: 'cosmos-db-sql-data-contributor' + dataAction: [ + 'Microsoft.DocumentDB/databaseAccounts/readMetadata' + 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' + 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' + ] + } + ] + } +} + +// ========== Backend Container App Environment ========== // +// WAF best practices for container apps: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-container-apps +var containerAppEnvironmentEnabled = containerAppEnvironmentConfiguration.?enabled ?? true +var containerAppEnvironmentResourceName = containerAppEnvironmentConfiguration.?name ?? 'cae-${solutionPrefix}' +module containerAppEnvironment 'modules/container-app-environment.bicep' = if (containerAppEnvironmentEnabled) { + name: take('module.container-app-environment.${containerAppEnvironmentResourceName}', 64) + params: { + name: containerAppEnvironmentResourceName + tags: containerAppEnvironmentConfiguration.?tags ?? tags + location: containerAppEnvironmentConfiguration.?location ?? solutionLocation + logAnalyticsResourceId: logAnalyticsWorkspaceId + publicNetworkAccess: 'Enabled' + zoneRedundant: false + applicationInsightsConnectionString: applicationInsights.outputs.connectionString + enableTelemetry: enableTelemetry + subnetResourceId: virtualNetworkEnabled + ? containerAppEnvironmentConfiguration.?subnetResourceId ?? virtualNetwork.?outputs.?subnetResourceIds[3] ?? '' + : '' + } +} + +// ========== Backend Container App Service ========== // +// WAF best practices for container apps: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-container-apps +var containerAppEnabled = containerAppConfiguration.?enabled ?? true +var containerAppResourceName = containerAppConfiguration.?name ?? 'ca-${solutionPrefix}' +module containerApp 'br/public:avm/res/app/container-app:0.14.2' = if (containerAppEnabled) { + name: take('avm.res.app.container-app.${containerAppResourceName}', 64) + params: { + name: containerAppResourceName + tags: containerAppConfiguration.?tags ?? tags + location: containerAppConfiguration.?location ?? solutionLocation + enableTelemetry: enableTelemetry + environmentResourceId: containerAppConfiguration.?environmentResourceId ?? containerAppEnvironment.outputs.resourceId + managedIdentities: { + systemAssigned: true //Replace with user assigned identity + userAssignedResourceIds: [userAssignedIdentity.outputs.resourceId] + } + ingressTargetPort: containerAppConfiguration.?ingressTargetPort ?? 8000 + ingressExternal: true + activeRevisionsMode: 'Single' + corsPolicy: { + allowedOrigins: [ + 'https://${webSiteName}.azurewebsites.net' + 'http://${webSiteName}.azurewebsites.net' + ] + } + scaleSettings: { + //TODO: Make maxReplicas and minReplicas parameterized + maxReplicas: containerAppConfiguration.?maxReplicas ?? 1 + minReplicas: containerAppConfiguration.?minReplicas ?? 1 + rules: [ + { + name: 'http-scaler' + http: { + metadata: { + concurrentRequests: containerAppConfiguration.?concurrentRequests ?? '100' + } + } + } + ] + } + containers: [ + { + name: containerAppConfiguration.?containerName ?? 'backend' + image: '${containerAppConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}/${containerAppConfiguration.?containerImageName ?? 'macaebackend'}:${containerAppConfiguration.?containerImageTag ?? 'latest'}' + resources: { + //TODO: Make cpu and memory parameterized + cpu: containerAppConfiguration.?containerCpu ?? '2.0' + memory: containerAppConfiguration.?containerMemory ?? '4.0Gi' + } + env: [ + { + name: 'COSMOSDB_ENDPOINT' + value: 'https://${cosmosDbResourceName}.documents.azure.com:443/' + } + { + name: 'COSMOSDB_DATABASE' + value: cosmosDbDatabaseName + } + { + name: 'COSMOSDB_CONTAINER' + value: cosmosDbDatabaseMemoryContainerName + } + { + name: 'AZURE_OPENAI_ENDPOINT' + value: 'https://${aiFoundryAiServicesResourceName}.openai.azure.com/' + } + { + name: 'AZURE_OPENAI_MODEL_NAME' + value: aiFoundryAiServicesModelDeployment.name + } + { + name: 'AZURE_OPENAI_DEPLOYMENT_NAME' + value: aiFoundryAiServicesModelDeployment.name + } + { + name: 'AZURE_OPENAI_API_VERSION' + value: '2025-01-01-preview' //TODO: set parameter/variable + } + { + name: 'APPLICATIONINSIGHTS_INSTRUMENTATION_KEY' + value: applicationInsights.outputs.instrumentationKey + } + { + name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' + value: applicationInsights.outputs.connectionString + } + { + name: 'AZURE_AI_SUBSCRIPTION_ID' + value: subscription().subscriptionId + } + { + name: 'AZURE_AI_RESOURCE_GROUP' + value: resourceGroup().name + } + { + name: 'AZURE_AI_PROJECT_NAME' + value: aiFoundryAiProjectName + } + { + name: 'FRONTEND_SITE_NAME' + value: 'https://${webSiteName}.azurewebsites.net' + } + { + name: 'AZURE_AI_AGENT_ENDPOINT' + value: aiFoundryAiServices.outputs.aiProjectInfo.apiEndpoint + } + { + name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' + value: aiFoundryAiServicesModelDeployment.name + } + { + name: 'APP_ENV' + value: 'Prod' + } + ] + } + ] + } +} + +var webServerFarmEnabled = webServerFarmConfiguration.?enabled ?? true +var webServerFarmResourceName = webServerFarmConfiguration.?name ?? 'asp-${solutionPrefix}' + +// ========== Frontend server farm ========== // +// WAF best practices for web app service: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps +module webServerFarm 'br/public:avm/res/web/serverfarm:0.4.1' = if (webServerFarmEnabled) { + name: take('avm.res.web.serverfarm.${webServerFarmResourceName}', 64) + params: { + name: webServerFarmResourceName + tags: tags + location: webServerFarmConfiguration.?location ?? solutionLocation + skuName: webServerFarmConfiguration.?skuName ?? 'P1v3' + skuCapacity: webServerFarmConfiguration.?skuCapacity ?? 3 + reserved: true + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + kind: 'linux' + zoneRedundant: false //TODO: make it zone redundant for waf aligned + } +} + +// ========== Frontend web site ========== // +// WAF best practices for web app service: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps +var webSiteEnabled = webSiteConfiguration.?enabled ?? true + +var webSiteName = 'app-${solutionPrefix}' +module webSite 'br/public:avm/res/web/site:0.15.1' = if (webSiteEnabled) { + name: take('avm.res.web.site.${webSiteName}', 64) + params: { + name: webSiteName + tags: webSiteConfiguration.?tags ?? tags + location: webSiteConfiguration.?location ?? solutionLocation + kind: 'app,linux,container' + enableTelemetry: enableTelemetry + serverFarmResourceId: webSiteConfiguration.?environmentResourceId ?? webServerFarm.?outputs.resourceId + appInsightResourceId: applicationInsights.outputs.resourceId + diagnosticSettings: [{ workspaceResourceId: logAnalyticsWorkspaceId }] + publicNetworkAccess: 'Enabled' //TODO: use Azure Front Door WAF or Application Gateway WAF instead + siteConfig: { + linuxFxVersion: 'DOCKER|${webSiteConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}/${webSiteConfiguration.?containerImageName ?? 'macaefrontend'}:${webSiteConfiguration.?containerImageTag ?? 'latest'}' + } + appSettingsKeyValuePairs: { + SCM_DO_BUILD_DURING_DEPLOYMENT: 'true' + DOCKER_REGISTRY_SERVER_URL: 'https://${webSiteConfiguration.?containerImageRegistryDomain ?? 'biabcontainerreg.azurecr.io'}' + WEBSITES_PORT: '3000' + WEBSITES_CONTAINER_START_TIME_LIMIT: '1800' // 30 minutes, adjust as needed + BACKEND_API_URL: 'https://${containerApp.outputs.fqdn}' + AUTH_ENABLED: 'false' + APP_ENV: 'Prod' + } + } +} + +// ============ // +// Outputs // +// ============ // + +// Add your outputs here + +@description('The default url of the website to connect to the Multi-Agent Custom Automation Engine solution.') +output webSiteDefaultHostname string = webSite.outputs.defaultHostname + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Log Analytics Workspace resource configuration.') +type logAnalyticsWorkspaceConfigurationType = { + @description('Optional. If the Log Analytics Workspace resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Log Analytics Workspace resource.') + @maxLength(63) + name: string? + + @description('Optional. Location for the Log Analytics Workspace resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to for the Log Analytics Workspace resource.') + tags: object? + + @description('Optional. The SKU for the Log Analytics Workspace resource.') + sku: ('CapacityReservation' | 'Free' | 'LACluster' | 'PerGB2018' | 'PerNode' | 'Premium' | 'Standalone' | 'Standard')? + + @description('Optional. The number of days to retain the data in the Log Analytics Workspace. If empty, it will be set to 365 days.') + @maxValue(730) + dataRetentionInDays: int? + + @description('Optional: Existing Log Analytics Workspace Resource ID') + existingWorkspaceResourceId: string? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Application Insights resource configuration.') +type applicationInsightsConfigurationType = { + @description('Optional. If the Application Insights resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Application Insights resource.') + @maxLength(90) + name: string? + + @description('Optional. Location for the Application Insights resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Application Insights resource.') + tags: object? + + @description('Optional. The retention of Application Insights data in days. If empty, Standard will be used.') + retentionInDays: (120 | 180 | 270 | 30 | 365 | 550 | 60 | 730 | 90)? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Application User Assigned Managed Identity resource configuration.') +type userAssignedManagedIdentityType = { + @description('Optional. If the User Assigned Managed Identity resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the User Assigned Managed Identity resource.') + @maxLength(128) + name: string? + + @description('Optional. Location for the User Assigned Managed Identity resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the User Assigned Managed Identity resource.') + tags: object? +} + +@export() +import { securityRuleType } from 'br/public:avm/res/network/network-security-group:0.5.1' +@description('The type for the Multi-Agent Custom Automation Engine Network Security Group resource configuration.') +type networkSecurityGroupConfigurationType = { + @description('Optional. If the Network Security Group resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Network Security Group resource.') + @maxLength(90) + name: string? + + @description('Optional. Location for the Network Security Group resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Network Security Group resource.') + tags: object? + + @description('Optional. The security rules to set for the Network Security Group resource.') + securityRules: securityRuleType[]? +} + +@export() +@description('The type for the Multi-Agent Custom Automation virtual network resource configuration.') +type virtualNetworkConfigurationType = { + @description('Optional. If the Virtual Network resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Virtual Network resource.') + @maxLength(90) + name: string? + + @description('Optional. Location for the Virtual Network resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Virtual Network resource.') + tags: object? + + @description('Optional. An array of 1 or more IP Addresses prefixes for the Virtual Network resource.') + addressPrefixes: string[]? + + @description('Optional. An array of 1 or more subnets for the Virtual Network resource.') + subnets: subnetType[]? +} + +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +type subnetType = { + @description('Optional. The Name of the subnet resource.') + name: string + + @description('Conditional. The address prefix for the subnet. Required if `addressPrefixes` is empty.') + addressPrefix: string? + + @description('Conditional. List of address prefixes for the subnet. Required if `addressPrefix` is empty.') + addressPrefixes: string[]? + + @description('Optional. Application gateway IP configurations of virtual network resource.') + applicationGatewayIPConfigurations: object[]? + + @description('Optional. The delegation to enable on the subnet.') + delegation: string? + + @description('Optional. The resource ID of the NAT Gateway to use for the subnet.') + natGatewayResourceId: string? + + @description('Optional. The resource ID of the network security group to assign to the subnet.') + networkSecurityGroupResourceId: string? + + @description('Optional. enable or disable apply network policies on private endpoint in the subnet.') + privateEndpointNetworkPolicies: ('Disabled' | 'Enabled' | 'NetworkSecurityGroupEnabled' | 'RouteTableEnabled')? + + @description('Optional. enable or disable apply network policies on private link service in the subnet.') + privateLinkServiceNetworkPolicies: ('Disabled' | 'Enabled')? + + @description('Optional. Array of role assignments to create.') + roleAssignments: roleAssignmentType[]? + + @description('Optional. The resource ID of the route table to assign to the subnet.') + routeTableResourceId: string? + + @description('Optional. An array of service endpoint policies.') + serviceEndpointPolicies: object[]? + + @description('Optional. The service endpoints to enable on the subnet.') + serviceEndpoints: string[]? + + @description('Optional. Set this property to false to disable default outbound connectivity for all VMs in the subnet. This property can only be set at the time of subnet creation and cannot be updated for an existing subnet.') + defaultOutboundAccess: bool? + + @description('Optional. Set this property to Tenant to allow sharing subnet with other subscriptions in your AAD tenant. This property can only be set if defaultOutboundAccess is set to false, both properties can only be set if subnet is empty.') + sharingScope: ('DelegatedServices' | 'Tenant')? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Bastion resource configuration.') +type bastionConfigurationType = { + @description('Optional. If the Bastion resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Bastion resource.') + @maxLength(90) + name: string? + + @description('Optional. Location for the Bastion resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Bastion resource.') + tags: object? + + @description('Optional. The SKU for the Bastion resource.') + sku: ('Basic' | 'Developer' | 'Premium' | 'Standard')? + + @description('Optional. The Virtual Network resource id where the Bastion resource should be deployed.') + virtualNetworkResourceId: string? + + @description('Optional. The name of the Public Ip resource created to connect to Bastion.') + publicIpResourceName: string? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine virtual machine resource configuration.') +type virtualMachineConfigurationType = { + @description('Optional. If the Virtual Machine resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Virtual Machine resource.') + @maxLength(90) + name: string? + + @description('Optional. Location for the Virtual Machine resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Virtual Machine resource.') + tags: object? + + @description('Optional. Specifies the size for the Virtual Machine resource.') + vmSize: ( + | 'Basic_A0' + | 'Basic_A1' + | 'Basic_A2' + | 'Basic_A3' + | 'Basic_A4' + | 'Standard_A0' + | 'Standard_A1' + | 'Standard_A2' + | 'Standard_A3' + | 'Standard_A4' + | 'Standard_A5' + | 'Standard_A6' + | 'Standard_A7' + | 'Standard_A8' + | 'Standard_A9' + | 'Standard_A10' + | 'Standard_A11' + | 'Standard_A1_v2' + | 'Standard_A2_v2' + | 'Standard_A4_v2' + | 'Standard_A8_v2' + | 'Standard_A2m_v2' + | 'Standard_A4m_v2' + | 'Standard_A8m_v2' + | 'Standard_B1s' + | 'Standard_B1ms' + | 'Standard_B2s' + | 'Standard_B2ms' + | 'Standard_B4ms' + | 'Standard_B8ms' + | 'Standard_D1' + | 'Standard_D2' + | 'Standard_D3' + | 'Standard_D4' + | 'Standard_D11' + | 'Standard_D12' + | 'Standard_D13' + | 'Standard_D14' + | 'Standard_D1_v2' + | 'Standard_D2_v2' + | 'Standard_D3_v2' + | 'Standard_D4_v2' + | 'Standard_D5_v2' + | 'Standard_D2_v3' + | 'Standard_D4_v3' + | 'Standard_D8_v3' + | 'Standard_D16_v3' + | 'Standard_D32_v3' + | 'Standard_D64_v3' + | 'Standard_D2s_v3' + | 'Standard_D4s_v3' + | 'Standard_D8s_v3' + | 'Standard_D16s_v3' + | 'Standard_D32s_v3' + | 'Standard_D64s_v3' + | 'Standard_D11_v2' + | 'Standard_D12_v2' + | 'Standard_D13_v2' + | 'Standard_D14_v2' + | 'Standard_D15_v2' + | 'Standard_DS1' + | 'Standard_DS2' + | 'Standard_DS3' + | 'Standard_DS4' + | 'Standard_DS11' + | 'Standard_DS12' + | 'Standard_DS13' + | 'Standard_DS14' + | 'Standard_DS1_v2' + | 'Standard_DS2_v2' + | 'Standard_DS3_v2' + | 'Standard_DS4_v2' + | 'Standard_DS5_v2' + | 'Standard_DS11_v2' + | 'Standard_DS12_v2' + | 'Standard_DS13_v2' + | 'Standard_DS14_v2' + | 'Standard_DS15_v2' + | 'Standard_DS13-4_v2' + | 'Standard_DS13-2_v2' + | 'Standard_DS14-8_v2' + | 'Standard_DS14-4_v2' + | 'Standard_E2_v3' + | 'Standard_E4_v3' + | 'Standard_E8_v3' + | 'Standard_E16_v3' + | 'Standard_E32_v3' + | 'Standard_E64_v3' + | 'Standard_E2s_v3' + | 'Standard_E4s_v3' + | 'Standard_E8s_v3' + | 'Standard_E16s_v3' + | 'Standard_E32s_v3' + | 'Standard_E64s_v3' + | 'Standard_E32-16_v3' + | 'Standard_E32-8s_v3' + | 'Standard_E64-32s_v3' + | 'Standard_E64-16s_v3' + | 'Standard_F1' + | 'Standard_F2' + | 'Standard_F4' + | 'Standard_F8' + | 'Standard_F16' + | 'Standard_F1s' + | 'Standard_F2s' + | 'Standard_F4s' + | 'Standard_F8s' + | 'Standard_F16s' + | 'Standard_F2s_v2' + | 'Standard_F4s_v2' + | 'Standard_F8s_v2' + | 'Standard_F16s_v2' + | 'Standard_F32s_v2' + | 'Standard_F64s_v2' + | 'Standard_F72s_v2' + | 'Standard_G1' + | 'Standard_G2' + | 'Standard_G3' + | 'Standard_G4' + | 'Standard_G5' + | 'Standard_GS1' + | 'Standard_GS2' + | 'Standard_GS3' + | 'Standard_GS4' + | 'Standard_GS5' + | 'Standard_GS4-8' + | 'Standard_GS4-4' + | 'Standard_GS5-16' + | 'Standard_GS5-8' + | 'Standard_H8' + | 'Standard_H16' + | 'Standard_H8m' + | 'Standard_H16m' + | 'Standard_H16r' + | 'Standard_H16mr' + | 'Standard_L4s' + | 'Standard_L8s' + | 'Standard_L16s' + | 'Standard_L32s' + | 'Standard_M64s' + | 'Standard_M64ms' + | 'Standard_M128s' + | 'Standard_M128ms' + | 'Standard_M64-32ms' + | 'Standard_M64-16ms' + | 'Standard_M128-64ms' + | 'Standard_M128-32ms' + | 'Standard_NC6' + | 'Standard_NC12' + | 'Standard_NC24' + | 'Standard_NC24r' + | 'Standard_NC6s_v2' + | 'Standard_NC12s_v2' + | 'Standard_NC24s_v2' + | 'Standard_NC24rs_v2' + | 'Standard_NC6s_v3' + | 'Standard_NC12s_v3' + | 'Standard_NC24s_v3' + | 'Standard_NC24rs_v3' + | 'Standard_ND6s' + | 'Standard_ND12s' + | 'Standard_ND24s' + | 'Standard_ND24rs' + | 'Standard_NV6' + | 'Standard_NV12' + | 'Standard_NV24')? + + @description('Optional. The username for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') + adminUsername: string? + + @description('Optional. The password for the administrator account on the virtual machine. Required if a virtual machine is created as part of the module.') + @secure() + adminPassword: string? + + @description('Optional. The resource ID of the subnet where the Virtual Machine resource should be deployed.') + subnetResourceId: string? +} + +@export() +import { deploymentType } from 'br/public:avm/res/cognitive-services/account:0.10.2' +@description('The type for the Multi-Agent Custom Automation Engine AI Services resource configuration.') +type aiServicesConfigurationType = { + @description('Optional. If the AI Services resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the AI Services resource.') + @maxLength(90) + name: string? + + @description('Optional. Location for the AI Services resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the AI Services resource.') + tags: object? + + @description('Optional. The SKU of the AI Services resource. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') + sku: ( + | 'C2' + | 'C3' + | 'C4' + | 'F0' + | 'F1' + | 'S' + | 'S0' + | 'S1' + | 'S10' + | 'S2' + | 'S3' + | 'S4' + | 'S5' + | 'S6' + | 'S7' + | 'S8' + | 'S9')? + + @description('Optional. The resource Id of the subnet where the AI Services private endpoint should be created.') + subnetResourceId: string? + + @description('Optional. The model deployments to set for the AI Services resource.') + deployments: deploymentType[]? + + @description('Optional. The capacity to set for AI Services GTP model.') + modelCapacity: int? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine AI Foundry AI Project resource configuration.') +type aiProjectConfigurationType = { + @description('Optional. If the AI Project resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the AI Project resource.') + @maxLength(90) + name: string? + + @description('Optional. Location for the AI Project resource deployment.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The SKU of the AI Project resource.') + sku: ('Basic' | 'Free' | 'Standard' | 'Premium')? + + @description('Optional. The tags to set for the AI Project resource.') + tags: object? +} + +import { sqlDatabaseType } from 'br/public:avm/res/document-db/database-account:0.13.0' +@export() +@description('The type for the Multi-Agent Custom Automation Engine Cosmos DB Account resource configuration.') +type cosmosDbAccountConfigurationType = { + @description('Optional. If the Cosmos DB Account resource should be deployed or not.') + enabled: bool? + @description('Optional. The name of the Cosmos DB Account resource.') + @maxLength(60) + name: string? + + @description('Optional. Location for the Cosmos DB Account resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Cosmos DB Account resource.') + tags: object? + + @description('Optional. The resource Id of the subnet where the Cosmos DB Account private endpoint should be created.') + subnetResourceId: string? + + @description('Optional. The SQL databases configuration for the Cosmos DB Account resource.') + sqlDatabases: sqlDatabaseType[]? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Container App Environment resource configuration.') +type containerAppEnvironmentConfigurationType = { + @description('Optional. If the Container App Environment resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Container App Environment resource.') + @maxLength(60) + name: string? + + @description('Optional. Location for the Container App Environment resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Container App Environment resource.') + tags: object? + + @description('Optional. The resource Id of the subnet where the Container App Environment private endpoint should be created.') + subnetResourceId: string? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Container App resource configuration.') +type containerAppConfigurationType = { + @description('Optional. If the Container App resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Container App resource.') + @maxLength(60) + name: string? + + @description('Optional. Location for the Container App resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Container App resource.') + tags: object? + + @description('Optional. The resource Id of the Container App Environment where the Container App should be created.') + environmentResourceId: string? + + @description('Optional. The maximum number of replicas of the Container App.') + maxReplicas: int? + + @description('Optional. The minimum number of replicas of the Container App.') + minReplicas: int? + + @description('Optional. The ingress target port of the Container App.') + ingressTargetPort: int? + + @description('Optional. The concurrent requests allowed for the Container App.') + concurrentRequests: string? + + @description('Optional. The name given to the Container App.') + containerName: string? + + @description('Optional. The container registry domain of the container image to be used by the Container App. Default to `biabcontainerreg.azurecr.io`') + containerImageRegistryDomain: string? + + @description('Optional. The name of the container image to be used by the Container App.') + containerImageName: string? + + @description('Optional. The tag of the container image to be used by the Container App.') + containerImageTag: string? + + @description('Optional. The CPU reserved for the Container App. Defaults to 2.0') + containerCpu: string? + + @description('Optional. The Memory reserved for the Container App. Defaults to 4.0Gi') + containerMemory: string? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Entra ID Application resource configuration.') +type entraIdApplicationConfigurationType = { + @description('Optional. If the Entra ID Application for website authentication should be deployed or not.') + enabled: bool? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Web Server Farm resource configuration.') +type webServerFarmConfigurationType = { + @description('Optional. If the Web Server Farm resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Web Server Farm resource.') + @maxLength(60) + name: string? + + @description('Optional. Location for the Web Server Farm resource.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Web Server Farm resource.') + tags: object? + + @description('Optional. The name of th SKU that will determine the tier, size and family for the Web Server Farm resource. This defaults to P1v3 to leverage availability zones.') + skuName: string? + + @description('Optional. Number of workers associated with the App Service Plan. This defaults to 3, to leverage availability zones.') + skuCapacity: int? +} + +@export() +@description('The type for the Multi-Agent Custom Automation Engine Web Site resource configuration.') +type webSiteConfigurationType = { + @description('Optional. If the Web Site resource should be deployed or not.') + enabled: bool? + + @description('Optional. The name of the Web Site resource.') + @maxLength(60) + name: string? + + @description('Optional. Location for the Web Site resource deployment.') + @metadata({ azd: { type: 'location' } }) + location: string? + + @description('Optional. The tags to set for the Web Site resource.') + tags: object? + + @description('Optional. The resource Id of the Web Site Environment where the Web Site should be created.') + environmentResourceId: string? + + @description('Optional. The name given to the Container App.') + containerName: string? + + @description('Optional. The container registry domain of the container image to be used by the Web Site. Default to `biabcontainerreg.azurecr.io`') + containerImageRegistryDomain: string? + + @description('Optional. The name of the container image to be used by the Web Site.') + containerImageName: string? + + @description('Optional. The tag of the container image to be used by the Web Site.') + containerImageTag: string? +} diff --git a/infra/old/08-2025/main.parameters.json b/infra/old/08-2025/main.parameters.json new file mode 100644 index 000000000..16b465617 --- /dev/null +++ b/infra/old/08-2025/main.parameters.json @@ -0,0 +1,102 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "aiModelDeployments": { + "value": [ + { + "name": "gpt", + "model": { + "name": "gpt-4o", + "version": "2024-08-06", + "format": "OpenAI" + }, + "sku": { + "name": "GlobalStandard", + "capacity": 140 + } + } + ] + }, + "environmentName": { + "value": "${AZURE_ENV_NAME}" + }, + "solutionLocation": { + "value": "${AZURE_LOCATION}" + }, + "aiDeploymentsLocation": { + "value": "${AZURE_ENV_OPENAI_LOCATION}" + }, + "modelDeploymentType": { + "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" + }, + "gptModelName": { + "value": "${AZURE_ENV_MODEL_NAME}" + }, + "gptModelVersion": { + "value": "${AZURE_ENV_MODEL_VERSION}" + }, + "gptModelCapacity": { + "value": "${AZURE_ENV_MODEL_CAPACITY}" + }, + "existingFoundryProjectResourceId": { + "value": "${AZURE_ENV_FOUNDRY_PROJECT_ID}" + }, + "imageTag": { + "value": "${AZURE_ENV_IMAGE_TAG}" + }, + "enableTelemetry": { + "value": "${AZURE_ENV_ENABLE_TELEMETRY}" + }, + "existingLogAnalyticsWorkspaceId": { + "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" + }, + "backendExists": { + "value": "${SERVICE_BACKEND_RESOURCE_EXISTS=false}" + }, + "backendDefinition": { + "value": { + "settings": [ + { + "name": "", + "value": "${VAR}", + "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", + "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment." + }, + { + "name": "", + "value": "${VAR_S}", + "secret": true, + "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", + "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment." + } + ] + } + }, + "frontendExists": { + "value": "${SERVICE_FRONTEND_RESOURCE_EXISTS=false}" + }, + "frontendDefinition": { + "value": { + "settings": [ + { + "name": "", + "value": "${VAR}", + "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", + "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR} to use the value of 'VAR' from the current environment." + }, + { + "name": "", + "value": "${VAR_S}", + "secret": true, + "_comment_name": "The name of the environment variable when running in Azure. If empty, ignored.", + "_comment_value": "The value to provide. This can be a fixed literal, or an expression like ${VAR_S} to use the value of 'VAR_S' from the current environment." + } + ] + } + }, + "principalId": { + "value": "${AZURE_PRINCIPAL_ID}" + } + } +} \ No newline at end of file diff --git a/infra/modules/account/main.bicep b/infra/old/08-2025/modules/account/main.bicep similarity index 100% rename from infra/modules/account/main.bicep rename to infra/old/08-2025/modules/account/main.bicep diff --git a/infra/modules/account/modules/dependencies.bicep b/infra/old/08-2025/modules/account/modules/dependencies.bicep similarity index 100% rename from infra/modules/account/modules/dependencies.bicep rename to infra/old/08-2025/modules/account/modules/dependencies.bicep diff --git a/infra/modules/account/modules/keyVaultExport.bicep b/infra/old/08-2025/modules/account/modules/keyVaultExport.bicep similarity index 100% rename from infra/modules/account/modules/keyVaultExport.bicep rename to infra/old/08-2025/modules/account/modules/keyVaultExport.bicep diff --git a/infra/modules/account/modules/project.bicep b/infra/old/08-2025/modules/account/modules/project.bicep similarity index 100% rename from infra/modules/account/modules/project.bicep rename to infra/old/08-2025/modules/account/modules/project.bicep diff --git a/infra/modules/ai-hub.bicep b/infra/old/08-2025/modules/ai-hub.bicep similarity index 100% rename from infra/modules/ai-hub.bicep rename to infra/old/08-2025/modules/ai-hub.bicep diff --git a/infra/modules/container-app-environment.bicep b/infra/old/08-2025/modules/container-app-environment.bicep similarity index 100% rename from infra/modules/container-app-environment.bicep rename to infra/old/08-2025/modules/container-app-environment.bicep diff --git a/infra/modules/fetch-container-image.bicep b/infra/old/08-2025/modules/fetch-container-image.bicep similarity index 100% rename from infra/modules/fetch-container-image.bicep rename to infra/old/08-2025/modules/fetch-container-image.bicep diff --git a/infra/modules/role.bicep b/infra/old/08-2025/modules/role.bicep similarity index 100% rename from infra/modules/role.bicep rename to infra/old/08-2025/modules/role.bicep From 0e9726289109921dfc2ea8738a148bd94925b1ac Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Mon, 11 Aug 2025 15:17:12 +0530 Subject: [PATCH 02/29] Refactor Azure credential retrieval to use AZURE_CLIENT_ID across multiple modules and update dependencies in pyproject.toml --- infra/main.bicep | 51 +++++++++++++++------ src/backend/app_config.py | 4 +- src/backend/config_kernel.py | 2 +- src/backend/context/cosmos_memory_kernel.py | 2 +- src/backend/pyproject.toml | 1 + src/backend/utils_kernel.py | 2 +- src/backend/uv.lock | 44 +++++++++++++----- 7 files changed, 75 insertions(+), 31 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index fc3cb1689..5b72df01c 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -30,13 +30,20 @@ param solutionUniqueText string = take(uniqueString(subscription().id, resourceG 'westeurope' 'uksouth' ]) -param location string = 'australiaeast' +param location string // Restricting deployment to only supported Azure OpenAI regions validated with GPT-4o model @allowed(['australiaeast', 'eastus2', 'francecentral', 'japaneast', 'norwayeast', 'swedencentral', 'uksouth', 'westus']) -@metadata({ azd: { type: 'location' } }) +@metadata({ + azd : { + type: 'location' + usageName : [ + 'OpenAI.GlobalStandard.gpt-4o, 150' + ] + } +}) @description('Optional. Location for all AI service resources. This should be one of the supported Azure AI Service locations.') -param azureAiServiceLocation string = 'australiaeast' +param azureAiServiceLocation string @description('Optional. The tags to apply to all deployed Azure resources.') param tags resourceInput<'Microsoft.Resources/resourceGroups@2025-04-01'>.tags = {} @@ -62,13 +69,13 @@ param virtualMachineAdminUsername string = take(newGuid(), 20) param virtualMachineAdminPassword string = newGuid() @description('Optional. The Container Registry hostname where the docker images for the backend are located.') -param backendContainerRegistryHostname string = 'biabcontainerreg.azurecr.io' +param backendContainerRegistryHostname string = 'macaer.azurecr.io' @description('Optional. The Container Image Name to deploy on the backend.') param backendContainerImageName string = 'macaebackend' @description('Optional. The Container Image Tag to deploy on the backend.') -param backendContainerImageTag string = 'latest_2025-07-22_895' +param backendContainerImageTag string = 'dev' @description('Optional. The Container Registry hostname where the docker images for the frontend are located.') param frontendContainerRegistryHostname string = 'biabcontainerreg.azurecr.io' @@ -77,7 +84,7 @@ param frontendContainerRegistryHostname string = 'biabcontainerreg.azurecr.io' param frontendContainerImageName string = 'macaefrontend' @description('Optional. The Container Image Tag to deploy on the frontend.') -param frontendContainerImageTag string = 'latest_2025-07-22_895' +param frontendContainerImageTag string = 'latest' @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true @@ -1038,6 +1045,10 @@ var cosmosDbResourceName = 'cosmos-${solutionSuffix}' var cosmosDbDatabaseName = 'macae' var cosmosDbDatabaseMemoryContainerName = 'memory' +resource sqlContributorRoleDefinition 'Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions@2024-11-15' existing = { + name: '${cosmosDbResourceName}/00000000-0000-0000-0000-000000000002' +} + //TODO: update to latest version of AVM module module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { name: take('avm.res.document-db.database-account.${cosmosDbResourceName}', 64) @@ -1062,16 +1073,22 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { ] } ] - dataPlaneRoleDefinitions: [ + // dataPlaneRoleDefinitions: [ + // { + // // Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor + // roleName: 'Cosmos DB SQL Data Contributor' + // dataActions: [ + // 'Microsoft.DocumentDB/databaseAccounts/readMetadata' + // 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' + // 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' + // ] + // assignments: [{ principalId: userAssignedIdentity.outputs.principalId }] + // } + // ] + dataPlaneRoleAssignments: [ { - // Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor - roleName: 'Cosmos DB SQL Data Contributor' - dataActions: [ - 'Microsoft.DocumentDB/databaseAccounts/readMetadata' - 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' - 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' - ] - assignments: [{ principalId: userAssignedIdentity.outputs.principalId }] + principalId: userAssignedIdentity.outputs.principalId + roleDefinitionId: sqlContributorRoleDefinition.id } ] // WAF aligned configuration for Monitoring @@ -1331,6 +1348,10 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' value: aiFoundryAiServicesModelDeployment.name } + { + name: 'AZURE_CLIENT_ID' + value: userAssignedIdentity.outputs.clientId // NOTE: This is the client ID of the managed identity, not the Entra application, and is needed for the App Service to access the Cosmos DB account. + } ] } ] diff --git a/src/backend/app_config.py b/src/backend/app_config.py index fe2b9f90c..0f2871967 100644 --- a/src/backend/app_config.py +++ b/src/backend/app_config.py @@ -115,7 +115,7 @@ def get_cosmos_database_client(self): try: if self._cosmos_client is None: self._cosmos_client = CosmosClient( - self.COSMOSDB_ENDPOINT, credential=get_azure_credential() + self.COSMOSDB_ENDPOINT, credential=get_azure_credential(self.AZURE_CLIENT_ID) ) if self._cosmos_database is None: @@ -152,7 +152,7 @@ def get_ai_project_client(self): return self._ai_project_client try: - credential = get_azure_credential() + credential = get_azure_credential(self.AZURE_CLIENT_ID) if credential is None: raise RuntimeError( "Unable to acquire Azure credentials; ensure Managed Identity is configured" diff --git a/src/backend/config_kernel.py b/src/backend/config_kernel.py index 598a88dc5..3fb92c1f0 100644 --- a/src/backend/config_kernel.py +++ b/src/backend/config_kernel.py @@ -32,7 +32,7 @@ class Config: @staticmethod def GetAzureCredentials(): """Get Azure credentials using the AppConfig implementation.""" - return get_azure_credential() + return get_azure_credential(config.AZURE_CLIENT_ID) @staticmethod def GetCosmosDatabaseClient(): diff --git a/src/backend/context/cosmos_memory_kernel.py b/src/backend/context/cosmos_memory_kernel.py index d547979da..e20cae00a 100644 --- a/src/backend/context/cosmos_memory_kernel.py +++ b/src/backend/context/cosmos_memory_kernel.py @@ -73,7 +73,7 @@ async def initialize(self): if not self._database: # Create Cosmos client cosmos_client = CosmosClient( - self._cosmos_endpoint, credential=get_azure_credential() + self._cosmos_endpoint, credential=get_azure_credential(config.AZURE_CLIENT_ID) ) self._database = cosmos_client.get_database_client( self._cosmos_database diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index e02186fdb..ba41839b0 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -8,6 +8,7 @@ dependencies = [ "azure-ai-evaluation>=1.5.0", "azure-ai-inference>=1.0.0b9", "azure-ai-projects>=1.0.0b9", + "azure-ai-agents>=1.2.0b1", "azure-cosmos>=4.9.0", "azure-identity>=1.21.0", "azure-monitor-events-extension>=0.1.0", diff --git a/src/backend/utils_kernel.py b/src/backend/utils_kernel.py index b6398ae2c..37753d171 100644 --- a/src/backend/utils_kernel.py +++ b/src/backend/utils_kernel.py @@ -172,7 +172,7 @@ async def rai_success(description: str, is_task_creation: bool) -> bool: """ try: # Use managed identity for authentication to Azure OpenAI - credential = get_azure_credential() + credential = get_azure_credential(config.AZURE_CLIENT_ID) access_token = credential.get_token( "https://cognitiveservices.azure.com/.default" ).token diff --git a/src/backend/uv.lock b/src/backend/uv.lock index 61b0afada..f2b09d240 100644 --- a/src/backend/uv.lock +++ b/src/backend/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.11" resolution-markers = [ "python_full_version >= '3.13'", @@ -224,6 +224,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/c0/44232f2e04358ecce33a1d9354f95683bb24262a788d008d8c9dafa3622d/av-14.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:f930faa2e6f6a46d55bc67545b81f5b22bd52975679c1de0f871fc9f8ca95711", size = 27433259, upload-time = "2025-04-06T10:21:53.567Z" }, ] +[[package]] +name = "azure-ai-agents" +version = "1.2.0b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-core" }, + { name = "isodate" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/70/0aa275a7eecead1691bd86474514bc28787f815c37d1d79ac78be03a7612/azure_ai_agents-1.2.0b1.tar.gz", hash = "sha256:914e08e553ea4379d41ad60dbc8ea5468311d97f0ae1a362686229b8565ab8dd", size = 339933, upload-time = "2025-08-05T22:21:07.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/c2/4824f3cd3980f976c4dace59cb25ab1891b22626be5c80c4a96f0b9c0ba5/azure_ai_agents-1.2.0b1-py3-none-any.whl", hash = "sha256:c6862f2e6655072ee3f1f1489be2dc2bf6c0ad636ec4e7f33a5fca9cb5c8eadb", size = 202032, upload-time = "2025-08-05T22:21:08.668Z" }, +] + [[package]] name = "azure-ai-evaluation" version = "1.5.0" @@ -263,16 +277,18 @@ wheels = [ [[package]] name = "azure-ai-projects" -version = "1.0.0b10" +version = "1.1.0b2" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "azure-ai-agents" }, { name = "azure-core" }, + { name = "azure-storage-blob" }, { name = "isodate" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/2e/e6ab1f7c1b12fcef9549a797a575e3dd5a71297ce12b083a983311cd5069/azure_ai_projects-1.0.0b10.tar.gz", hash = "sha256:cdc8055305cec762f09f7581796ea97599d2a2fb26f2c8486f34f728d5bdc98a", size = 323251, upload-time = "2025-04-23T21:56:56.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/17/33664227381ff59690e16a8d3261c9edeb80d88acdb24b717733d63529bb/azure_ai_projects-1.1.0b2.tar.gz", hash = "sha256:79432e2de8b27f01aaad6d3f12e1549396f1c2a022665a859c45b179bf6ff228", size = 144848, upload-time = "2025-08-05T22:18:45.351Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/7c/e45b98dc298a706ac639064aec316730a534d0d49d27986d00ba4e23dced/azure_ai_projects-1.0.0b10-py3-none-any.whl", hash = "sha256:77cd7fdac5affc37c437e60f1e244a706c1151b1bf682c5a471b3d233978b647", size = 200755, upload-time = "2025-04-23T21:56:58.032Z" }, + { url = "https://files.pythonhosted.org/packages/26/2b/98f928ea41c03c78c02e1a72fc5e9c900d2e6e472cb51f9272cb0d4ba3bf/azure_ai_projects-1.1.0b2-py3-none-any.whl", hash = "sha256:3a4ecc6de6ab27a75b4c8228cd8162c9853fd1432e77746792b0ee2088c775db", size = 125301, upload-time = "2025-08-05T22:18:46.577Z" }, ] [[package]] @@ -429,6 +445,7 @@ name = "backend" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "azure-ai-agents" }, { name = "azure-ai-evaluation" }, { name = "azure-ai-inference" }, { name = "azure-ai-projects" }, @@ -456,6 +473,7 @@ dependencies = [ [package.metadata] requires-dist = [ + { name = "azure-ai-agents", specifier = ">=1.2.0b1" }, { name = "azure-ai-evaluation", specifier = ">=1.5.0" }, { name = "azure-ai-inference", specifier = ">=1.0.0b9" }, { name = "azure-ai-projects", specifier = ">=1.0.0b9" }, @@ -477,7 +495,7 @@ requires-dist = [ { name = "pytest-cov", specifier = "==5.0.0" }, { name = "python-dotenv", specifier = ">=1.1.0" }, { name = "python-multipart", specifier = ">=0.0.20" }, - { name = "semantic-kernel", specifier = ">=1.28.1" }, + { name = "semantic-kernel", specifier = ">=1.32.2" }, { name = "uvicorn", specifier = ">=0.34.2" }, ] @@ -1634,7 +1652,7 @@ wheels = [ [[package]] name = "openai" -version = "1.76.2" +version = "1.99.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -1646,9 +1664,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d5/48/e767710b07acc1fca1f6b8cacd743102c71b8fdeca603876de0749ec00f1/openai-1.76.2.tar.gz", hash = "sha256:f430c8b848775907405c6eff54621254c96f6444c593c097e0cc3a9f8fdda96f", size = 434922, upload-time = "2025-04-29T20:02:56.294Z" } +sdist = { url = "https://files.pythonhosted.org/packages/11/45/38a87bd6949236db5ae3132f41d5861824702b149f86d2627d6900919103/openai-1.99.6.tar.gz", hash = "sha256:f48f4239b938ef187062f3d5199a05b69711d8b600b9a9b6a3853cd271799183", size = 505364, upload-time = "2025-08-09T15:20:54.438Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/5f/aecb820917e93ca9fcac408e998dc22ee0561c308ed58dc8f328e3f7ef14/openai-1.76.2-py3-none-any.whl", hash = "sha256:9c1d9ad59e6e3bea7205eedc9ca66eeebae18d47b527e505a2b0d2fb1538e26e", size = 661253, upload-time = "2025-04-29T20:02:54.362Z" }, + { url = "https://files.pythonhosted.org/packages/d6/dd/9aa956485c2856346b3181542fbb0aea4e5b457fa7a523944726746da8da/openai-1.99.6-py3-none-any.whl", hash = "sha256:e40d44b2989588c45ce13819598788b77b8fb80ba2f7ae95ce90d14e46f1bd26", size = 786296, upload-time = "2025-08-09T15:20:51.95Z" }, ] [[package]] @@ -2939,11 +2957,13 @@ wheels = [ [[package]] name = "semantic-kernel" -version = "1.29.0" +version = "1.35.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, { name = "aiortc" }, + { name = "azure-ai-agents" }, + { name = "azure-ai-projects" }, { name = "azure-identity" }, { name = "cloudevents" }, { name = "defusedxml" }, @@ -2955,15 +2975,17 @@ dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, { name = "prance" }, + { name = "protobuf" }, { name = "pybars4" }, { name = "pydantic" }, { name = "pydantic-settings" }, { name = "scipy" }, + { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/51/fb/f12134e866867396d7706f9dff232900ec682240c8c646aab37f02479ef8/semantic_kernel-1.29.0.tar.gz", hash = "sha256:7a8e9da374c7ecc58f17aceda104d89aa35b8f5e21d080c2839a93c5b8c94450", size = 498588, upload-time = "2025-04-28T23:41:51.243Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/06/a6cad34440265222c8a709ed576067ecc1781c5255e89307174b993afc0f/semantic_kernel-1.35.2.tar.gz", hash = "sha256:e7c22aa3e3b17087040800a277999a6675f450cce971dee411982038e9bf8edd", size = 573355, upload-time = "2025-08-08T01:28:51.974Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/86/89e844020fbd0d37a2c60da611e2c3ee05fbf8dc0b38993cf804cc3c12d9/semantic_kernel-1.29.0-py3-none-any.whl", hash = "sha256:5157fb617ad5c069822db62906957396521d8813c24ce2057e7f652c53c88edf", size = 818108, upload-time = "2025-04-28T23:41:53.285Z" }, + { url = "https://files.pythonhosted.org/packages/c1/cb/65e32b06b247c40b566cddf74a879042a1910e46f29472b8fb7b690824d5/semantic_kernel-1.35.2-py3-none-any.whl", hash = "sha256:5cf58809e67bb398b3eda053801c5aa48714bf9986852b1e8c41f4eac08e6941", size = 881396, upload-time = "2025-08-08T01:28:49.962Z" }, ] [[package]] From 9d6ecbd094b9fc2b8126fb78af296c45e2e5f6de Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Tue, 12 Aug 2025 14:27:42 +0530 Subject: [PATCH 03/29] Refactor Cosmos DB role definitions and assignments for clarity and compliance with Azure standards --- infra/main.bicep | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index 5b72df01c..3fedf78cb 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -1045,10 +1045,6 @@ var cosmosDbResourceName = 'cosmos-${solutionSuffix}' var cosmosDbDatabaseName = 'macae' var cosmosDbDatabaseMemoryContainerName = 'memory' -resource sqlContributorRoleDefinition 'Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions@2024-11-15' existing = { - name: '${cosmosDbResourceName}/00000000-0000-0000-0000-000000000002' -} - //TODO: update to latest version of AVM module module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { name: take('avm.res.document-db.database-account.${cosmosDbResourceName}', 64) @@ -1073,22 +1069,16 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { ] } ] - // dataPlaneRoleDefinitions: [ - // { - // // Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor - // roleName: 'Cosmos DB SQL Data Contributor' - // dataActions: [ - // 'Microsoft.DocumentDB/databaseAccounts/readMetadata' - // 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' - // 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' - // ] - // assignments: [{ principalId: userAssignedIdentity.outputs.principalId }] - // } - // ] - dataPlaneRoleAssignments: [ + dataPlaneRoleDefinitions: [ { - principalId: userAssignedIdentity.outputs.principalId - roleDefinitionId: sqlContributorRoleDefinition.id + // Cosmos DB Built-in Data Contributor: https://docs.azure.cn/en-us/cosmos-db/nosql/security/reference-data-plane-roles#cosmos-db-built-in-data-contributor + roleName: 'Cosmos DB SQL Data Contributor' + dataActions: [ + 'Microsoft.DocumentDB/databaseAccounts/readMetadata' + 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*' + 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*' + ] + assignments: [{ principalId: userAssignedIdentity.outputs.principalId }] } ] // WAF aligned configuration for Monitoring From 240f5cf59e77a7e07d5924aef80c4b91908244d4 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Wed, 13 Aug 2025 12:48:40 +0530 Subject: [PATCH 04/29] Merge all the changes from main --- docs/DeploymentGuide.md | 49 +++++------------- .../azure_ai_foundry_list.png | Bin 0 -> 339436 bytes .../navigate_to_projects.png | Bin 0 -> 97180 bytes .../project_resource_id.png | Bin 0 -> 200850 bytes docs/re-use-foundry-project.md | 44 ++++++++++++++++ docs/re-use-log-analytics.md | 4 +- src/backend/app_kernel.py | 6 +-- src/backend/pyproject.toml | 1 + src/backend/uv.lock | 38 +++++++++++--- 9 files changed, 92 insertions(+), 50 deletions(-) create mode 100644 docs/images/re_use_foundry_project/azure_ai_foundry_list.png create mode 100644 docs/images/re_use_foundry_project/navigate_to_projects.png create mode 100644 docs/images/re_use_foundry_project/project_resource_id.png create mode 100644 docs/re-use-foundry-project.md diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index 362c64c5a..18442dfc7 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -153,7 +153,8 @@ When you start the deployment, most parameters will have **default values**, but | **GPT Model Capacity** | Sets the GPT model capacity. | 150 | | **Image Tag** | Docker image tag used for container deployments. | latest | | **Enable Telemetry** | Enables telemetry for monitoring and diagnostics. | true | - +| **Existing Log Analytics Workspace** | To reuse an existing Log Analytics Workspace ID instead of creating a new one. | *(none)* | +| **Existing Azure AI Foundry Project** | To reuse an existing Azure AI Foundry Project ID instead of creating a new one. | *(none)* | @@ -176,6 +177,14 @@ To adjust quota settings, follow these [steps](./AzureGPTQuotaSettings.md). +
+ + Reusing an Existing Azure AI Foundry Project + + Guide to get your [Existing Project ID](/docs/re-use-foundry-project.md) + +
+ ### Deploying with AZD Once you've opened the project in [Codespaces](#github-codespaces), [Dev Containers](#vs-code-dev-containers), or [locally](#local-environment), you can deploy it to Azure by following these steps: @@ -206,43 +215,9 @@ Once you've opened the project in [Codespaces](#github-codespaces), [Dev Contain 5. Once the deployment has completed successfully, open the [Azure Portal](https://portal.azure.com/), go to the deployed resource group, find the App Service, and get the app URL from `Default domain`. -6. If you are done trying out the application, you can delete the resources by running `azd down`. - -### Publishing Local Build Container to Azure Container Registry - -If you need to rebuild the source code and push the updated container to the deployed Azure Container Registry, follow these steps: - -1. Set the environment variable `USE_LOCAL_BUILD` to `True`: - - - **Linux/macOS**: - - ```bash - export USE_LOCAL_BUILD=True - ``` - - - **Windows (PowerShell)**: - ```powershell - $env:USE_LOCAL_BUILD = $true - ``` - -2. Run the `az login` command - - ```bash - az login - ``` - -3. Run the `azd up` command again to rebuild and push the updated container: - ```bash - azd up - ``` - -This will rebuild the source code, package it into a container, and push it to the Azure Container Registry associated with your deployment. - -This guide provides step-by-step instructions for deploying your application using Azure Container Registry (ACR) and Azure Container Apps. - -There are several ways to deploy the solution. You can deploy to run in Azure in one click, or manually, or you can deploy locally. +6. When Deployment is complete, follow steps in [Set Up Authentication in Azure App Service](../docs/azure_app_service_auth_setup.md) to add app authentication to your web app running on Azure App Service -When Deployment is complete, follow steps in [Set Up Authentication in Azure App Service](../docs/azure_app_service_auth_setup.md) to add app authentication to your web app running on Azure App Service +7. If you are done trying out the application, you can delete the resources by running `azd down`. # Local setup diff --git a/docs/images/re_use_foundry_project/azure_ai_foundry_list.png b/docs/images/re_use_foundry_project/azure_ai_foundry_list.png new file mode 100644 index 0000000000000000000000000000000000000000..784bc85c74c188f7e647fba807fd3157bf191273 GIT binary patch literal 339436 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 z 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

ja1gw1j{sEZJuZtRXDwl%- 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 literal 0 HcmV?d00001 diff --git a/docs/images/re_use_foundry_project/navigate_to_projects.png b/docs/images/re_use_foundry_project/navigate_to_projects.png new file mode 100644 index 0000000000000000000000000000000000000000..11082c15c95c2c0b85ed5a9974670b6ee6d2d0cd GIT binary patch literal 97180 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ଊK$F?alhEbLTmRA}GGS0rT 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

a*UF{M8N^YKeJe)}thN9azY^#qNIp&on#iZv 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 GuKf@1N=y>~ literal 0 HcmV?d00001 diff --git a/docs/re-use-foundry-project.md b/docs/re-use-foundry-project.md new file mode 100644 index 000000000..c29ac5d8a --- /dev/null +++ b/docs/re-use-foundry-project.md @@ -0,0 +1,44 @@ +[← Back to *DEPLOYMENT* guide](/docs/DeploymentGuide.md#deployment-steps) + +# Reusing an Existing Azure AI Foundry Project +To configure your environment to use an existing Azure AI Foundry Project, follow these steps: +--- +### 1. Go to Azure Portal +Go to https://portal.azure.com + +### 2. Search for Azure AI Foundry +In the search bar at the top, type "Azure AI Foundry" and click on it. Then select the Foundry service instance where your project exists. + +![alt text](../docs/images/re_use_foundry_project/azure_ai_foundry_list.png) + +### 3. Navigate to Projects under Resource Management +On the left sidebar of the Foundry service blade: + +- Expand the Resource Management section +- Click on Projects (this refers to the active Foundry project tied to the service) + +### 4. Click on the Project +From the Projects view: Click on the project name to open its details + + Note: You will see only one project listed here, as each Foundry service maps to a single project in this accelerator + +![alt text](../docs/images/re_use_foundry_project/navigate_to_projects.png) + +### 5. Copy Resource ID +In the left-hand menu of the project blade: + +- Click on Properties under Resource Management +- Locate the Resource ID field +- Click on the copy icon next to the Resource ID value + +![alt text](../docs/images/re_use_foundry_project/project_resource_id.png) + +### 6. Set the Foundry Project Resource ID in Your Environment +Run the following command in your terminal +```bash +azd env set AZURE_ENV_FOUNDRY_PROJECT_ID '' +``` +Replace `` with the value obtained from Step 5. + +### 7. Continue Deployment +Proceed with the next steps in the [deployment guide](/docs/DeploymentGuide.md#deployment-steps). diff --git a/docs/re-use-log-analytics.md b/docs/re-use-log-analytics.md index 9d48b0f92..1fa7a35df 100644 --- a/docs/re-use-log-analytics.md +++ b/docs/re-use-log-analytics.md @@ -1,4 +1,4 @@ -[← Back to *DEPLOYMENT* guide](/docs/DeploymentGuide.md#deployment-options--steps) +[← Back to *DEPLOYMENT* guide](/docs/DeploymentGuide.md#deployment-steps) # Reusing an Existing Log Analytics Workspace To configure your environment to use an existing Log Analytics Workspace, follow these steps: @@ -28,4 +28,4 @@ azd env set AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID '` with the value obtained from Step 3. ### 5. Continue Deployment -Proceed with the next steps in the [deployment guide](/docs/DeploymentGuide.md#deployment-options--steps). +Proceed with the next steps in the [deployment guide](/docs/DeploymentGuide.md#deployment-steps). diff --git a/src/backend/app_kernel.py b/src/backend/app_kernel.py index e0e81abd1..0c0273b45 100644 --- a/src/backend/app_kernel.py +++ b/src/backend/app_kernel.py @@ -74,7 +74,7 @@ # Add this near the top of your app.py, after initializing the app app.add_middleware( CORSMiddleware, - allow_origins=[frontend_url], + allow_origins=[frontend_url], # Allow all origins for development; restrict in production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], @@ -269,7 +269,7 @@ async def input_task_endpoint(input_task: InputTask, request: Request): if "Rate limit is exceeded" in error_msg: match = re.search(r"Rate limit is exceeded\. Try again in (\d+) seconds?\.", error_msg) if match: - error_msg = f"Rate limit is exceeded. Try again in {match.group(1)} seconds." + error_msg = "Application temporarily unavailable due to quota limits. Please try again later." track_event_if_configured( "InputTaskError", @@ -279,7 +279,7 @@ async def input_task_endpoint(input_task: InputTask, request: Request): "error": str(e), }, ) - raise HTTPException(status_code=400, detail=f"Error creating plan: {error_msg}") from e + raise HTTPException(status_code=400, detail=f"{error_msg}") from e @app.post("/api/human_feedback") diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml index e02186fdb..ba41839b0 100644 --- a/src/backend/pyproject.toml +++ b/src/backend/pyproject.toml @@ -8,6 +8,7 @@ dependencies = [ "azure-ai-evaluation>=1.5.0", "azure-ai-inference>=1.0.0b9", "azure-ai-projects>=1.0.0b9", + "azure-ai-agents>=1.2.0b1", "azure-cosmos>=4.9.0", "azure-identity>=1.21.0", "azure-monitor-events-extension>=0.1.0", diff --git a/src/backend/uv.lock b/src/backend/uv.lock index 61b0afada..2f9a6fc21 100644 --- a/src/backend/uv.lock +++ b/src/backend/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.11" resolution-markers = [ "python_full_version >= '3.13'", @@ -224,6 +224,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5b/c0/44232f2e04358ecce33a1d9354f95683bb24262a788d008d8c9dafa3622d/av-14.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:f930faa2e6f6a46d55bc67545b81f5b22bd52975679c1de0f871fc9f8ca95711", size = 27433259, upload-time = "2025-04-06T10:21:53.567Z" }, ] +[[package]] +name = "azure-ai-agents" +version = "1.2.0b1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "azure-core" }, + { name = "isodate" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/70/0aa275a7eecead1691bd86474514bc28787f815c37d1d79ac78be03a7612/azure_ai_agents-1.2.0b1.tar.gz", hash = "sha256:914e08e553ea4379d41ad60dbc8ea5468311d97f0ae1a362686229b8565ab8dd", size = 339933, upload-time = "2025-08-05T22:21:07.262Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/c2/4824f3cd3980f976c4dace59cb25ab1891b22626be5c80c4a96f0b9c0ba5/azure_ai_agents-1.2.0b1-py3-none-any.whl", hash = "sha256:c6862f2e6655072ee3f1f1489be2dc2bf6c0ad636ec4e7f33a5fca9cb5c8eadb", size = 202032, upload-time = "2025-08-05T22:21:08.668Z" }, +] + [[package]] name = "azure-ai-evaluation" version = "1.5.0" @@ -263,16 +277,18 @@ wheels = [ [[package]] name = "azure-ai-projects" -version = "1.0.0b10" +version = "1.1.0b2" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "azure-ai-agents" }, { name = "azure-core" }, + { name = "azure-storage-blob" }, { name = "isodate" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/2e/e6ab1f7c1b12fcef9549a797a575e3dd5a71297ce12b083a983311cd5069/azure_ai_projects-1.0.0b10.tar.gz", hash = "sha256:cdc8055305cec762f09f7581796ea97599d2a2fb26f2c8486f34f728d5bdc98a", size = 323251, upload-time = "2025-04-23T21:56:56.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/17/33664227381ff59690e16a8d3261c9edeb80d88acdb24b717733d63529bb/azure_ai_projects-1.1.0b2.tar.gz", hash = "sha256:79432e2de8b27f01aaad6d3f12e1549396f1c2a022665a859c45b179bf6ff228", size = 144848, upload-time = "2025-08-05T22:18:45.351Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/7c/e45b98dc298a706ac639064aec316730a534d0d49d27986d00ba4e23dced/azure_ai_projects-1.0.0b10-py3-none-any.whl", hash = "sha256:77cd7fdac5affc37c437e60f1e244a706c1151b1bf682c5a471b3d233978b647", size = 200755, upload-time = "2025-04-23T21:56:58.032Z" }, + { url = "https://files.pythonhosted.org/packages/26/2b/98f928ea41c03c78c02e1a72fc5e9c900d2e6e472cb51f9272cb0d4ba3bf/azure_ai_projects-1.1.0b2-py3-none-any.whl", hash = "sha256:3a4ecc6de6ab27a75b4c8228cd8162c9853fd1432e77746792b0ee2088c775db", size = 125301, upload-time = "2025-08-05T22:18:46.577Z" }, ] [[package]] @@ -429,6 +445,7 @@ name = "backend" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "azure-ai-agents" }, { name = "azure-ai-evaluation" }, { name = "azure-ai-inference" }, { name = "azure-ai-projects" }, @@ -456,6 +473,7 @@ dependencies = [ [package.metadata] requires-dist = [ + { name = "azure-ai-agents", specifier = ">=1.2.0b1" }, { name = "azure-ai-evaluation", specifier = ">=1.5.0" }, { name = "azure-ai-inference", specifier = ">=1.0.0b9" }, { name = "azure-ai-projects", specifier = ">=1.0.0b9" }, @@ -477,7 +495,7 @@ requires-dist = [ { name = "pytest-cov", specifier = "==5.0.0" }, { name = "python-dotenv", specifier = ">=1.1.0" }, { name = "python-multipart", specifier = ">=0.0.20" }, - { name = "semantic-kernel", specifier = ">=1.28.1" }, + { name = "semantic-kernel", specifier = ">=1.32.2" }, { name = "uvicorn", specifier = ">=0.34.2" }, ] @@ -2939,11 +2957,13 @@ wheels = [ [[package]] name = "semantic-kernel" -version = "1.29.0" +version = "1.35.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, { name = "aiortc" }, + { name = "azure-ai-agents" }, + { name = "azure-ai-projects" }, { name = "azure-identity" }, { name = "cloudevents" }, { name = "defusedxml" }, @@ -2955,15 +2975,17 @@ dependencies = [ { name = "opentelemetry-api" }, { name = "opentelemetry-sdk" }, { name = "prance" }, + { name = "protobuf" }, { name = "pybars4" }, { name = "pydantic" }, { name = "pydantic-settings" }, { name = "scipy" }, + { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/51/fb/f12134e866867396d7706f9dff232900ec682240c8c646aab37f02479ef8/semantic_kernel-1.29.0.tar.gz", hash = "sha256:7a8e9da374c7ecc58f17aceda104d89aa35b8f5e21d080c2839a93c5b8c94450", size = 498588, upload-time = "2025-04-28T23:41:51.243Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/5c/4d761ff412c211260415f0e6683d22139b4ab990d9010c9962d1ec35d1b8/semantic_kernel-1.35.0.tar.gz", hash = "sha256:7fe49faaf7086263d3ac4cb42ec5d0b2344dcc21f0759bd6b79a92a7b4f8533f", size = 572339, upload-time = "2025-07-16T00:33:47.948Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/86/89e844020fbd0d37a2c60da611e2c3ee05fbf8dc0b38993cf804cc3c12d9/semantic_kernel-1.29.0-py3-none-any.whl", hash = "sha256:5157fb617ad5c069822db62906957396521d8813c24ce2057e7f652c53c88edf", size = 818108, upload-time = "2025-04-28T23:41:53.285Z" }, + { url = "https://files.pythonhosted.org/packages/b0/14/b0ddf679dae28393cf068401e8f953602adf78d1fe17504479ddf9f7afdf/semantic_kernel-1.35.0-py3-none-any.whl", hash = "sha256:ce2b9c313d53841448059833e885f082d136c54a113e687359b14c5e358c0e66", size = 875792, upload-time = "2025-07-16T00:33:45.891Z" }, ] [[package]] From 422c8fb6d8bbd15a610b3f8347f7295c356bbcab Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Wed, 13 Aug 2025 19:04:49 +0530 Subject: [PATCH 05/29] Added more parameters --- infra/main.bicep | 29 +++++++++++++++++++++-------- infra/main.parameters.json | 14 +++++++++++++- infra/main.waf.parameters.json | 14 +++++++++++++- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index a76d39505..7952dbf20 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -42,8 +42,22 @@ param location string ] } }) -@description('Optional. Location for all AI service resources. This should be one of the supported Azure AI Service locations.') -param azureAiServiceLocation string +@description('Required. Location for all AI service resources. This should be one of the supported Azure AI Service locations.') +param aiDeploymentsLocation string + +@minLength(1) +@description('Optional. Name of the GPT model to deploy:') +param gptModelName string = 'gpt-4o' + +@description('Optional. Version of the GPT model to deploy. Defaults to 2024-08-06.') +param gptModelVersion string = '2024-08-06' + +@minLength(1) +@description('Optional. GPT model deployment type. Defaults to GlobalStandard.') +param modelDeploymentType string = 'GlobalStandard' + +@description('Optional. AI model deployment token capacity. Defaults to 150 for optimal performance.') +param gptModelCapacity int = 150 @description('Optional. The tags to apply to all deployed Azure resources.') param tags resourceInput<'Microsoft.Resources/resourceGroups@2025-04-01'>.tags = {} @@ -910,12 +924,11 @@ var aiFoundryAiServicesAiProjectResourceName = 'proj-${solutionSuffix}' var aiFoundryAIservicesEnabled = true var aiFoundryAiServicesModelDeployment = { format: 'OpenAI' - name: 'gpt-4o' - version: '2024-08-06' + name: gptModelName + version: gptModelVersion sku: { - name: 'GlobalStandard' - //Currently the capacity is set to 140 for optimal performance. - capacity: 140 + name: modelDeploymentType + capacity: gptModelCapacity } raiPolicyName: 'Microsoft.Default' } @@ -925,7 +938,7 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) params: { name: aiFoundryAiServicesResourceName - location: azureAiServiceLocation + location: aiDeploymentsLocation tags: tags projectName: aiFoundryAiServicesAiProjectResourceName projectDescription: 'AI Foundry Project' diff --git a/infra/main.parameters.json b/infra/main.parameters.json index c52f902ee..5f1964754 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -8,9 +8,21 @@ "location": { "value": "${AZURE_LOCATION}" }, - "azureAiServiceLocation": { + "aiDeploymentsLocation": { "value": "${AZURE_ENV_OPENAI_LOCATION}" }, + "modelDeploymentType": { + "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" + }, + "gptModelName": { + "value": "${AZURE_ENV_MODEL_NAME}" + }, + "gptModelVersion": { + "value": "${AZURE_ENV_MODEL_VERSION}" + }, + "gptModelCapacity": { + "value": "${AZURE_ENV_MODEL_CAPACITY}" + }, "backendContainerImageTag": { "value": "${AZURE_ENV_IMAGE_TAG}" }, diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json index c4b7d5ddc..d540db23c 100644 --- a/infra/main.waf.parameters.json +++ b/infra/main.waf.parameters.json @@ -11,9 +11,21 @@ "location": { "value": "${AZURE_LOCATION}" }, - "azureAiServiceLocation": { + "aiDeploymentsLocation": { "value": "${AZURE_ENV_OPENAI_LOCATION}" }, + "modelDeploymentType": { + "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" + }, + "gptModelName": { + "value": "${AZURE_ENV_MODEL_NAME}" + }, + "gptModelVersion": { + "value": "${AZURE_ENV_MODEL_VERSION}" + }, + "gptModelCapacity": { + "value": "${AZURE_ENV_MODEL_CAPACITY}" + }, "backendContainerImageTag": { "value": "${AZURE_ENV_IMAGE_TAG}" }, From 7a0b86bdaa860d7c87c3215cfe9622f4427c6651 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Thu, 14 Aug 2025 18:20:13 +0530 Subject: [PATCH 06/29] Fixes for the command shared by Alvaro --- .github/workflows/deploy-waf.yml | 14 ++++++++------ .github/workflows/deploy.yml | 13 ++++--------- infra/main.bicep | 14 +++++++++----- infra/main.parameters.json | 4 ++-- infra/main.waf.parameters.json | 4 ++-- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/.github/workflows/deploy-waf.yml b/.github/workflows/deploy-waf.yml index 8ec0a5e19..0427638d0 100644 --- a/.github/workflows/deploy-waf.yml +++ b/.github/workflows/deploy-waf.yml @@ -109,13 +109,15 @@ jobs: --resource-group ${{ env.RESOURCE_GROUP_NAME }} \ --template-file infra/main.bicep \ --parameters \ - environmentName=${{ env.SOLUTION_PREFIX }} \ - useWafAlignedArchitecture=true \ - aiDeploymentsLocation='${{ env.AZURE_LOCATION }}' \ + solutionName=${{ env.SOLUTION_PREFIX }} \ + location="${{ env.AZURE_LOCATION }}" \ + azureAiServiceLocation='${{ env.AZURE_LOCATION }}' \ gptModelCapacity=5 \ - virtualMachineConfiguration='{"adminUsername": "adminuser", "adminPassword": "P@ssw0rd1234"}' \ - logAnalyticsWorkspaceConfiguration='{"existingWorkspaceResourceId": ""}' - + enableTelemetry=true \ + enableMonitoring=true \ + enablePrivateNetworking=true \ + enableScalability=true \ + - name: Send Notification on Failure if: failure() diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 747d8de53..82f0941b1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -129,19 +129,14 @@ jobs: --resource-group ${{ env.RESOURCE_GROUP_NAME }} \ --template-file infra/main.bicep \ --parameters \ - environmentName=${{ env.SOLUTION_PREFIX }} \ - solutionLocation="${{ env.AZURE_LOCATION }}" \ - modelDeploymentType="GlobalStandard" \ + solutionName=${{ env.SOLUTION_PREFIX }} \ + location="${{ env.AZURE_LOCATION }}" \ + gptModelDeploymentType="GlobalStandard" \ gptModelName="gpt-4o" \ gptModelVersion="2024-08-06" \ imageTag="${IMAGE_TAG}" \ - useWafAlignedArchitecture=false \ - aiDeploymentsLocation='${{ env.AZURE_LOCATION }}' \ + azureAiServiceLocation='${{ env.AZURE_LOCATION }}' \ gptModelCapacity=150 \ - logAnalyticsWorkspaceConfiguration='{"dataRetentionInDays": 30, "existingWorkspaceResourceId": ""}' \ - applicationInsightsConfiguration='{"retentionInDays": 30}' \ - virtualNetworkConfiguration='{"enabled": false}' \ - webServerFarmConfiguration='{"skuCapacity": 1, "skuName": "B2"}' \ --output json - name: Extract Web App and API App URLs diff --git a/infra/main.bicep b/infra/main.bicep index 7952dbf20..94556f60f 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -43,7 +43,7 @@ param location string } }) @description('Required. Location for all AI service resources. This should be one of the supported Azure AI Service locations.') -param aiDeploymentsLocation string +param azureAiServiceLocation string @minLength(1) @description('Optional. Name of the GPT model to deploy:') @@ -53,8 +53,12 @@ param gptModelName string = 'gpt-4o' param gptModelVersion string = '2024-08-06' @minLength(1) +@allowed([ + 'Standard' + 'GlobalStandard' +]) @description('Optional. GPT model deployment type. Defaults to GlobalStandard.') -param modelDeploymentType string = 'GlobalStandard' +param gptModelDeploymentType string = 'GlobalStandard' @description('Optional. AI model deployment token capacity. Defaults to 150 for optimal performance.') param gptModelCapacity int = 150 @@ -927,7 +931,7 @@ var aiFoundryAiServicesModelDeployment = { name: gptModelName version: gptModelVersion sku: { - name: modelDeploymentType + name: gptModelDeploymentType capacity: gptModelCapacity } raiPolicyName: 'Microsoft.Default' @@ -938,7 +942,7 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) params: { name: aiFoundryAiServicesResourceName - location: aiDeploymentsLocation + location: azureAiServiceLocation tags: tags projectName: aiFoundryAiServicesAiProjectResourceName projectDescription: 'AI Foundry Project' @@ -1169,7 +1173,7 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2 destination: 'log-analytics' logAnalyticsConfiguration: { customerId: logAnalyticsWorkspace!.outputs.logAnalyticsWorkspaceId - sharedKey: logAnalyticsWorkspace!.outputs.primarySharedKey + sharedKey: logAnalyticsWorkspace.outputs.primarySharedKey } } : null diff --git a/infra/main.parameters.json b/infra/main.parameters.json index 5f1964754..0faa4c9ae 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -8,10 +8,10 @@ "location": { "value": "${AZURE_LOCATION}" }, - "aiDeploymentsLocation": { + "azureAiServiceLocation": { "value": "${AZURE_ENV_OPENAI_LOCATION}" }, - "modelDeploymentType": { + "gptModelDeploymentType": { "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" }, "gptModelName": { diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json index d540db23c..66e52ec12 100644 --- a/infra/main.waf.parameters.json +++ b/infra/main.waf.parameters.json @@ -11,10 +11,10 @@ "location": { "value": "${AZURE_LOCATION}" }, - "aiDeploymentsLocation": { + "azureAiServiceLocation": { "value": "${AZURE_ENV_OPENAI_LOCATION}" }, - "modelDeploymentType": { + "gptModelDeploymentType": { "value": "${AZURE_ENV_MODEL_DEPLOYMENT_TYPE}" }, "gptModelName": { From b42f0fddde651fd25258fe78bc37fe0bfadc1a03 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Tue, 19 Aug 2025 18:24:08 +0530 Subject: [PATCH 07/29] Refactor private DNS zone configurations --- infra/main.bicep | 100 ++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 54 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index 94556f60f..d97a0cda6 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -893,21 +893,30 @@ module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.17.0' = if (e } } -// ========== AI Foundry: AI Services ========== // -// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -var openAiSubResource = 'account' -var openAiPrivateDnsZones = { - 'privatelink.cognitiveservices.azure.com': openAiSubResource - 'privatelink.openai.azure.com': openAiSubResource - 'privatelink.services.ai.azure.com': openAiSubResource +// ========== Private DNS Zones ========== // +var privateDnsZones = [ + 'privatelink.cognitiveservices.azure.com' + 'privatelink.openai.azure.com' + 'privatelink.services.ai.azure.com' + 'privatelink.documents.azure.com' + 'privatelink.${toLower(replace(location,' ',''))}.azurecontainerapps.io' + 'privatelink.azurewebsites.net' +] + +// DNS Zone Index Constants +var dnsZoneIndex = { + cognitiveServices: 0 + openAI: 1 + aiServices: 2 + cosmosDb: 3 + containerAppEnvironment: 4 + appService: 5 } -module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for zone in objectKeys(openAiPrivateDnsZones): if (enablePrivateNetworking) { - name: take( - 'avm.res.network.private-dns-zone.ai-services.${uniqueString(aiFoundryAiServicesResourceName,zone)}.${solutionSuffix}', - 64 - ) +@batchSize(5) +module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ + for (zone, i) in privateDnsZones: if (enablePrivateNetworking) { + name: 'avm.res.network.private-dns-zone.${i}' params: { name: zone tags: tags @@ -922,6 +931,9 @@ module privateDnsZonesAiServices 'br/public:avm/res/network/private-dns-zone:0.7 } ] +// ========== AI Foundry: AI Services ========== // +// WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai + // NOTE: Required version 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' not available in AVM var aiFoundryAiServicesResourceName = 'aif-${solutionSuffix}' var aiFoundryAiServicesAiProjectResourceName = 'proj-${solutionSuffix}' @@ -986,10 +998,20 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices customNetworkInterfaceName: 'nic-${aiFoundryAiServicesResourceName}' subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: map(objectKeys(openAiPrivateDnsZones), zone => { - name: replace(zone, '.', '-') - privateDnsZoneResourceId: resourceId('Microsoft.Network/privateDnsZones', zone) - }) + privateDnsZoneGroupConfigs: [ + { + name: 'ai-services-dns-zone-cognitiveservices' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId + } + { + name: 'ai-services-dns-zone-openai' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.openAI]!.outputs.resourceId + } + { + name: 'ai-services-dns-zone-aiservices' + privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.aiServices]!.outputs.resourceId + } + ] } } ]) @@ -1051,20 +1073,6 @@ module resourceRoleAssignmentAiServicesAiProjectCognitiveServicesOpenAiUser 'br/ // ========== Cosmos DB ========== // // WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db -module privateDnsZonesCosmosDb 'br/public:avm/res/network/private-dns-zone:0.7.1' = if (enablePrivateNetworking) { - name: take('avm.res.network.private-dns-zone.cosmos-db.${solutionSuffix}', 64) - params: { - name: 'privatelink.documents.azure.com' - enableTelemetry: enableTelemetry - virtualNetworkLinks: [ - { - name: take('vnetlink-${virtualNetworkResourceName}-documents', 80) - virtualNetworkResourceId: virtualNetwork!.outputs.resourceId - } - ] - tags: tags - } -} var cosmosDbResourceName = 'cosmos-${solutionSuffix}' var cosmosDbDatabaseName = 'macae' @@ -1119,7 +1127,7 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { name: 'pep-${cosmosDbResourceName}' customNetworkInterfaceName: 'nic-${cosmosDbResourceName}' privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesCosmosDb!.outputs.resourceId }] + privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cosmosDb]!.outputs.resourceId }] } service: 'Sql' subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] @@ -1199,16 +1207,7 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2 } } -// Private DNS Zone Group for Container App Environment Private Endpoint -module privateDnsZonesContainerAppEnvironment 'br/public:avm/res/network/private-dns-zone:0.7.1' = if (enablePrivateNetworking) { - name: take('avm.res.network.private-dns-zone.app-environment.${solutionSuffix}', 64) - params: { - name: 'privatelink.${toLower(replace(containerAppEnvironment.outputs.location,' ',''))}.azurecontainerapps.io' - enableTelemetry: enableTelemetry - virtualNetworkLinks: [{ virtualNetworkResourceId: virtualNetwork!.outputs.resourceId }] - tags: tags - } -} + // Private Endpoint for Container App Environment var privateEndpointContainerAppEnvironmentService = 'managedEnvironments' @@ -1233,7 +1232,7 @@ module privateEndpointContainerAppEnvironment 'br:mcr.microsoft.com/bicep/avm/re ] privateDnsZoneGroup: { privateDnsZoneGroupConfigs: [ - { privateDnsZoneResourceId: privateDnsZonesContainerAppEnvironment!.outputs.resourceId } + { privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.containerAppEnvironment]!.outputs.resourceId } ] } } @@ -1245,6 +1244,9 @@ module privateEndpointContainerAppEnvironment 'br:mcr.microsoft.com/bicep/avm/re var containerAppResourceName = 'ca-${solutionSuffix}' module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { name: take('avm.res.app.container-app.${containerAppResourceName}', 64) + dependsOn:[ + privateEndpointContainerAppEnvironment + ] params: { name: containerAppResourceName tags: tags @@ -1399,16 +1401,6 @@ module webServerFarm 'br/public:avm/res/web/serverfarm:0.5.0' = { // ========== Frontend web site ========== // // WAF best practices for web app service: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/app-service-web-apps // PSRule for Web Server Farm: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#app-service -// Private DNS Zone Group for Web App Service Private Endpoint -module privateDnsZonesWebApp 'br/public:avm/res/network/private-dns-zone:0.7.1' = if (enablePrivateNetworking) { - name: take('avm.res.network.private-dns-zone.web-app.${solutionSuffix}', 64) - params: { - name: 'privatelink.azurewebsites.net' - enableTelemetry: enableTelemetry - virtualNetworkLinks: [{ virtualNetworkResourceId: virtualNetwork!.outputs.resourceId }] - tags: tags - } -} //NOTE: AVM module adds 1 MB of overhead to the template. Keeping vanilla resource to save template size. var webSiteResourceName = 'app-${solutionSuffix}' @@ -1451,7 +1443,7 @@ module webSite 'modules/web-sites.bicep' = { name: 'pep-${webSiteResourceName}' customNetworkInterfaceName: 'nic-${webSiteResourceName}' privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: privateDnsZonesWebApp!.outputs.resourceId }] + privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.appService]!.outputs.resourceId }] } service: 'sites' subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] From 8ee525d2cc2da7068a77b58f83cf0687c5c42bab Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Wed, 20 Aug 2025 13:54:01 +0530 Subject: [PATCH 08/29] Added changes to reuse the existing log analytics --- infra/main.bicep | 63 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index d97a0cda6..edb305395 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -107,6 +107,12 @@ param frontendContainerImageTag string = 'latest_2025-07-22_895' @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true +@description('Use this parameter to reuse an existing Log Analytics Workspace') +param existingLogAnalyticsWorkspaceId string = '' + +@description('Use this parameter to reuse an existing AI project resource ID') +param existingFoundryProjectResourceId string = '' + // ============== // // Variables // // ============== // @@ -191,11 +197,23 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } +// Extracts subscription, resource group, and workspace name from the resource ID when using an existing Log Analytics workspace +var useExistingLogAnalytics = !empty(existingLogAnalyticsWorkspaceId) + +var existingLawSubscription = useExistingLogAnalytics ? split(existingLogAnalyticsWorkspaceId, '/')[2] : '' +var existingLawResourceGroup = useExistingLogAnalytics ? split(existingLogAnalyticsWorkspaceId, '/')[4] : '' +var existingLawName = useExistingLogAnalytics ? split(existingLogAnalyticsWorkspaceId, '/')[8] : '' + +resource existingLogAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = if (useExistingLogAnalytics) { + name: existingLawName + scope: resourceGroup(existingLawSubscription, existingLawResourceGroup) +} + // ========== Log Analytics Workspace ========== // // WAF best practices for Log Analytics: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-log-analytics // WAF PSRules for Log Analytics: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#azure-monitor-logs var logAnalyticsWorkspaceResourceName = 'log-${solutionSuffix}' -module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.12.0' = if (enableMonitoring) { +module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.12.0' = if (enableMonitoring && !useExistingLogAnalytics) { name: take('avm.res.operational-insights.workspace.${logAnalyticsWorkspaceResourceName}', 64) params: { name: logAnalyticsWorkspaceResourceName @@ -253,6 +271,11 @@ module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0 : null } } +// Log Analytics Name, workspace ID, customer ID, and shared key (existing or new) +var logAnalyticsWorkspaceName = useExistingLogAnalytics ? existingLogAnalyticsWorkspace!.name : logAnalyticsWorkspace!.outputs.name +var logAnalyticsWorkspaceResourceId = useExistingLogAnalytics ? existingLogAnalyticsWorkspaceId : logAnalyticsWorkspace!.outputs.resourceId +var logAnalyticsPrimarySharedKey = useExistingLogAnalytics? existingLogAnalyticsWorkspace!.listKeys().primarySharedKey : logAnalyticsWorkspace.outputs.primarySharedKey +var logAnalyticsWorkspaceId = useExistingLogAnalytics? existingLogAnalyticsWorkspace!.properties.customerId : logAnalyticsWorkspace!.outputs.logAnalyticsWorkspaceId // ========== Application Insights ========== // // WAF best practices for Application Insights: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/application-insights @@ -270,8 +293,8 @@ module applicationInsights 'br/public:avm/res/insights/component:0.6.0' = if (en disableIpMasking: false flowType: 'Bluefield' // WAF aligned configuration for Monitoring - workspaceResourceId: enableMonitoring ? logAnalyticsWorkspace!.outputs.resourceId : '' - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + workspaceResourceId: enableMonitoring ? logAnalyticsWorkspaceResourceId : '' + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null } } @@ -299,7 +322,7 @@ module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-g location: location tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null securityRules: [ { name: 'deny-hop-outbound' @@ -329,7 +352,7 @@ module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-g location: location tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null securityRules: [ { name: 'AllowHttpsInBound' @@ -485,7 +508,7 @@ module networkSecurityGroupAdministration 'br/public:avm/res/network/network-sec location: location tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null securityRules: [ { name: 'deny-hop-outbound' @@ -515,7 +538,7 @@ module networkSecurityGroupContainers 'br/public:avm/res/network/network-securit location: location tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null securityRules: [ { name: 'deny-hop-outbound' @@ -545,7 +568,7 @@ module networkSecurityGroupWebsite 'br/public:avm/res/network/network-security-g location: location tags: tags enableTelemetry: enableTelemetry - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null securityRules: [ { name: 'deny-hop-outbound' @@ -639,7 +662,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:0.7.0' = if (enablePr virtualNetworkResourceId: virtualNetwork!.?outputs.?resourceId publicIPAddressObject: { name: 'pip-bas${solutionSuffix}' - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null tags: tags } disableCopyPaste: true @@ -647,7 +670,7 @@ module bastionHost 'br/public:avm/res/network/bastion-host:0.7.0' = if (enablePr enableIpConnect: false enableShareableLink: false scaleUnits: 4 - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null } } @@ -762,7 +785,7 @@ module windowsVmDataCollectionRules 'br/public:avm/res/insights/data-collection- destinations: { logAnalytics: [ { - workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId + workspaceResourceId: logAnalyticsWorkspaceResourceId name: 'la--1264800308' } ] @@ -840,14 +863,14 @@ module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.17.0' = if (e tags: tags deleteOption: 'Delete' diagnosticSettings: enableMonitoring //WAF aligned configuration for Monitoring - ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] + ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null ipConfigurations: [ { name: '${virtualMachineResourceName}-nic01-ipconfig01' subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[1] diagnosticSettings: enableMonitoring //WAF aligned configuration for Monitoring - ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] + ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null } ] @@ -879,7 +902,7 @@ module virtualMachine 'br/public:avm/res/compute/virtual-machine:0.17.0' = if (e dataCollectionRuleAssociations: [ { dataCollectionRuleResourceId: windowsVmDataCollectionRules!.outputs.resourceId - name: 'send-${logAnalyticsWorkspace!.outputs.name}' + name: 'send-${logAnalyticsWorkspaceName}' } ] enabled: true @@ -989,7 +1012,7 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices } ] // WAF aligned configuration for Monitoring - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' privateEndpoints: enablePrivateNetworking ? ([ @@ -1115,7 +1138,7 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { } ] // WAF aligned configuration for Monitoring - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null // WAF aligned configuration for Private Networking networkRestrictions: { networkAclBypass: 'None' @@ -1180,8 +1203,8 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2 ? { destination: 'log-analytics' logAnalyticsConfiguration: { - customerId: logAnalyticsWorkspace!.outputs.logAnalyticsWorkspaceId - sharedKey: logAnalyticsWorkspace.outputs.primarySharedKey + customerId: logAnalyticsWorkspaceId + sharedKey: logAnalyticsPrimarySharedKey } } : null @@ -1389,7 +1412,7 @@ module webServerFarm 'br/public:avm/res/web/serverfarm:0.5.0' = { reserved: true kind: 'linux' // WAF aligned configuration for Monitoring - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null // WAF aligned configuration for Scalability skuName: enableScalability || enableRedundancy ? 'P1v3' : 'B3' skuCapacity: enableScalability ? 3 : 1 @@ -1431,7 +1454,7 @@ module webSite 'modules/web-sites.bicep' = { applicationInsightResourceId: enableMonitoring ? applicationInsights!.outputs.resourceId : null } ] - diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspace!.outputs.resourceId }] : null + diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null // WAF aligned configuration for Private Networking vnetRouteAllEnabled: enablePrivateNetworking ? true : false vnetImagePullEnabled: enablePrivateNetworking ? true : false From 68ef9589db8332bf2fe83b86963ecc4568219090 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Thu, 21 Aug 2025 09:40:55 +0530 Subject: [PATCH 09/29] Added bicep changes related to reuse existing foundry project --- infra/main.bicep | 50 +-- infra/main.parameters.json | 6 + infra/main.waf.parameters.json | 9 +- infra/modules/ai-services.bicep | 344 ++++----------------- infra/modules/dependencies.bicep | 479 +++++++++++++++++++++++++++++ infra/modules/keyVaultExport.bicep | 43 +++ infra/modules/project.bicep | 62 ++++ 7 files changed, 665 insertions(+), 328 deletions(-) create mode 100644 infra/modules/dependencies.bicep create mode 100644 infra/modules/keyVaultExport.bicep create mode 100644 infra/modules/project.bicep diff --git a/infra/main.bicep b/infra/main.bicep index edb305395..6652e7fe9 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -107,10 +107,10 @@ param frontendContainerImageTag string = 'latest_2025-07-22_895' @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -@description('Use this parameter to reuse an existing Log Analytics Workspace') +@description('Optional. Resource ID of an existing Log Analytics Workspace') param existingLogAnalyticsWorkspaceId string = '' - -@description('Use this parameter to reuse an existing AI project resource ID') + +@description('Optional. Resource ID of an existing Foundry project') param existingFoundryProjectResourceId string = '' // ============== // @@ -979,6 +979,7 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices name: aiFoundryAiServicesResourceName location: azureAiServiceLocation tags: tags + existingFoundryProjectResourceId: existingFoundryProjectResourceId projectName: aiFoundryAiServicesAiProjectResourceName projectDescription: 'AI Foundry Project' sku: 'S0' @@ -1014,7 +1015,7 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices // WAF aligned configuration for Monitoring diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' - privateEndpoints: enablePrivateNetworking + privateEndpoints: (enablePrivateNetworking && empty(existingFoundryProjectResourceId)) ? ([ { name: 'pep-${aiFoundryAiServicesResourceName}' @@ -1057,43 +1058,6 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices } } -//Role assignments for AI Project -module resourceRoleAssignmentAiServicesAiProjectAiUser 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.2' = { - name: 'avm.ptn.authorization.resource-role-assignment.${uniqueString(aiFoundryAiServicesAiProjectResourceName,containerAppResourceName,'Azure AI User')}' - params: { - roleName: 'Azure AI User' - roleDefinitionId: '53ca6127-db72-4b80-b1b0-d745d6d5456d' - principalId: userAssignedIdentity.outputs.principalId - principalType: 'ServicePrincipal' - resourceId: aiFoundryAiServices.outputs.aiProjectResourceId - enableTelemetry: enableTelemetry - } -} - -module resourceRoleAssignmentAiServicesAiProjectAiDeveloper 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.2' = { - name: 'avm.ptn.authorization.resource-role-assignment.${uniqueString(aiFoundryAiServicesAiProjectResourceName,containerAppResourceName,'Azure AI Developer')}' - params: { - roleName: 'Azure AI Developer' - roleDefinitionId: '64702f94-c441-49e6-a78b-ef80e0188fee' - principalId: userAssignedIdentity.outputs.principalId - principalType: 'ServicePrincipal' - resourceId: aiFoundryAiServices.outputs.aiProjectResourceId - enableTelemetry: enableTelemetry - } -} - -module resourceRoleAssignmentAiServicesAiProjectCognitiveServicesOpenAiUser 'br/public:avm/ptn/authorization/resource-role-assignment:0.1.2' = { - name: 'avm.ptn.authorization.resource-role-assignment.${uniqueString(aiFoundryAiServicesAiProjectResourceName,containerAppResourceName,'Cognitive Services OpenAI User')}' - params: { - roleName: 'Cognitive Services OpenAI User' - roleDefinitionId: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - principalId: userAssignedIdentity.outputs.principalId - principalType: 'ServicePrincipal' - resourceId: aiFoundryAiServices.outputs.aiProjectResourceId - enableTelemetry: enableTelemetry - } -} - // ========== Cosmos DB ========== // // WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db @@ -1342,7 +1306,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_OPENAI_ENDPOINT' - value: 'https://${aiFoundryAiServicesResourceName}.openai.azure.com/' + value: aiFoundryAiServices.outputs.endpoint } { name: 'AZURE_OPENAI_MODEL_NAME' @@ -1382,7 +1346,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_AI_AGENT_ENDPOINT' - value: aiFoundryAiServices.outputs.aiProjectApiEndpoint + value: aiFoundryAiServices.outputs.aiProjectInfo.apiEndpoint } { name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' diff --git a/infra/main.parameters.json b/infra/main.parameters.json index 0faa4c9ae..9c41f245d 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -31,6 +31,12 @@ }, "enableTelemetry": { "value": "${AZURE_ENV_ENABLE_TELEMETRY}" + }, + "existingLogAnalyticsWorkspaceId": { + "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" + }, + "existingFoundryProjectResourceId": { + "value": "${AZURE_ENV_FOUNDRY_PROJECT_ID}" } } } \ No newline at end of file diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json index 66e52ec12..0048a3224 100644 --- a/infra/main.waf.parameters.json +++ b/infra/main.waf.parameters.json @@ -5,9 +5,6 @@ "solutionName": { "value": "${AZURE_ENV_NAME}" }, - "solutionLocation": { - "value": "${AZURE_LOCATION}" - }, "location": { "value": "${AZURE_LOCATION}" }, @@ -49,6 +46,12 @@ }, "virtualMachineAdminPassword": { "value": "${AZURE_ENV_VM_ADMIN_PASSWORD}" + }, + "existingLogAnalyticsWorkspaceId": { + "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" + }, + "existingFoundryProjectResourceId": { + "value": "${AZURE_ENV_FOUNDRY_PROJECT_ID}" } } } \ No newline at end of file diff --git a/infra/modules/ai-services.bicep b/infra/modules/ai-services.bicep index a3472bb07..94b70795b 100644 --- a/infra/modules/ai-services.bicep +++ b/infra/modules/ai-services.bicep @@ -135,7 +135,11 @@ param managedIdentities managedIdentityAllType? @description('Optional. Array of deployments about cognitive service accounts to create.') param deployments deploymentType[]? -var enableReferencedModulesTelemetry = false +@description('Optional. The resource ID of an existing Foundry project to use.') +param existingFoundryProjectResourceId string = '' + +@description('Optional. Key vault reference and secret settings for the module\'s secrets export.') +param secretsExportConfiguration secretsExportConfigurationType? var formattedUserAssignedIdentities = reduce( map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), @@ -151,127 +155,6 @@ var identity = !empty(managedIdentities) } : null -var builtInRoleNames = { - 'Cognitive Services Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' - ) - 'Cognitive Services Custom Vision Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' - ) - 'Cognitive Services Custom Vision Deployment': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '5c4089e1-6d96-4d2f-b296-c1bc7137275f' - ) - 'Cognitive Services Custom Vision Labeler': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '88424f51-ebe7-446f-bc41-7fa16989e96c' - ) - 'Cognitive Services Custom Vision Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '93586559-c37d-4a6b-ba08-b9f0940c2d73' - ) - 'Cognitive Services Custom Vision Trainer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' - ) - 'Cognitive Services Data Reader (Preview)': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'b59867f0-fa02-499b-be73-45a86b5b3e1c' - ) - 'Cognitive Services Face Recognizer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '9894cab4-e18a-44aa-828b-cb588cd6f2d7' - ) - 'Cognitive Services Immersive Reader User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'b2de6794-95db-4659-8781-7e080d3f2b9d' - ) - 'Cognitive Services Language Owner': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f07febfe-79bc-46b1-8b37-790e26e6e498' - ) - 'Cognitive Services Language Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '7628b7b8-a8b2-4cdc-b46f-e9b35248918e' - ) - 'Cognitive Services Language Writer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8' - ) - 'Cognitive Services LUIS Owner': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f72c8140-2111-481c-87ff-72b910f6e3f8' - ) - 'Cognitive Services LUIS Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '18e81cdc-4e98-4e29-a639-e7d10c5a6226' - ) - 'Cognitive Services LUIS Writer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '6322a993-d5c9-4bed-b113-e49bbea25b27' - ) - 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'cb43c632-a144-4ec5-977c-e80c4affc34a' - ) - 'Cognitive Services Metrics Advisor User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '3b20f47b-3825-43cb-8114-4bd2201156a8' - ) - 'Cognitive Services OpenAI Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'a001fd3d-188f-4b5d-821b-7da978bf7442' - ) - 'Cognitive Services OpenAI User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - ) - 'Cognitive Services QnA Maker Editor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f4cc2bf9-21be-47a1-bdf1-5c5804381025' - ) - 'Cognitive Services QnA Maker Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '466ccd10-b268-4a11-b098-b4849f024126' - ) - 'Cognitive Services Speech Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '0e75ca1e-0464-4b4d-8b93-68208a576181' - ) - 'Cognitive Services Speech User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f2dc8367-1007-4938-bd23-fe263f013447' - ) - 'Cognitive Services User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'a97b65f3-24c7-4388-baec-2e87135dc908' - ) - Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Role Based Access Control Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' - ) - 'User Access Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' - ) -} - -var formattedRoleAssignments = [ - for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { - roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( - roleAssignment.roleDefinitionIdOrName, - '/providers/Microsoft.Authorization/roleDefinitions/' - ) - ? roleAssignment.roleDefinitionIdOrName - : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) - }) -] - resource cMKKeyVault 'Microsoft.KeyVault/vaults@2024-11-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { name: last(split(customerManagedKey.?keyVaultResourceId!, '/')) scope: resourceGroup( @@ -292,7 +175,9 @@ resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentiti ) } -resource cognitiveService 'Microsoft.CognitiveServices/accounts@2025-06-01' = { +var useExistingService = !empty(existingFoundryProjectResourceId) + +resource cognitiveServiceNew 'Microsoft.CognitiveServices/accounts@2025-06-01' = if(!useExistingService) { name: name kind: kind identity: identity @@ -351,189 +236,84 @@ resource cognitiveService 'Microsoft.CognitiveServices/accounts@2025-06-01' = { } } -@batchSize(1) -resource cognitiveService_deployments 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = [ - for (deployment, index) in (deployments ?? []): { - parent: cognitiveService - name: deployment.?name ?? '${name}-deployments' - properties: { - model: deployment.model - raiPolicyName: deployment.?raiPolicyName - versionUpgradeOption: deployment.?versionUpgradeOption - } - sku: deployment.?sku ?? { - name: sku - capacity: sku.?capacity - tier: sku.?tier - size: sku.?size - family: sku.?family - } - } -] +var existingCognitiveServiceDetails = split(existingFoundryProjectResourceId, '/') -resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' = { - parent: cognitiveService - name: projectName - tags: tags - location: location - identity: { - type: 'SystemAssigned' - } - properties: { - description: projectDescription - displayName: projectName - } +resource cognitiveServiceExisting 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = if(useExistingService) { + name: existingCognitiveServiceDetails[8] + scope: resourceGroup(existingCognitiveServiceDetails[2], existingCognitiveServiceDetails[4]) } -resource cognitiveService_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { - name: lock.?name ?? 'lock-${name}' - properties: { - level: lock.?kind ?? '' - notes: lock.?kind == 'CanNotDelete' - ? 'Cannot delete resource or child resources.' - : 'Cannot delete or modify the resource or child resources.' +module cognitive_service_dependencies './dependencies.bicep' = if(!useExistingService) { + params: { + projectName: projectName + projectDescription: projectDescription + name: cognitiveServiceNew.name + location: location + deployments: deployments + diagnosticSettings: diagnosticSettings + lock: lock + privateEndpoints: privateEndpoints + roleAssignments: roleAssignments + secretsExportConfiguration: secretsExportConfiguration + sku: sku + tags: tags } - scope: cognitiveService } -#disable-next-line use-recent-api-versions -resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ - for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [ - for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - } - ] - logs: [ - for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - } - ] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType - } - scope: cognitiveService - } -] - -module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [ - for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: take('${uniqueString(deployment().name, location)}-cognitiveService-PrivateEndpoint-${index}', 64) - scope: resourceGroup( - split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[2], - split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[4] - ) - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - privateLinkServiceConnections: privateEndpoint.?isManualConnection != true - ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' - ] - } - } - ] - : null - manualPrivateLinkServiceConnections: privateEndpoint.?isManualConnection == true - ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' - ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] - : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: enableReferencedModulesTelemetry - location: privateEndpoint.?location ?? reference( - split(privateEndpoint.subnetResourceId, '/subnets/')[0], - '2020-06-01', - 'Full' - ).location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName - } +module existing_cognitive_service_dependencies './dependencies.bicep' = if(useExistingService) { + params: { + name: cognitiveServiceExisting.name + projectName: projectName + projectDescription: projectDescription + existingFoundryProjectResourceId: existingFoundryProjectResourceId + location: location + deployments: deployments + diagnosticSettings: diagnosticSettings + lock: lock + privateEndpoints: privateEndpoints + roleAssignments: roleAssignments + secretsExportConfiguration: secretsExportConfiguration + sku: sku + tags: tags } -] - -resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ - for (roleAssignment, index) in (formattedRoleAssignments ?? []): { - name: roleAssignment.?name ?? guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) - properties: { - roleDefinitionId: roleAssignment.roleDefinitionId - principalId: roleAssignment.principalId - description: roleAssignment.?description - principalType: roleAssignment.?principalType - condition: roleAssignment.?condition - conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set - delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId - } - scope: cognitiveService - } -] + scope: resourceGroup(existingCognitiveServiceDetails[2], existingCognitiveServiceDetails[4]) +} + +var cognitiveService = useExistingService ? cognitiveServiceExisting : cognitiveServiceNew @description('The name of the cognitive services account.') -output name string = cognitiveService.name +output name string = useExistingService ? cognitiveServiceExisting.name : cognitiveServiceNew.name @description('The resource ID of the cognitive services account.') -output resourceId string = cognitiveService.id - -@description('The resource ID of AI project.') -output aiProjectResourceId string = aiFoundryProject.id +output resourceId string = useExistingService ? cognitiveServiceExisting.id : cognitiveServiceNew.id -@description('The endpoint to connect to the AI Project API') -output aiProjectApiEndpoint string = aiFoundryProject.properties.endpoints['AI Foundry API'] +@description('The resource group the cognitive services account was deployed into.') +output subscriptionId string = useExistingService ? existingCognitiveServiceDetails[2] : subscription().subscriptionId @description('The resource group the cognitive services account was deployed into.') -output resourceGroupName string = resourceGroup().name +output resourceGroupName string = useExistingService ? existingCognitiveServiceDetails[4] : resourceGroup().name @description('The service endpoint of the cognitive services account.') -output endpoint string = cognitiveService.properties.endpoint +output endpoint string = useExistingService ? cognitiveServiceExisting!.properties.endpoint : cognitiveService.properties.endpoint @description('All endpoints available for the cognitive services account, types depends on the cognitive service kind.') -output endpoints endpointType = cognitiveService.properties.endpoints +output endpoints endpointType = useExistingService ? cognitiveServiceExisting!.properties.endpoints : cognitiveService.properties.endpoints @description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string? = cognitiveService.?identity.?principalId +output systemAssignedMIPrincipalId string? = useExistingService ? cognitiveServiceExisting!.identity.principalId : cognitiveService.?identity.?principalId @description('The location the resource was deployed into.') -output location string = cognitiveService.location +output location string = useExistingService ? cognitiveServiceExisting!.location : cognitiveService.location + +import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') +output exportedSecrets secretsOutputType = useExistingService ? existing_cognitive_service_dependencies!.outputs.exportedSecrets : cognitive_service_dependencies!.outputs.exportedSecrets @description('The private endpoints of the congitive services account.') -output privateEndpoints privateEndpointOutputType[] = [ - for (pe, index) in (privateEndpoints ?? []): { - name: cognitiveService_privateEndpoints[index].outputs.name - resourceId: cognitiveService_privateEndpoints[index].outputs.resourceId - groupId: cognitiveService_privateEndpoints[index].outputs.?groupId! - customDnsConfigs: cognitiveService_privateEndpoints[index].outputs.customDnsConfigs - networkInterfaceResourceIds: cognitiveService_privateEndpoints[index].outputs.networkInterfaceResourceIds - } -] +output privateEndpoints privateEndpointOutputType[] = useExistingService ? existing_cognitive_service_dependencies!.outputs.privateEndpoints : cognitive_service_dependencies!.outputs.privateEndpoints + +import { aiProjectOutputType } from './project.bicep' +output aiProjectInfo aiProjectOutputType = useExistingService ? existing_cognitive_service_dependencies!.outputs.aiProjectInfo : cognitive_service_dependencies!.outputs.aiProjectInfo // ================ // // Definitions // diff --git a/infra/modules/dependencies.bicep b/infra/modules/dependencies.bicep new file mode 100644 index 000000000..9c9efb278 --- /dev/null +++ b/infra/modules/dependencies.bicep @@ -0,0 +1,479 @@ +@description('Required. The name of Cognitive Services account.') +param name string + +@description('Optional. SKU of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') +@allowed([ + 'C2' + 'C3' + 'C4' + 'F0' + 'F1' + 'S' + 'S0' + 'S1' + 'S10' + 'S2' + 'S3' + 'S4' + 'S5' + 'S6' + 'S7' + 'S8' + 'S9' +]) +param sku string = 'S0' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Array of deployments about cognitive service accounts to create.') +param deployments deploymentType[]? + +@description('Optional. Key vault reference and secret settings for the module\'s secrets export.') +param secretsExportConfiguration secretsExportConfigurationType? + +import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointSingleServiceType[]? + +import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The lock settings of the service.') +param lock lockType? + +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType[]? + +import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingFullType[]? + +@description('Optional. Name for the project which needs to be created.') +param projectName string + +@description('Optional. Description for the project which needs to be created.') +param projectDescription string + +@description('Optional. Provide the existing project resource id in case if it needs to be reused') +param existingFoundryProjectResourceId string = '' + +var builtInRoleNames = { + 'Cognitive Services Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + ) + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + ) + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5c4089e1-6d96-4d2f-b296-c1bc7137275f' + ) + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '88424f51-ebe7-446f-bc41-7fa16989e96c' + ) + 'Cognitive Services Custom Vision Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '93586559-c37d-4a6b-ba08-b9f0940c2d73' + ) + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + ) + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b59867f0-fa02-499b-be73-45a86b5b3e1c' + ) + 'Cognitive Services Face Recognizer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9894cab4-e18a-44aa-828b-cb588cd6f2d7' + ) + 'Cognitive Services Immersive Reader User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b2de6794-95db-4659-8781-7e080d3f2b9d' + ) + 'Cognitive Services Language Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f07febfe-79bc-46b1-8b37-790e26e6e498' + ) + 'Cognitive Services Language Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7628b7b8-a8b2-4cdc-b46f-e9b35248918e' + ) + 'Cognitive Services Language Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8' + ) + 'Cognitive Services LUIS Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f72c8140-2111-481c-87ff-72b910f6e3f8' + ) + 'Cognitive Services LUIS Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18e81cdc-4e98-4e29-a639-e7d10c5a6226' + ) + 'Cognitive Services LUIS Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '6322a993-d5c9-4bed-b113-e49bbea25b27' + ) + 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'cb43c632-a144-4ec5-977c-e80c4affc34a' + ) + 'Cognitive Services Metrics Advisor User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3b20f47b-3825-43cb-8114-4bd2201156a8' + ) + 'Cognitive Services OpenAI Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a001fd3d-188f-4b5d-821b-7da978bf7442' + ) + 'Cognitive Services OpenAI User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + ) + 'Cognitive Services QnA Maker Editor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f4cc2bf9-21be-47a1-bdf1-5c5804381025' + ) + 'Cognitive Services QnA Maker Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '466ccd10-b268-4a11-b098-b4849f024126' + ) + 'Cognitive Services Speech Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0e75ca1e-0464-4b4d-8b93-68208a576181' + ) + 'Cognitive Services Speech User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2dc8367-1007-4938-bd23-fe263f013447' + ) + 'Cognitive Services User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a97b65f3-24c7-4388-baec-2e87135dc908' + ) + 'Azure AI Developer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '64702f94-c441-49e6-a78b-ef80e0188fee' + ) + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) +} + +var formattedRoleAssignments = [ + for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { + roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( + roleAssignment.roleDefinitionIdOrName, + '/providers/Microsoft.Authorization/roleDefinitions/' + ) + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) + }) +] + +var enableReferencedModulesTelemetry = false + +resource cognitiveService 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = { + name: name +} + +@batchSize(1) +resource cognitiveService_deployments 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = [ + for (deployment, index) in (deployments ?? []): { + parent: cognitiveService + name: deployment.?name ?? '${name}-deployments' + properties: { + model: deployment.model + raiPolicyName: deployment.?raiPolicyName + versionUpgradeOption: deployment.?versionUpgradeOption + } + sku: deployment.?sku ?? { + name: sku + capacity: sku.?capacity + tier: sku.?tier + size: sku.?size + family: sku.?family + } + } +] + +resource cognitiveService_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' + ? 'Cannot delete resource or child resources.' + : 'Cannot delete or modify the resource or child resources.' + } + scope: cognitiveService +} + +resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ + for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: [ + for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { + category: group.category + enabled: group.?enabled ?? true + timeGrain: null + } + ] + logs: [ + for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { + categoryGroup: group.?categoryGroup + category: group.?category + enabled: group.?enabled ?? true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: cognitiveService + } +] + +module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [ + for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-cognitiveService-PrivateEndpoint-${index}' + scope: resourceGroup( + split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[2], + split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[4] + ) + params: { + name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + privateLinkServiceConnections: privateEndpoint.?isManualConnection != true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + } + } + ] + : null + manualPrivateLinkServiceConnections: privateEndpoint.?isManualConnection == true + ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] + : null + subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: enableReferencedModulesTelemetry + location: privateEndpoint.?location ?? reference( + split(privateEndpoint.subnetResourceId, '/subnets/')[0], + '2020-06-01', + 'Full' + ).location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + } + } +] + +resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (formattedRoleAssignments ?? []): { + name: roleAssignment.?name ?? guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) + properties: { + roleDefinitionId: roleAssignment.roleDefinitionId + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: cognitiveService + } +] + +module secretsExport './keyVaultExport.bicep' = if (secretsExportConfiguration != null) { + name: '${uniqueString(deployment().name, location)}-secrets-kv' + scope: resourceGroup( + split(secretsExportConfiguration.?keyVaultResourceId!, '/')[2], + split(secretsExportConfiguration.?keyVaultResourceId!, '/')[4] + ) + params: { + keyVaultName: last(split(secretsExportConfiguration.?keyVaultResourceId!, '/')) + secretsToSet: union( + [], + contains(secretsExportConfiguration!, 'accessKey1Name') + ? [ + { + name: secretsExportConfiguration!.?accessKey1Name + value: cognitiveService.listKeys().key1 + } + ] + : [], + contains(secretsExportConfiguration!, 'accessKey2Name') + ? [ + { + name: secretsExportConfiguration!.?accessKey2Name + value: cognitiveService.listKeys().key2 + } + ] + : [] + ) + } +} + +module aiProject 'project.bicep' = if(!empty(projectName) || !empty(existingFoundryProjectResourceId)) { + name: take('${name}-ai-project-${projectName}-deployment', 64) + params: { + name: projectName + desc: projectDescription + aiServicesName: cognitiveService.name + location: location + tags: tags + existingFoundryProjectResourceId: existingFoundryProjectResourceId + } +} + +import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') +output exportedSecrets secretsOutputType = (secretsExportConfiguration != null) + ? toObject(secretsExport!.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret) + : {} + +@description('The private endpoints of the congitive services account.') +output privateEndpoints privateEndpointOutputType[] = [ + for (pe, index) in (privateEndpoints ?? []): { + name: cognitiveService_privateEndpoints[index].outputs.name + resourceId: cognitiveService_privateEndpoints[index].outputs.resourceId + groupId: cognitiveService_privateEndpoints[index].outputs.?groupId! + customDnsConfigs: cognitiveService_privateEndpoints[index].outputs.customDnsConfigs + networkInterfaceResourceIds: cognitiveService_privateEndpoints[index].outputs.networkInterfaceResourceIds + } +] + +import { aiProjectOutputType } from 'project.bicep' +output aiProjectInfo aiProjectOutputType = aiProject!.outputs.aiProjectInfo + +// ================ // +// Definitions // +// ================ // + +@export() +@description('The type for the private endpoint output.') +type privateEndpointOutputType = { + @description('The name of the private endpoint.') + name: string + + @description('The resource ID of the private endpoint.') + resourceId: string + + @description('The group Id for the private endpoint Group.') + groupId: string? + + @description('The custom DNS configurations of the private endpoint.') + customDnsConfigs: { + @description('FQDN that resolves to private endpoint IP address.') + fqdn: string? + + @description('A list of private IP addresses of the private endpoint.') + ipAddresses: string[] + }[] + + @description('The IDs of the network interfaces associated with the private endpoint.') + networkInterfaceResourceIds: string[] +} + +@export() +@description('The type for a cognitive services account deployment.') +type deploymentType = { + @description('Optional. Specify the name of cognitive service account deployment.') + name: string? + + @description('Required. Properties of Cognitive Services account deployment model.') + model: { + @description('Required. The name of Cognitive Services account deployment model.') + name: string + + @description('Required. The format of Cognitive Services account deployment model.') + format: string + + @description('Required. The version of Cognitive Services account deployment model.') + version: string + } + + @description('Optional. The resource model definition representing SKU.') + sku: { + @description('Required. The name of the resource model definition representing SKU.') + name: string + + @description('Optional. The capacity of the resource model definition representing SKU.') + capacity: int? + + @description('Optional. The tier of the resource model definition representing SKU.') + tier: string? + + @description('Optional. The size of the resource model definition representing SKU.') + size: string? + + @description('Optional. The family of the resource model definition representing SKU.') + family: string? + }? + + @description('Optional. The name of RAI policy.') + raiPolicyName: string? + + @description('Optional. The version upgrade option.') + versionUpgradeOption: string? +} + +@export() +@description('The type for a cognitive services account endpoint.') +type endpointType = { + @description('Type of the endpoint.') + name: string? + @description('The endpoint URI.') + endpoint: string? +} + +@export() +@description('The type of the secrets exported to the provided Key Vault.') +type secretsExportConfigurationType = { + @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') + keyVaultResourceId: string + + @description('Optional. The name for the accessKey1 secret to create.') + accessKey1Name: string? + + @description('Optional. The name for the accessKey2 secret to create.') + accessKey2Name: string? +} diff --git a/infra/modules/keyVaultExport.bicep b/infra/modules/keyVaultExport.bicep new file mode 100644 index 000000000..a54cc5576 --- /dev/null +++ b/infra/modules/keyVaultExport.bicep @@ -0,0 +1,43 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. The name of the Key Vault to set the ecrets in.') +param keyVaultName string + +import { secretToSetType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Required. The secrets to set in the Key Vault.') +param secretsToSet secretToSetType[] + +// ============= // +// Resources // +// ============= // + +resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = { + name: keyVaultName +} + +resource secrets 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = [ + for secret in secretsToSet: { + name: secret.name + parent: keyVault + properties: { + value: secret.value + } + } +] + +// =========== // +// Outputs // +// =========== // + +import { secretSetOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('The references to the secrets exported to the provided Key Vault.') +output secretsSet secretSetOutputType[] = [ + #disable-next-line outputs-should-not-contain-secrets // Only returning the references, not a secret value + for index in range(0, length(secretsToSet ?? [])): { + secretResourceId: secrets[index].id + secretUri: secrets[index].properties.secretUri + secretUriWithVersion: secrets[index].properties.secretUriWithVersion + } +] diff --git a/infra/modules/project.bicep b/infra/modules/project.bicep new file mode 100644 index 000000000..f2964c875 --- /dev/null +++ b/infra/modules/project.bicep @@ -0,0 +1,62 @@ +@description('Required. Name of the AI Services project.') +param name string + +@description('Required. The location of the Project resource.') +param location string = resourceGroup().location + +@description('Optional. The description of the AI Foundry project to create. Defaults to the project name.') +param desc string = name + +@description('Required. Name of the existing Cognitive Services resource to create the AI Foundry project in.') +param aiServicesName string + +@description('Optional. Tags to be applied to the resources.') +param tags object = {} + +@description('Optional. Use this parameter to use an existing AI project resource ID from different resource group') +param existingFoundryProjectResourceId string = '' + +// // Extract components from existing AI Project Resource ID if provided +var useExistingProject = !empty(existingFoundryProjectResourceId) +var existingProjName = useExistingProject ? last(split(existingFoundryProjectResourceId, '/')) : '' +var existingProjEndpoint = useExistingProject ? format('https://{0}.services.ai.azure.com/api/projects/{1}', aiServicesName, existingProjName) : '' + +// Reference to cognitive service in current resource group for new projects +resource cogServiceReference 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = { + name: aiServicesName +} + +// Create new AI project only if not reusing existing one +resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' = if(!useExistingProject) { + parent: cogServiceReference + name: name + tags: tags + location: location + identity: { + type: 'SystemAssigned' + } + properties: { + description: desc + displayName: name + } +} + +@description('AI Project metadata including name, resource ID, and API endpoint.') +output aiProjectInfo aiProjectOutputType = { + name: useExistingProject ? existingProjName : aiProject.name + resourceId: useExistingProject ? existingFoundryProjectResourceId : aiProject.id + apiEndpoint: useExistingProject ? existingProjEndpoint : aiProject!.properties.endpoints['AI Foundry API'] +} + +@export() +@description('Output type representing AI project information.') +type aiProjectOutputType = { + @description('Required. Name of the AI project.') + name: string + + @description('Required. Resource ID of the AI project.') + resourceId: string + + @description('Required. API endpoint for the AI project.') + apiEndpoint: string +} From b30dc15be286b89e7cc84b977c6c2dd359b916c4 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Thu, 21 Aug 2025 15:43:08 +0530 Subject: [PATCH 10/29] restricting dns zone creation based on reuse existing foundry project --- infra/main.bicep | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index 6652e7fe9..bed1db58f 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -924,7 +924,7 @@ var privateDnsZones = [ 'privatelink.documents.azure.com' 'privatelink.${toLower(replace(location,' ',''))}.azurecontainerapps.io' 'privatelink.azurewebsites.net' -] +] // DNS Zone Index Constants var dnsZoneIndex = { @@ -936,10 +936,22 @@ var dnsZoneIndex = { appService: 5 } +// List of DNS zone indices that correspond to AI-related services. +var aiRelatedDnsZoneIndices = [ + dnsZoneIndex.cognitiveServices + dnsZoneIndex.openAI + dnsZoneIndex.aiServices +] + +// =================================================== +// DEPLOY PRIVATE DNS ZONES +// - Deploys all zones if no existing Foundry project is used +// - Excludes AI-related zones when using with an existing Foundry project +// =================================================== @batchSize(5) module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for (zone, i) in privateDnsZones: if (enablePrivateNetworking) { - name: 'avm.res.network.private-dns-zone.${i}' + for (zone, i) in privateDnsZones: if (enablePrivateNetworking && (empty(existingFoundryProjectResourceId) || !contains(aiRelatedDnsZoneIndices, i))) { + name: 'avm.res.network.private-dns-zone.${contains(zone, 'azurecontainerapps.io') ? 'containerappenv' : split(zone, '.')[1]}' params: { name: zone tags: tags @@ -1194,8 +1206,6 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2 } } - - // Private Endpoint for Container App Environment var privateEndpointContainerAppEnvironmentService = 'managedEnvironments' module privateEndpointContainerAppEnvironment 'br:mcr.microsoft.com/bicep/avm/res/network/private-endpoint:0.11.0' = if (enablePrivateNetworking) { From e2b5e13cee1f9503e58b4a9a27f2fe19661b440e Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Fri, 22 Aug 2025 10:49:14 +0200 Subject: [PATCH 11/29] Refactor AI project module: consolidate parameters and outputs for better clarity and maintainability --- infra/main.bicep | 171 +++++++++++++++--- .../{project.bicep => ai-project.bicep} | 17 +- 2 files changed, 153 insertions(+), 35 deletions(-) rename infra/modules/{project.bicep => ai-project.bicep} (61%) diff --git a/infra/main.bicep b/infra/main.bicep index bed1db58f..fbeeef0f4 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -35,9 +35,9 @@ param location string // Restricting deployment to only supported Azure OpenAI regions validated with GPT-4o model @allowed(['australiaeast', 'eastus2', 'francecentral', 'japaneast', 'norwayeast', 'swedencentral', 'uksouth', 'westus']) @metadata({ - azd : { + azd: { type: 'location' - usageName : [ + usageName: [ 'OpenAI.GlobalStandard.gpt-4o, 150' ] } @@ -199,11 +199,11 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT // Extracts subscription, resource group, and workspace name from the resource ID when using an existing Log Analytics workspace var useExistingLogAnalytics = !empty(existingLogAnalyticsWorkspaceId) - + var existingLawSubscription = useExistingLogAnalytics ? split(existingLogAnalyticsWorkspaceId, '/')[2] : '' var existingLawResourceGroup = useExistingLogAnalytics ? split(existingLogAnalyticsWorkspaceId, '/')[4] : '' var existingLawName = useExistingLogAnalytics ? split(existingLogAnalyticsWorkspaceId, '/')[8] : '' - + resource existingLogAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' existing = if (useExistingLogAnalytics) { name: existingLawName scope: resourceGroup(existingLawSubscription, existingLawResourceGroup) @@ -272,10 +272,18 @@ module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0 } } // Log Analytics Name, workspace ID, customer ID, and shared key (existing or new) -var logAnalyticsWorkspaceName = useExistingLogAnalytics ? existingLogAnalyticsWorkspace!.name : logAnalyticsWorkspace!.outputs.name -var logAnalyticsWorkspaceResourceId = useExistingLogAnalytics ? existingLogAnalyticsWorkspaceId : logAnalyticsWorkspace!.outputs.resourceId -var logAnalyticsPrimarySharedKey = useExistingLogAnalytics? existingLogAnalyticsWorkspace!.listKeys().primarySharedKey : logAnalyticsWorkspace.outputs.primarySharedKey -var logAnalyticsWorkspaceId = useExistingLogAnalytics? existingLogAnalyticsWorkspace!.properties.customerId : logAnalyticsWorkspace!.outputs.logAnalyticsWorkspaceId +var logAnalyticsWorkspaceName = useExistingLogAnalytics + ? existingLogAnalyticsWorkspace!.name + : logAnalyticsWorkspace!.outputs.name +var logAnalyticsWorkspaceResourceId = useExistingLogAnalytics + ? existingLogAnalyticsWorkspaceId + : logAnalyticsWorkspace!.outputs.resourceId +var logAnalyticsPrimarySharedKey = useExistingLogAnalytics + ? existingLogAnalyticsWorkspace!.listKeys().primarySharedKey + : logAnalyticsWorkspace.outputs.primarySharedKey +var logAnalyticsWorkspaceId = useExistingLogAnalytics + ? existingLogAnalyticsWorkspace!.properties.customerId + : logAnalyticsWorkspace!.outputs.logAnalyticsWorkspaceId // ========== Application Insights ========== // // WAF best practices for Application Insights: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/application-insights @@ -950,7 +958,10 @@ var aiRelatedDnsZoneIndices = [ // =================================================== @batchSize(5) module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for (zone, i) in privateDnsZones: if (enablePrivateNetworking && (empty(existingFoundryProjectResourceId) || !contains(aiRelatedDnsZoneIndices, i))) { + for (zone, i) in privateDnsZones: if (enablePrivateNetworking && (empty(existingFoundryProjectResourceId) || !contains( + aiRelatedDnsZoneIndices, + i + ))) { name: 'avm.res.network.private-dns-zone.${contains(zone, 'azurecontainerapps.io') ? 'containerappenv' : split(zone, '.')[1]}' params: { name: zone @@ -969,10 +980,96 @@ module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ // ========== AI Foundry: AI Services ========== // // WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -// NOTE: Required version 'Microsoft.CognitiveServices/accounts@2024-04-01-preview' not available in AVM -var aiFoundryAiServicesResourceName = 'aif-${solutionSuffix}' -var aiFoundryAiServicesAiProjectResourceName = 'proj-${solutionSuffix}' -var aiFoundryAIservicesEnabled = true +// //TODO: update to AVM module when AI Projects and AI Projects RBAC are supported +// module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservicesEnabled) { +// name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) +// params: { +// name: aiFoundryAiServicesResourceName +// location: azureAiServiceLocation +// tags: tags +// existingFoundryProjectResourceId: existingFoundryProjectResourceId +// projectName: aiFoundryAiServicesAiProjectResourceName +// projectDescription: 'AI Foundry Project' +// sku: 'S0' +// kind: 'AIServices' +// disableLocalAuth: true +// customSubDomainName: aiFoundryAiServicesResourceName +// apiProperties: { +// //staticsEnabled: false +// } +// networkAcls: { +// defaultAction: 'Allow' +// virtualNetworkRules: [] +// ipRules: [] +// } +// managedIdentities: { userAssignedResourceIds: [userAssignedIdentity!.outputs.resourceId] } //To create accounts or projects, you must enable a managed identity on your resource +// roleAssignments: [ +// { +// roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User +// principalId: userAssignedIdentity.outputs.principalId +// principalType: 'ServicePrincipal' +// } +// { +// roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' // Azure AI Developer +// principalId: userAssignedIdentity.outputs.principalId +// principalType: 'ServicePrincipal' +// } +// { +// roleDefinitionIdOrName: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' // Cognitive Services OpenAI User +// principalId: userAssignedIdentity.outputs.principalId +// principalType: 'ServicePrincipal' +// } +// ] +// // WAF aligned configuration for Monitoring +// diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null +// publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' +// privateEndpoints: (enablePrivateNetworking && empty(existingFoundryProjectResourceId)) +// ? ([ +// { +// name: 'pep-${aiFoundryAiServicesResourceName}' +// customNetworkInterfaceName: 'nic-${aiFoundryAiServicesResourceName}' +// subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] +// privateDnsZoneGroup: { +// privateDnsZoneGroupConfigs: [ +// { +// name: 'ai-services-dns-zone-cognitiveservices' +// privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId +// } +// { +// name: 'ai-services-dns-zone-openai' +// privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.openAI]!.outputs.resourceId +// } +// { +// name: 'ai-services-dns-zone-aiservices' +// privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.aiServices]!.outputs.resourceId +// } +// ] +// } +// } +// ]) +// : [] +// deployments: [ +// { +// name: aiFoundryAiServicesModelDeployment.name +// model: { +// format: aiFoundryAiServicesModelDeployment.format +// name: aiFoundryAiServicesModelDeployment.name +// version: aiFoundryAiServicesModelDeployment.version +// } +// raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName +// sku: { +// name: aiFoundryAiServicesModelDeployment.sku.name +// capacity: aiFoundryAiServicesModelDeployment.sku.capacity +// } +// } +// ] +// } +// } + +var useExistingAiFoundry = !empty(existingFoundryProjectResourceId) +var aiFoundryAiServicesResourceName = useExistingAiFoundry + ? split(existingFoundryProjectResourceId, '/')[8] + : 'aif-${solutionSuffix}' var aiFoundryAiServicesModelDeployment = { format: 'OpenAI' name: gptModelName @@ -984,19 +1081,21 @@ var aiFoundryAiServicesModelDeployment = { raiPolicyName: 'Microsoft.Default' } -//TODO: update to AVM module when AI Projects and AI Projects RBAC are supported -module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservicesEnabled) { +resource existingAiFoundryAiServices 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = if (useExistingAiFoundry) { + name: aiFoundryAiServicesResourceName + scope: resourceGroup(split(existingFoundryProjectResourceId, '/')[2], split(existingFoundryProjectResourceId, '/')[4]) +} + +module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-services/account:0.13.1' = if (!useExistingAiFoundry) { name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) params: { name: aiFoundryAiServicesResourceName location: azureAiServiceLocation tags: tags - existingFoundryProjectResourceId: existingFoundryProjectResourceId - projectName: aiFoundryAiServicesAiProjectResourceName - projectDescription: 'AI Foundry Project' sku: 'S0' kind: 'AIServices' disableLocalAuth: true + allowProjectManagement: true customSubDomainName: aiFoundryAiServicesResourceName apiProperties: { //staticsEnabled: false @@ -1027,7 +1126,7 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices // WAF aligned configuration for Monitoring diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' - privateEndpoints: (enablePrivateNetworking && empty(existingFoundryProjectResourceId)) + privateEndpoints: (enablePrivateNetworking && empty(existingFoundryProjectResourceId)) ? ([ { name: 'pep-${aiFoundryAiServicesResourceName}' @@ -1070,6 +1169,30 @@ module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservices } } +var useExistingAiProject = !empty(existingFoundryProjectResourceId) +var aiFoundryAiProjectResourceName = useExistingAiProject + ? last(split(existingFoundryProjectResourceId, '/')) + : 'proj-${solutionSuffix}' +var aiFoundryAiProjectDescription = 'AI Foundry Project' +var aiFoundryAiProjectEndpoint = useExistingAiProject + ? format( + 'https://{0}.services.ai.azure.com/api/projects/{1}', + aiFoundryAiServicesResourceName, + aiFoundryAiProjectResourceName + ) + : aiFoundryAiServicesProject!.outputs.aiProjectInfo.apiEndpoint + +module aiFoundryAiServicesProject 'modules/ai-project.bicep' = if (!useExistingAiProject) { + name: take('module.ai-project.${aiFoundryAiProjectResourceName}', 64) + params: { + name: aiFoundryAiProjectResourceName + location: azureAiServiceLocation + tags: tags + desc: aiFoundryAiProjectDescription + aiServicesName: aiFoundryAiServicesResourceName + } +} + // ========== Cosmos DB ========== // // WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db @@ -1126,7 +1249,9 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = { name: 'pep-${cosmosDbResourceName}' customNetworkInterfaceName: 'nic-${cosmosDbResourceName}' privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cosmosDb]!.outputs.resourceId }] + privateDnsZoneGroupConfigs: [ + { privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cosmosDb]!.outputs.resourceId } + ] } service: 'Sql' subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] @@ -1241,7 +1366,7 @@ module privateEndpointContainerAppEnvironment 'br:mcr.microsoft.com/bicep/avm/re var containerAppResourceName = 'ca-${solutionSuffix}' module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { name: take('avm.res.app.container-app.${containerAppResourceName}', 64) - dependsOn:[ + dependsOn: [ privateEndpointContainerAppEnvironment ] params: { @@ -1440,7 +1565,9 @@ module webSite 'modules/web-sites.bicep' = { name: 'pep-${webSiteResourceName}' customNetworkInterfaceName: 'nic-${webSiteResourceName}' privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [{ privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.appService]!.outputs.resourceId }] + privateDnsZoneGroupConfigs: [ + { privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.appService]!.outputs.resourceId } + ] } service: 'sites' subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] diff --git a/infra/modules/project.bicep b/infra/modules/ai-project.bicep similarity index 61% rename from infra/modules/project.bicep rename to infra/modules/ai-project.bicep index f2964c875..460e4381c 100644 --- a/infra/modules/project.bicep +++ b/infra/modules/ai-project.bicep @@ -13,21 +13,12 @@ param aiServicesName string @description('Optional. Tags to be applied to the resources.') param tags object = {} -@description('Optional. Use this parameter to use an existing AI project resource ID from different resource group') -param existingFoundryProjectResourceId string = '' - -// // Extract components from existing AI Project Resource ID if provided -var useExistingProject = !empty(existingFoundryProjectResourceId) -var existingProjName = useExistingProject ? last(split(existingFoundryProjectResourceId, '/')) : '' -var existingProjEndpoint = useExistingProject ? format('https://{0}.services.ai.azure.com/api/projects/{1}', aiServicesName, existingProjName) : '' - // Reference to cognitive service in current resource group for new projects resource cogServiceReference 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = { name: aiServicesName } -// Create new AI project only if not reusing existing one -resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' = if(!useExistingProject) { +resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' = { parent: cogServiceReference name: name tags: tags @@ -43,9 +34,9 @@ resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' = @description('AI Project metadata including name, resource ID, and API endpoint.') output aiProjectInfo aiProjectOutputType = { - name: useExistingProject ? existingProjName : aiProject.name - resourceId: useExistingProject ? existingFoundryProjectResourceId : aiProject.id - apiEndpoint: useExistingProject ? existingProjEndpoint : aiProject!.properties.endpoints['AI Foundry API'] + name: aiProject.name + resourceId: aiProject.id + apiEndpoint: aiProject!.properties.endpoints['AI Foundry API'] } @export() From e305238a1d9047a6f2ed9bfa9d6dda442035c06f Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Mon, 25 Aug 2025 11:55:19 +0200 Subject: [PATCH 12/29] Refactor AI project output structure and remove unused modules - Simplified the output structure in `ai-project.bicep` by directly outputting project name, resource ID, and API endpoint instead of using a separate output type. - Deleted the `ai-services.bicep`, `dependencies.bicep`, and `keyVaultExport.bicep` modules as they are no longer needed. - Introduced a new module `ai-services-model-deployments.bicep` to handle cognitive services account deployments and role assignments. - Updated role assignment handling to utilize built-in role names for better clarity and maintainability. --- infra/main.bicep | 110 ++-- infra/modules/ai-project.bicep | 23 +- .../ai-services-model-deployments.bicep | 197 +++++++ infra/modules/ai-services.bicep | 410 --------------- infra/modules/dependencies.bicep | 479 ------------------ infra/modules/keyVaultExport.bicep | 43 -- 6 files changed, 272 insertions(+), 990 deletions(-) create mode 100644 infra/modules/ai-services-model-deployments.bicep delete mode 100644 infra/modules/ai-services.bicep delete mode 100644 infra/modules/dependencies.bicep delete mode 100644 infra/modules/keyVaultExport.bicep diff --git a/infra/main.bicep b/infra/main.bicep index fbeeef0f4..daac1c8f4 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -107,11 +107,11 @@ param frontendContainerImageTag string = 'latest_2025-07-22_895' @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -@description('Optional. Resource ID of an existing Log Analytics Workspace') +@description('Optional. Resource ID of an existing Log Analytics Workspace.') param existingLogAnalyticsWorkspaceId string = '' -@description('Optional. Resource ID of an existing Foundry project') -param existingFoundryProjectResourceId string = '' +@description('Optional. Resource ID of an existing Ai Foundry AI Services resource.') +param existingAiFoundryResourceId string = '' // ============== // // Variables // @@ -958,7 +958,7 @@ var aiRelatedDnsZoneIndices = [ // =================================================== @batchSize(5) module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for (zone, i) in privateDnsZones: if (enablePrivateNetworking && (empty(existingFoundryProjectResourceId) || !contains( + for (zone, i) in privateDnsZones: if (enablePrivateNetworking && (!useExistingAiFoundry || !contains( aiRelatedDnsZoneIndices, i ))) { @@ -1066,9 +1066,9 @@ module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ // } // } -var useExistingAiFoundry = !empty(existingFoundryProjectResourceId) +var useExistingAiFoundry = !empty(existingAiFoundryResourceId) var aiFoundryAiServicesResourceName = useExistingAiFoundry - ? split(existingFoundryProjectResourceId, '/')[8] + ? split(existingAiFoundryResourceId, '/')[8] : 'aif-${solutionSuffix}' var aiFoundryAiServicesModelDeployment = { format: 'OpenAI' @@ -1083,10 +1083,49 @@ var aiFoundryAiServicesModelDeployment = { resource existingAiFoundryAiServices 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = if (useExistingAiFoundry) { name: aiFoundryAiServicesResourceName - scope: resourceGroup(split(existingFoundryProjectResourceId, '/')[2], split(existingFoundryProjectResourceId, '/')[4]) + scope: resourceGroup(split(existingAiFoundryResourceId, '/')[2], split(existingAiFoundryResourceId, '/')[4]) } -module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-services/account:0.13.1' = if (!useExistingAiFoundry) { +module existingAiFoundryAiServicesDeployments 'modules/ai-services-model-deployments.bicep' = if (useExistingAiFoundry) { + name: take('module.ai-services-model-deployments.${existingAiFoundryAiServices.name}', 64) + params: { + name: existingAiFoundryAiServices.name + deployments: [ + { + name: aiFoundryAiServicesModelDeployment.name + model: { + format: aiFoundryAiServicesModelDeployment.format + name: aiFoundryAiServicesModelDeployment.name + version: aiFoundryAiServicesModelDeployment.version + } + raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName + sku: { + name: aiFoundryAiServicesModelDeployment.sku.name + capacity: aiFoundryAiServicesModelDeployment.sku.capacity + } + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' // Azure AI Developer + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' // Cognitive Services OpenAI User + principalId: userAssignedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + } + ] + } +} + +module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-services/account:0.13.2' = if (!useExistingAiFoundry) { name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) params: { name: aiFoundryAiServicesResourceName @@ -1100,6 +1139,21 @@ module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-service apiProperties: { //staticsEnabled: false } + deployments: [ + { + name: aiFoundryAiServicesModelDeployment.name + model: { + format: aiFoundryAiServicesModelDeployment.format + name: aiFoundryAiServicesModelDeployment.name + version: aiFoundryAiServicesModelDeployment.version + } + raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName + sku: { + name: aiFoundryAiServicesModelDeployment.sku.name + capacity: aiFoundryAiServicesModelDeployment.sku.capacity + } + } + ] networkAcls: { defaultAction: 'Allow' virtualNetworkRules: [] @@ -1126,7 +1180,7 @@ module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-service // WAF aligned configuration for Monitoring diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' - privateEndpoints: (enablePrivateNetworking && empty(existingFoundryProjectResourceId)) + privateEndpoints: (enablePrivateNetworking) ? ([ { name: 'pep-${aiFoundryAiServicesResourceName}' @@ -1151,38 +1205,13 @@ module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-service } ]) : [] - deployments: [ - { - name: aiFoundryAiServicesModelDeployment.name - model: { - format: aiFoundryAiServicesModelDeployment.format - name: aiFoundryAiServicesModelDeployment.name - version: aiFoundryAiServicesModelDeployment.version - } - raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName - sku: { - name: aiFoundryAiServicesModelDeployment.sku.name - capacity: aiFoundryAiServicesModelDeployment.sku.capacity - } - } - ] } } -var useExistingAiProject = !empty(existingFoundryProjectResourceId) -var aiFoundryAiProjectResourceName = useExistingAiProject - ? last(split(existingFoundryProjectResourceId, '/')) - : 'proj-${solutionSuffix}' +var aiFoundryAiProjectResourceName = 'proj-${solutionSuffix}' var aiFoundryAiProjectDescription = 'AI Foundry Project' -var aiFoundryAiProjectEndpoint = useExistingAiProject - ? format( - 'https://{0}.services.ai.azure.com/api/projects/{1}', - aiFoundryAiServicesResourceName, - aiFoundryAiProjectResourceName - ) - : aiFoundryAiServicesProject!.outputs.aiProjectInfo.apiEndpoint - -module aiFoundryAiServicesProject 'modules/ai-project.bicep' = if (!useExistingAiProject) { + +module aiFoundryAiServicesProject 'modules/ai-project.bicep' = { name: take('module.ai-project.${aiFoundryAiProjectResourceName}', 64) params: { name: aiFoundryAiProjectResourceName @@ -1345,7 +1374,6 @@ module privateEndpointContainerAppEnvironment 'br:mcr.microsoft.com/bicep/avm/re privateLinkServiceConnections: [ { name: '${last(split(containerAppEnvironment.outputs.resourceId, '/'))}-${privateEndpointContainerAppEnvironmentService}-0' - properties: { groupIds: [privateEndpointContainerAppEnvironmentService] privateLinkServiceId: containerAppEnvironment.outputs.resourceId @@ -1441,7 +1469,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_OPENAI_ENDPOINT' - value: aiFoundryAiServices.outputs.endpoint + value: aiFoundryAiServicesProject.outputs.apiEndpoint } { name: 'AZURE_OPENAI_MODEL_NAME' @@ -1473,7 +1501,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_AI_PROJECT_NAME' - value: aiFoundryAiServicesAiProjectResourceName + value: aiFoundryAiServicesProject.outputs.name } { name: 'FRONTEND_SITE_NAME' @@ -1481,7 +1509,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_AI_AGENT_ENDPOINT' - value: aiFoundryAiServices.outputs.aiProjectInfo.apiEndpoint + value: aiFoundryAiServicesProject!.outputs.apiEndpoint } { name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' diff --git a/infra/modules/ai-project.bicep b/infra/modules/ai-project.bicep index 460e4381c..bfed5eb02 100644 --- a/infra/modules/ai-project.bicep +++ b/infra/modules/ai-project.bicep @@ -32,22 +32,11 @@ resource aiProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' = } } -@description('AI Project metadata including name, resource ID, and API endpoint.') -output aiProjectInfo aiProjectOutputType = { - name: aiProject.name - resourceId: aiProject.id - apiEndpoint: aiProject!.properties.endpoints['AI Foundry API'] -} - -@export() -@description('Output type representing AI project information.') -type aiProjectOutputType = { - @description('Required. Name of the AI project.') - name: string +@description('Required. Name of the AI project.') +output name string = aiProject.name - @description('Required. Resource ID of the AI project.') - resourceId: string +@description('Required. Resource ID of the AI project.') +output resourceId string = aiProject.id - @description('Required. API endpoint for the AI project.') - apiEndpoint: string -} +@description('Required. API endpoint for the AI project.') +output apiEndpoint string = aiProject!.properties.endpoints['AI Foundry API'] diff --git a/infra/modules/ai-services-model-deployments.bicep b/infra/modules/ai-services-model-deployments.bicep new file mode 100644 index 000000000..8c32a0e73 --- /dev/null +++ b/infra/modules/ai-services-model-deployments.bicep @@ -0,0 +1,197 @@ +@description('Required. The name of Cognitive Services account.') +param name string + +@description('Optional. SKU of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') +@allowed([ + 'C2' + 'C3' + 'C4' + 'F0' + 'F1' + 'S' + 'S0' + 'S1' + 'S10' + 'S2' + 'S3' + 'S4' + 'S5' + 'S6' + 'S7' + 'S8' + 'S9' +]) +param sku string = 'S0' + +import { deploymentType } from 'br:mcr.microsoft.com/bicep/avm/res/cognitive-services/account:0.13.2' +@description('Optional. Array of deployments about cognitive service accounts to create.') +param deployments deploymentType[]? + +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType[]? + +var builtInRoleNames = { + 'Cognitive Services Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' + ) + 'Cognitive Services Custom Vision Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' + ) + 'Cognitive Services Custom Vision Deployment': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5c4089e1-6d96-4d2f-b296-c1bc7137275f' + ) + 'Cognitive Services Custom Vision Labeler': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '88424f51-ebe7-446f-bc41-7fa16989e96c' + ) + 'Cognitive Services Custom Vision Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '93586559-c37d-4a6b-ba08-b9f0940c2d73' + ) + 'Cognitive Services Custom Vision Trainer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' + ) + 'Cognitive Services Data Reader (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b59867f0-fa02-499b-be73-45a86b5b3e1c' + ) + 'Cognitive Services Face Recognizer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '9894cab4-e18a-44aa-828b-cb588cd6f2d7' + ) + 'Cognitive Services Immersive Reader User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'b2de6794-95db-4659-8781-7e080d3f2b9d' + ) + 'Cognitive Services Language Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f07febfe-79bc-46b1-8b37-790e26e6e498' + ) + 'Cognitive Services Language Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '7628b7b8-a8b2-4cdc-b46f-e9b35248918e' + ) + 'Cognitive Services Language Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8' + ) + 'Cognitive Services LUIS Owner': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f72c8140-2111-481c-87ff-72b910f6e3f8' + ) + 'Cognitive Services LUIS Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18e81cdc-4e98-4e29-a639-e7d10c5a6226' + ) + 'Cognitive Services LUIS Writer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '6322a993-d5c9-4bed-b113-e49bbea25b27' + ) + 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'cb43c632-a144-4ec5-977c-e80c4affc34a' + ) + 'Cognitive Services Metrics Advisor User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '3b20f47b-3825-43cb-8114-4bd2201156a8' + ) + 'Cognitive Services OpenAI Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a001fd3d-188f-4b5d-821b-7da978bf7442' + ) + 'Cognitive Services OpenAI User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' + ) + 'Cognitive Services QnA Maker Editor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f4cc2bf9-21be-47a1-bdf1-5c5804381025' + ) + 'Cognitive Services QnA Maker Reader': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '466ccd10-b268-4a11-b098-b4849f024126' + ) + 'Cognitive Services Speech Contributor': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '0e75ca1e-0464-4b4d-8b93-68208a576181' + ) + 'Cognitive Services Speech User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f2dc8367-1007-4938-bd23-fe263f013447' + ) + 'Cognitive Services User': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'a97b65f3-24c7-4388-baec-2e87135dc908' + ) + 'Azure AI Developer': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '64702f94-c441-49e6-a78b-ef80e0188fee' + ) + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) +} + +var formattedRoleAssignments = [ + for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { + roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( + roleAssignment.roleDefinitionIdOrName, + '/providers/Microsoft.Authorization/roleDefinitions/' + ) + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) + }) +] + +resource cognitiveService 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = { + name: name +} + +@batchSize(1) +resource cognitiveService_deployments 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = [ + for (deployment, index) in (deployments ?? []): { + parent: cognitiveService + name: deployment.?name ?? '${name}-deployments' + properties: { + model: deployment.model + raiPolicyName: deployment.?raiPolicyName + versionUpgradeOption: deployment.?versionUpgradeOption + } + sku: deployment.?sku ?? { + name: sku + capacity: sku.?capacity + tier: sku.?tier + size: sku.?size + family: sku.?family + } + } +] + +resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (formattedRoleAssignments ?? []): { + name: roleAssignment.?name ?? guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) + properties: { + roleDefinitionId: roleAssignment.roleDefinitionId + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: cognitiveService + } +] diff --git a/infra/modules/ai-services.bicep b/infra/modules/ai-services.bicep deleted file mode 100644 index 94b70795b..000000000 --- a/infra/modules/ai-services.bicep +++ /dev/null @@ -1,410 +0,0 @@ -metadata name = 'Cognitive Services' -metadata description = 'This module deploys a Cognitive Service.' - -@description('Required. The name of Cognitive Services account.') -param name string - -@description('Required. Kind of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') -@allowed([ - 'AIServices' - 'AnomalyDetector' - 'CognitiveServices' - 'ComputerVision' - 'ContentModerator' - 'ContentSafety' - 'ConversationalLanguageUnderstanding' - 'CustomVision.Prediction' - 'CustomVision.Training' - 'Face' - 'FormRecognizer' - 'HealthInsights' - 'ImmersiveReader' - 'Internal.AllInOne' - 'LUIS' - 'LUIS.Authoring' - 'LanguageAuthoring' - 'MetricsAdvisor' - 'OpenAI' - 'Personalizer' - 'QnAMaker.v2' - 'SpeechServices' - 'TextAnalytics' - 'TextTranslation' -]) -param kind string - -@description('Required. The name of the AI Foundry project to create.') -param projectName string - -@description('Required. The description of the AI Foundry project to create.') -param projectDescription string - -@description('Optional. SKU of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') -@allowed([ - 'C2' - 'C3' - 'C4' - 'F0' - 'F1' - 'S' - 'S0' - 'S1' - 'S10' - 'S2' - 'S3' - 'S4' - 'S5' - 'S6' - 'S7' - 'S8' - 'S9' -]) -param sku string = 'S0' - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location - -import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingFullType[]? - -@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkAcls are not set.') -@allowed([ - 'Enabled' - 'Disabled' -]) -param publicNetworkAccess string? - -@description('Conditional. Subdomain name used for token-based authentication. Required if \'networkAcls\' or \'privateEndpoints\' are set.') -param customSubDomainName string? - -@description('Optional. A collection of rules governing the accessibility from specific network locations.') -param networkAcls object? - -@description('Optional. The network injection subnet resource Id for the Cognitive Services account. This allows to use the AI Services account with a virtual network.') -param networkInjectionSubnetResourceId string? - -import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointSingleServiceType[]? - -import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The lock settings of the service.') -param lock lockType? - -import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType[]? - -@description('Optional. Tags of the resource.') -param tags object? - -@description('Optional. List of allowed FQDN.') -param allowedFqdnList array? - -@description('Optional. The API properties for special APIs.') -param apiProperties object? - -@description('Optional. Allow only Azure AD authentication. Should be enabled for security reasons.') -param disableLocalAuth bool = true - -import { customerManagedKeyType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The customer managed key definition.') -param customerManagedKey customerManagedKeyType? - -@description('Optional. The flag to enable dynamic throttling.') -param dynamicThrottlingEnabled bool = false - -@secure() -@description('Optional. Resource migration token.') -param migrationToken string? - -@description('Optional. Restore a soft-deleted cognitive service at deployment time. Will fail if no such soft-deleted resource exists.') -param restore bool = false - -@description('Optional. Restrict outbound network access.') -param restrictOutboundNetworkAccess bool = true - -@description('Optional. The storage accounts for this resource.') -param userOwnedStorage array? - -import { managedIdentityAllType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The managed identity definition for this resource.') -param managedIdentities managedIdentityAllType? - -@description('Optional. Array of deployments about cognitive service accounts to create.') -param deployments deploymentType[]? - -@description('Optional. The resource ID of an existing Foundry project to use.') -param existingFoundryProjectResourceId string = '' - -@description('Optional. Key vault reference and secret settings for the module\'s secrets export.') -param secretsExportConfiguration secretsExportConfigurationType? - -var formattedUserAssignedIdentities = reduce( - map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), - {}, - (cur, next) => union(cur, next) -) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } -var identity = !empty(managedIdentities) - ? { - type: (managedIdentities.?systemAssigned ?? false) - ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned, UserAssigned' : 'SystemAssigned') - : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null - } - : null - -resource cMKKeyVault 'Microsoft.KeyVault/vaults@2024-11-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { - name: last(split(customerManagedKey.?keyVaultResourceId!, '/')) - scope: resourceGroup( - split(customerManagedKey.?keyVaultResourceId!, '/')[2], - split(customerManagedKey.?keyVaultResourceId!, '/')[4] - ) - - resource cMKKey 'keys@2024-11-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { - name: customerManagedKey.?keyName! - } -} - -resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { - name: last(split(customerManagedKey.?userAssignedIdentityResourceId!, '/')) - scope: resourceGroup( - split(customerManagedKey.?userAssignedIdentityResourceId!, '/')[2], - split(customerManagedKey.?userAssignedIdentityResourceId!, '/')[4] - ) -} - -var useExistingService = !empty(existingFoundryProjectResourceId) - -resource cognitiveServiceNew 'Microsoft.CognitiveServices/accounts@2025-06-01' = if(!useExistingService) { - name: name - kind: kind - identity: identity - location: location - tags: tags - sku: { - name: sku - } - properties: { - customSubDomainName: customSubDomainName - allowProjectManagement: true - networkAcls: !empty(networkAcls ?? {}) - ? { - defaultAction: networkAcls.?defaultAction - virtualNetworkRules: networkAcls.?virtualNetworkRules ?? [] - ipRules: networkAcls.?ipRules ?? [] - } - : null - publicNetworkAccess: publicNetworkAccess != null - ? publicNetworkAccess - : (!empty(networkAcls) ? 'Enabled' : 'Disabled') - allowedFqdnList: allowedFqdnList - apiProperties: apiProperties - disableLocalAuth: disableLocalAuth - #disable-next-line BCP036 - networkInjections: networkInjectionSubnetResourceId != null - ? [ - { - scenario: 'agent' - subnetArmId: networkInjectionSubnetResourceId - useMicrosoftManagedNetwork: false - } - ] - : null - // true is not supported today - encryption: !empty(customerManagedKey) - ? { - keySource: 'Microsoft.KeyVault' - keyVaultProperties: { - identityClientId: !empty(customerManagedKey.?userAssignedIdentityResourceId ?? '') - ? cMKUserAssignedIdentity!.properties.clientId - : null - keyVaultUri: cMKKeyVault!.properties.vaultUri - keyName: customerManagedKey!.keyName - keyVersion: !empty(customerManagedKey.?keyVersion ?? '') - ? customerManagedKey!.?keyVersion - : last(split(cMKKeyVault::cMKKey!.properties.keyUriWithVersion, '/')) - } - } - : null - migrationToken: migrationToken - restore: restore - restrictOutboundNetworkAccess: restrictOutboundNetworkAccess - userOwnedStorage: userOwnedStorage - dynamicThrottlingEnabled: dynamicThrottlingEnabled - } -} - -var existingCognitiveServiceDetails = split(existingFoundryProjectResourceId, '/') - -resource cognitiveServiceExisting 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = if(useExistingService) { - name: existingCognitiveServiceDetails[8] - scope: resourceGroup(existingCognitiveServiceDetails[2], existingCognitiveServiceDetails[4]) -} - -module cognitive_service_dependencies './dependencies.bicep' = if(!useExistingService) { - params: { - projectName: projectName - projectDescription: projectDescription - name: cognitiveServiceNew.name - location: location - deployments: deployments - diagnosticSettings: diagnosticSettings - lock: lock - privateEndpoints: privateEndpoints - roleAssignments: roleAssignments - secretsExportConfiguration: secretsExportConfiguration - sku: sku - tags: tags - } -} - -module existing_cognitive_service_dependencies './dependencies.bicep' = if(useExistingService) { - params: { - name: cognitiveServiceExisting.name - projectName: projectName - projectDescription: projectDescription - existingFoundryProjectResourceId: existingFoundryProjectResourceId - location: location - deployments: deployments - diagnosticSettings: diagnosticSettings - lock: lock - privateEndpoints: privateEndpoints - roleAssignments: roleAssignments - secretsExportConfiguration: secretsExportConfiguration - sku: sku - tags: tags - } - scope: resourceGroup(existingCognitiveServiceDetails[2], existingCognitiveServiceDetails[4]) -} - -var cognitiveService = useExistingService ? cognitiveServiceExisting : cognitiveServiceNew - -@description('The name of the cognitive services account.') -output name string = useExistingService ? cognitiveServiceExisting.name : cognitiveServiceNew.name - -@description('The resource ID of the cognitive services account.') -output resourceId string = useExistingService ? cognitiveServiceExisting.id : cognitiveServiceNew.id - -@description('The resource group the cognitive services account was deployed into.') -output subscriptionId string = useExistingService ? existingCognitiveServiceDetails[2] : subscription().subscriptionId - -@description('The resource group the cognitive services account was deployed into.') -output resourceGroupName string = useExistingService ? existingCognitiveServiceDetails[4] : resourceGroup().name - -@description('The service endpoint of the cognitive services account.') -output endpoint string = useExistingService ? cognitiveServiceExisting!.properties.endpoint : cognitiveService.properties.endpoint - -@description('All endpoints available for the cognitive services account, types depends on the cognitive service kind.') -output endpoints endpointType = useExistingService ? cognitiveServiceExisting!.properties.endpoints : cognitiveService.properties.endpoints - -@description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string? = useExistingService ? cognitiveServiceExisting!.identity.principalId : cognitiveService.?identity.?principalId - -@description('The location the resource was deployed into.') -output location string = useExistingService ? cognitiveServiceExisting!.location : cognitiveService.location - -import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') -output exportedSecrets secretsOutputType = useExistingService ? existing_cognitive_service_dependencies!.outputs.exportedSecrets : cognitive_service_dependencies!.outputs.exportedSecrets - -@description('The private endpoints of the congitive services account.') -output privateEndpoints privateEndpointOutputType[] = useExistingService ? existing_cognitive_service_dependencies!.outputs.privateEndpoints : cognitive_service_dependencies!.outputs.privateEndpoints - -import { aiProjectOutputType } from './project.bicep' -output aiProjectInfo aiProjectOutputType = useExistingService ? existing_cognitive_service_dependencies!.outputs.aiProjectInfo : cognitive_service_dependencies!.outputs.aiProjectInfo - -// ================ // -// Definitions // -// ================ // - -@export() -@description('The type for the private endpoint output.') -type privateEndpointOutputType = { - @description('The name of the private endpoint.') - name: string - - @description('The resource ID of the private endpoint.') - resourceId: string - - @description('The group Id for the private endpoint Group.') - groupId: string? - - @description('The custom DNS configurations of the private endpoint.') - customDnsConfigs: { - @description('FQDN that resolves to private endpoint IP address.') - fqdn: string? - - @description('A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[] - - @description('The IDs of the network interfaces associated with the private endpoint.') - networkInterfaceResourceIds: string[] -} - -@export() -@description('The type for a cognitive services account deployment.') -type deploymentType = { - @description('Optional. Specify the name of cognitive service account deployment.') - name: string? - - @description('Required. Properties of Cognitive Services account deployment model.') - model: { - @description('Required. The name of Cognitive Services account deployment model.') - name: string - - @description('Required. The format of Cognitive Services account deployment model.') - format: string - - @description('Required. The version of Cognitive Services account deployment model.') - version: string - } - - @description('Optional. The resource model definition representing SKU.') - sku: { - @description('Required. The name of the resource model definition representing SKU.') - name: string - - @description('Optional. The capacity of the resource model definition representing SKU.') - capacity: int? - - @description('Optional. The tier of the resource model definition representing SKU.') - tier: string? - - @description('Optional. The size of the resource model definition representing SKU.') - size: string? - - @description('Optional. The family of the resource model definition representing SKU.') - family: string? - }? - - @description('Optional. The name of RAI policy.') - raiPolicyName: string? - - @description('Optional. The version upgrade option.') - versionUpgradeOption: string? -} - -@export() -@description('The type for a cognitive services account endpoint.') -type endpointType = { - @description('Type of the endpoint.') - name: string? - @description('The endpoint URI.') - endpoint: string? -} - -@export() -@description('The type of the secrets exported to the provided Key Vault.') -type secretsExportConfigurationType = { - @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') - keyVaultResourceId: string - - @description('Optional. The name for the accessKey1 secret to create.') - accessKey1Name: string? - - @description('Optional. The name for the accessKey2 secret to create.') - accessKey2Name: string? -} diff --git a/infra/modules/dependencies.bicep b/infra/modules/dependencies.bicep deleted file mode 100644 index 9c9efb278..000000000 --- a/infra/modules/dependencies.bicep +++ /dev/null @@ -1,479 +0,0 @@ -@description('Required. The name of Cognitive Services account.') -param name string - -@description('Optional. SKU of the Cognitive Services account. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') -@allowed([ - 'C2' - 'C3' - 'C4' - 'F0' - 'F1' - 'S' - 'S0' - 'S1' - 'S10' - 'S2' - 'S3' - 'S4' - 'S5' - 'S6' - 'S7' - 'S8' - 'S9' -]) -param sku string = 'S0' - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location - -@description('Optional. Tags of the resource.') -param tags object? - -@description('Optional. Array of deployments about cognitive service accounts to create.') -param deployments deploymentType[]? - -@description('Optional. Key vault reference and secret settings for the module\'s secrets export.') -param secretsExportConfiguration secretsExportConfigurationType? - -import { privateEndpointSingleServiceType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') -param privateEndpoints privateEndpointSingleServiceType[]? - -import { lockType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The lock settings of the service.') -param lock lockType? - -import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType[]? - -import { diagnosticSettingFullType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Optional. The diagnostic settings of the service.') -param diagnosticSettings diagnosticSettingFullType[]? - -@description('Optional. Name for the project which needs to be created.') -param projectName string - -@description('Optional. Description for the project which needs to be created.') -param projectDescription string - -@description('Optional. Provide the existing project resource id in case if it needs to be reused') -param existingFoundryProjectResourceId string = '' - -var builtInRoleNames = { - 'Cognitive Services Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68' - ) - 'Cognitive Services Custom Vision Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3' - ) - 'Cognitive Services Custom Vision Deployment': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '5c4089e1-6d96-4d2f-b296-c1bc7137275f' - ) - 'Cognitive Services Custom Vision Labeler': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '88424f51-ebe7-446f-bc41-7fa16989e96c' - ) - 'Cognitive Services Custom Vision Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '93586559-c37d-4a6b-ba08-b9f0940c2d73' - ) - 'Cognitive Services Custom Vision Trainer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b' - ) - 'Cognitive Services Data Reader (Preview)': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'b59867f0-fa02-499b-be73-45a86b5b3e1c' - ) - 'Cognitive Services Face Recognizer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '9894cab4-e18a-44aa-828b-cb588cd6f2d7' - ) - 'Cognitive Services Immersive Reader User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'b2de6794-95db-4659-8781-7e080d3f2b9d' - ) - 'Cognitive Services Language Owner': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f07febfe-79bc-46b1-8b37-790e26e6e498' - ) - 'Cognitive Services Language Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '7628b7b8-a8b2-4cdc-b46f-e9b35248918e' - ) - 'Cognitive Services Language Writer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f2310ca1-dc64-4889-bb49-c8e0fa3d47a8' - ) - 'Cognitive Services LUIS Owner': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f72c8140-2111-481c-87ff-72b910f6e3f8' - ) - 'Cognitive Services LUIS Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '18e81cdc-4e98-4e29-a639-e7d10c5a6226' - ) - 'Cognitive Services LUIS Writer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '6322a993-d5c9-4bed-b113-e49bbea25b27' - ) - 'Cognitive Services Metrics Advisor Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'cb43c632-a144-4ec5-977c-e80c4affc34a' - ) - 'Cognitive Services Metrics Advisor User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '3b20f47b-3825-43cb-8114-4bd2201156a8' - ) - 'Cognitive Services OpenAI Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'a001fd3d-188f-4b5d-821b-7da978bf7442' - ) - 'Cognitive Services OpenAI User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' - ) - 'Cognitive Services QnA Maker Editor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f4cc2bf9-21be-47a1-bdf1-5c5804381025' - ) - 'Cognitive Services QnA Maker Reader': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '466ccd10-b268-4a11-b098-b4849f024126' - ) - 'Cognitive Services Speech Contributor': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '0e75ca1e-0464-4b4d-8b93-68208a576181' - ) - 'Cognitive Services Speech User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f2dc8367-1007-4938-bd23-fe263f013447' - ) - 'Cognitive Services User': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'a97b65f3-24c7-4388-baec-2e87135dc908' - ) - 'Azure AI Developer': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '64702f94-c441-49e6-a78b-ef80e0188fee' - ) - Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Role Based Access Control Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' - ) - 'User Access Administrator': subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', - '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' - ) -} - -var formattedRoleAssignments = [ - for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { - roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( - roleAssignment.roleDefinitionIdOrName, - '/providers/Microsoft.Authorization/roleDefinitions/' - ) - ? roleAssignment.roleDefinitionIdOrName - : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) - }) -] - -var enableReferencedModulesTelemetry = false - -resource cognitiveService 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = { - name: name -} - -@batchSize(1) -resource cognitiveService_deployments 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = [ - for (deployment, index) in (deployments ?? []): { - parent: cognitiveService - name: deployment.?name ?? '${name}-deployments' - properties: { - model: deployment.model - raiPolicyName: deployment.?raiPolicyName - versionUpgradeOption: deployment.?versionUpgradeOption - } - sku: deployment.?sku ?? { - name: sku - capacity: sku.?capacity - tier: sku.?tier - size: sku.?size - family: sku.?family - } - } -] - -resource cognitiveService_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { - name: lock.?name ?? 'lock-${name}' - properties: { - level: lock.?kind ?? '' - notes: lock.?kind == 'CanNotDelete' - ? 'Cannot delete resource or child resources.' - : 'Cannot delete or modify the resource or child resources.' - } - scope: cognitiveService -} - -resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [ - for (diagnosticSetting, index) in (diagnosticSettings ?? []): { - name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' - properties: { - storageAccountId: diagnosticSetting.?storageAccountResourceId - workspaceId: diagnosticSetting.?workspaceResourceId - eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId - eventHubName: diagnosticSetting.?eventHubName - metrics: [ - for group in (diagnosticSetting.?metricCategories ?? [{ category: 'AllMetrics' }]): { - category: group.category - enabled: group.?enabled ?? true - timeGrain: null - } - ] - logs: [ - for group in (diagnosticSetting.?logCategoriesAndGroups ?? [{ categoryGroup: 'allLogs' }]): { - categoryGroup: group.?categoryGroup - category: group.?category - enabled: group.?enabled ?? true - } - ] - marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId - logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType - } - scope: cognitiveService - } -] - -module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.11.0' = [ - for (privateEndpoint, index) in (privateEndpoints ?? []): { - name: '${uniqueString(deployment().name, location)}-cognitiveService-PrivateEndpoint-${index}' - scope: resourceGroup( - split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[2], - split(privateEndpoint.?resourceGroupResourceId ?? resourceGroup().id, '/')[4] - ) - params: { - name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - privateLinkServiceConnections: privateEndpoint.?isManualConnection != true - ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' - ] - } - } - ] - : null - manualPrivateLinkServiceConnections: privateEndpoint.?isManualConnection == true - ? [ - { - name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - properties: { - privateLinkServiceId: cognitiveService.id - groupIds: [ - privateEndpoint.?service ?? 'account' - ] - requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' - } - } - ] - : null - subnetResourceId: privateEndpoint.subnetResourceId - enableTelemetry: enableReferencedModulesTelemetry - location: privateEndpoint.?location ?? reference( - split(privateEndpoint.subnetResourceId, '/subnets/')[0], - '2020-06-01', - 'Full' - ).location - lock: privateEndpoint.?lock ?? lock - privateDnsZoneGroup: privateEndpoint.?privateDnsZoneGroup - roleAssignments: privateEndpoint.?roleAssignments - tags: privateEndpoint.?tags ?? tags - customDnsConfigs: privateEndpoint.?customDnsConfigs - ipConfigurations: privateEndpoint.?ipConfigurations - applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds - customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName - } - } -] - -resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ - for (roleAssignment, index) in (formattedRoleAssignments ?? []): { - name: roleAssignment.?name ?? guid(cognitiveService.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) - properties: { - roleDefinitionId: roleAssignment.roleDefinitionId - principalId: roleAssignment.principalId - description: roleAssignment.?description - principalType: roleAssignment.?principalType - condition: roleAssignment.?condition - conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set - delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId - } - scope: cognitiveService - } -] - -module secretsExport './keyVaultExport.bicep' = if (secretsExportConfiguration != null) { - name: '${uniqueString(deployment().name, location)}-secrets-kv' - scope: resourceGroup( - split(secretsExportConfiguration.?keyVaultResourceId!, '/')[2], - split(secretsExportConfiguration.?keyVaultResourceId!, '/')[4] - ) - params: { - keyVaultName: last(split(secretsExportConfiguration.?keyVaultResourceId!, '/')) - secretsToSet: union( - [], - contains(secretsExportConfiguration!, 'accessKey1Name') - ? [ - { - name: secretsExportConfiguration!.?accessKey1Name - value: cognitiveService.listKeys().key1 - } - ] - : [], - contains(secretsExportConfiguration!, 'accessKey2Name') - ? [ - { - name: secretsExportConfiguration!.?accessKey2Name - value: cognitiveService.listKeys().key2 - } - ] - : [] - ) - } -} - -module aiProject 'project.bicep' = if(!empty(projectName) || !empty(existingFoundryProjectResourceId)) { - name: take('${name}-ai-project-${projectName}-deployment', 64) - params: { - name: projectName - desc: projectDescription - aiServicesName: cognitiveService.name - location: location - tags: tags - existingFoundryProjectResourceId: existingFoundryProjectResourceId - } -} - -import { secretsOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.') -output exportedSecrets secretsOutputType = (secretsExportConfiguration != null) - ? toObject(secretsExport!.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret) - : {} - -@description('The private endpoints of the congitive services account.') -output privateEndpoints privateEndpointOutputType[] = [ - for (pe, index) in (privateEndpoints ?? []): { - name: cognitiveService_privateEndpoints[index].outputs.name - resourceId: cognitiveService_privateEndpoints[index].outputs.resourceId - groupId: cognitiveService_privateEndpoints[index].outputs.?groupId! - customDnsConfigs: cognitiveService_privateEndpoints[index].outputs.customDnsConfigs - networkInterfaceResourceIds: cognitiveService_privateEndpoints[index].outputs.networkInterfaceResourceIds - } -] - -import { aiProjectOutputType } from 'project.bicep' -output aiProjectInfo aiProjectOutputType = aiProject!.outputs.aiProjectInfo - -// ================ // -// Definitions // -// ================ // - -@export() -@description('The type for the private endpoint output.') -type privateEndpointOutputType = { - @description('The name of the private endpoint.') - name: string - - @description('The resource ID of the private endpoint.') - resourceId: string - - @description('The group Id for the private endpoint Group.') - groupId: string? - - @description('The custom DNS configurations of the private endpoint.') - customDnsConfigs: { - @description('FQDN that resolves to private endpoint IP address.') - fqdn: string? - - @description('A list of private IP addresses of the private endpoint.') - ipAddresses: string[] - }[] - - @description('The IDs of the network interfaces associated with the private endpoint.') - networkInterfaceResourceIds: string[] -} - -@export() -@description('The type for a cognitive services account deployment.') -type deploymentType = { - @description('Optional. Specify the name of cognitive service account deployment.') - name: string? - - @description('Required. Properties of Cognitive Services account deployment model.') - model: { - @description('Required. The name of Cognitive Services account deployment model.') - name: string - - @description('Required. The format of Cognitive Services account deployment model.') - format: string - - @description('Required. The version of Cognitive Services account deployment model.') - version: string - } - - @description('Optional. The resource model definition representing SKU.') - sku: { - @description('Required. The name of the resource model definition representing SKU.') - name: string - - @description('Optional. The capacity of the resource model definition representing SKU.') - capacity: int? - - @description('Optional. The tier of the resource model definition representing SKU.') - tier: string? - - @description('Optional. The size of the resource model definition representing SKU.') - size: string? - - @description('Optional. The family of the resource model definition representing SKU.') - family: string? - }? - - @description('Optional. The name of RAI policy.') - raiPolicyName: string? - - @description('Optional. The version upgrade option.') - versionUpgradeOption: string? -} - -@export() -@description('The type for a cognitive services account endpoint.') -type endpointType = { - @description('Type of the endpoint.') - name: string? - @description('The endpoint URI.') - endpoint: string? -} - -@export() -@description('The type of the secrets exported to the provided Key Vault.') -type secretsExportConfigurationType = { - @description('Required. The key vault name where to store the keys and connection strings generated by the modules.') - keyVaultResourceId: string - - @description('Optional. The name for the accessKey1 secret to create.') - accessKey1Name: string? - - @description('Optional. The name for the accessKey2 secret to create.') - accessKey2Name: string? -} diff --git a/infra/modules/keyVaultExport.bicep b/infra/modules/keyVaultExport.bicep deleted file mode 100644 index a54cc5576..000000000 --- a/infra/modules/keyVaultExport.bicep +++ /dev/null @@ -1,43 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. The name of the Key Vault to set the ecrets in.') -param keyVaultName string - -import { secretToSetType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('Required. The secrets to set in the Key Vault.') -param secretsToSet secretToSetType[] - -// ============= // -// Resources // -// ============= // - -resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = { - name: keyVaultName -} - -resource secrets 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = [ - for secret in secretsToSet: { - name: secret.name - parent: keyVault - properties: { - value: secret.value - } - } -] - -// =========== // -// Outputs // -// =========== // - -import { secretSetOutputType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' -@description('The references to the secrets exported to the provided Key Vault.') -output secretsSet secretSetOutputType[] = [ - #disable-next-line outputs-should-not-contain-secrets // Only returning the references, not a secret value - for index in range(0, length(secretsToSet ?? [])): { - secretResourceId: secrets[index].id - secretUri: secrets[index].properties.secretUri - secretUriWithVersion: secrets[index].properties.secretUriWithVersion - } -] From 169a654357f7e96fb8772ff01c4dc911b22e48e8 Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Mon, 25 Aug 2025 12:36:39 +0200 Subject: [PATCH 13/29] Refactor AI services module: remove deprecated deployments module and update references --- infra/main.bicep | 20 ++----------------- ...ts.bicep => ai-services-deployments.bicep} | 0 2 files changed, 2 insertions(+), 18 deletions(-) rename infra/modules/{ai-services-model-deployments.bicep => ai-services-deployments.bicep} (100%) diff --git a/infra/main.bicep b/infra/main.bicep index daac1c8f4..054e6fac8 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -127,22 +127,6 @@ var solutionSuffix = toLower(trim(replace( '' ))) -// Region pairs list based on article in [Azure regions list](https://learn.microsoft.com/azure/reliability/regions-list) -// var azureRegionPairs = { -// australiaeast: 'australiasoutheast' -// centralus: 'eastus2' -// eastasia: 'southeastasia' -// eastus: 'centralus' -// eastus2: 'centralus' -// japaneast: 'japanwest' -// northeurope: 'westeurope' -// southeastasia: 'eastasia' -// uksouth: 'ukwest' -// westeurope: 'northeurope' -// } -// // Paired location calculated based on 'location' parameter. This location will be used by applicable resources if `enableScalability` is set to `true` -// var pairedLocation = azureRegionPairs[location] - // Region pairs list based on article in [Azure Database for MySQL Flexible Server - Azure Regions](https://learn.microsoft.com/azure/mysql/flexible-server/overview#azure-regions) for supported high availability regions for CosmosDB. var cosmosDbZoneRedundantHaRegionPairs = { australiaeast: 'uksouth' //'southeastasia' @@ -280,7 +264,7 @@ var logAnalyticsWorkspaceResourceId = useExistingLogAnalytics : logAnalyticsWorkspace!.outputs.resourceId var logAnalyticsPrimarySharedKey = useExistingLogAnalytics ? existingLogAnalyticsWorkspace!.listKeys().primarySharedKey - : logAnalyticsWorkspace.outputs.primarySharedKey + : logAnalyticsWorkspace!.outputs!.primarySharedKey var logAnalyticsWorkspaceId = useExistingLogAnalytics ? existingLogAnalyticsWorkspace!.properties.customerId : logAnalyticsWorkspace!.outputs.logAnalyticsWorkspaceId @@ -1086,7 +1070,7 @@ resource existingAiFoundryAiServices 'Microsoft.CognitiveServices/accounts@2025- scope: resourceGroup(split(existingAiFoundryResourceId, '/')[2], split(existingAiFoundryResourceId, '/')[4]) } -module existingAiFoundryAiServicesDeployments 'modules/ai-services-model-deployments.bicep' = if (useExistingAiFoundry) { +module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.bicep' = if (useExistingAiFoundry) { name: take('module.ai-services-model-deployments.${existingAiFoundryAiServices.name}', 64) params: { name: existingAiFoundryAiServices.name diff --git a/infra/modules/ai-services-model-deployments.bicep b/infra/modules/ai-services-deployments.bicep similarity index 100% rename from infra/modules/ai-services-model-deployments.bicep rename to infra/modules/ai-services-deployments.bicep From efcf54f12d75155f96dbcbf6aed43a6ad9b103aa Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Mon, 25 Aug 2025 17:50:30 +0200 Subject: [PATCH 14/29] Refactor AI project parameters: rename existing AI Foundry resource ID for clarity and update related references --- infra/main.bicep | 49 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index 054e6fac8..676fedd8a 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -111,7 +111,7 @@ param enableTelemetry bool = true param existingLogAnalyticsWorkspaceId string = '' @description('Optional. Resource ID of an existing Ai Foundry AI Services resource.') -param existingAiFoundryResourceId string = '' +param existingAiFoundryAiProjectResourceId string = '' // ============== // // Variables // @@ -129,7 +129,7 @@ var solutionSuffix = toLower(trim(replace( // Region pairs list based on article in [Azure Database for MySQL Flexible Server - Azure Regions](https://learn.microsoft.com/azure/mysql/flexible-server/overview#azure-regions) for supported high availability regions for CosmosDB. var cosmosDbZoneRedundantHaRegionPairs = { - australiaeast: 'uksouth' //'southeastasia' + australiaeast: 'uksouth' centralus: 'eastus2' eastasia: 'southeastasia' eastus: 'centralus' @@ -942,7 +942,7 @@ var aiRelatedDnsZoneIndices = [ // =================================================== @batchSize(5) module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ - for (zone, i) in privateDnsZones: if (enablePrivateNetworking && (!useExistingAiFoundry || !contains( + for (zone, i) in privateDnsZones: if (enablePrivateNetworking && (!useExistingAiFoundryAiProject || !contains( aiRelatedDnsZoneIndices, i ))) { @@ -1050,10 +1050,14 @@ module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ // } // } -var useExistingAiFoundry = !empty(existingAiFoundryResourceId) -var aiFoundryAiServicesResourceName = useExistingAiFoundry - ? split(existingAiFoundryResourceId, '/')[8] +// resource id: /subscriptions//resourceGroups//providers/Microsoft.CognitiveServices/accounts//projects/ +var useExistingAiFoundryAiProject = !empty(existingAiFoundryAiProjectResourceId) +var aiFoundryAiServicesResourceName = useExistingAiFoundryAiProject + ? split(existingAiFoundryAiProjectResourceId, '/')[8] : 'aif-${solutionSuffix}' +var aiFoundryAiProjectResourceName = useExistingAiFoundryAiProject + ? split(existingAiFoundryAiProjectResourceId, '/')[10] + : 'proj-${solutionSuffix}' var aiFoundryAiServicesModelDeployment = { format: 'OpenAI' name: gptModelName @@ -1064,13 +1068,17 @@ var aiFoundryAiServicesModelDeployment = { } raiPolicyName: 'Microsoft.Default' } +var aiFoundryAiProjectDescription = 'AI Foundry Project' -resource existingAiFoundryAiServices 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = if (useExistingAiFoundry) { +resource existingAiFoundryAiServices 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = if (useExistingAiFoundryAiProject) { name: aiFoundryAiServicesResourceName - scope: resourceGroup(split(existingAiFoundryResourceId, '/')[2], split(existingAiFoundryResourceId, '/')[4]) + scope: resourceGroup( + split(existingAiFoundryAiProjectResourceId, '/')[2], + split(existingAiFoundryAiProjectResourceId, '/')[4] + ) } -module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.bicep' = if (useExistingAiFoundry) { +module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.bicep' = if (useExistingAiFoundryAiProject) { name: take('module.ai-services-model-deployments.${existingAiFoundryAiServices.name}', 64) params: { name: existingAiFoundryAiServices.name @@ -1109,7 +1117,7 @@ module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.b } } -module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-services/account:0.13.2' = if (!useExistingAiFoundry) { +module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-services/account:0.13.2' = if (!useExistingAiFoundryAiProject) { name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) params: { name: aiFoundryAiServicesResourceName @@ -1192,10 +1200,12 @@ module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-service } } -var aiFoundryAiProjectResourceName = 'proj-${solutionSuffix}' -var aiFoundryAiProjectDescription = 'AI Foundry Project' +resource existingAiFoundryAiServicesProject 'Microsoft.CognitiveServices/accounts/projects@2025-06-01' existing = if (useExistingAiFoundryAiProject) { + name: aiFoundryAiProjectResourceName + parent: existingAiFoundryAiServices +} -module aiFoundryAiServicesProject 'modules/ai-project.bicep' = { +module aiFoundryAiServicesProject 'modules/ai-project.bicep' = if (!useExistingAiFoundryAiProject) { name: take('module.ai-project.${aiFoundryAiProjectResourceName}', 64) params: { name: aiFoundryAiProjectResourceName @@ -1206,6 +1216,13 @@ module aiFoundryAiServicesProject 'modules/ai-project.bicep' = { } } +var aiFoundryAiProjectName = useExistingAiFoundryAiProject + ? existingAiFoundryAiServicesProject.name + : aiFoundryAiServicesProject!.outputs.name +var aiFoundryAiProjectEndpoint = useExistingAiFoundryAiProject + ? existingAiFoundryAiServicesProject!.properties.endpoints['AI Foundry API'] + : aiFoundryAiServicesProject!.outputs.apiEndpoint + // ========== Cosmos DB ========== // // WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db @@ -1453,7 +1470,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_OPENAI_ENDPOINT' - value: aiFoundryAiServicesProject.outputs.apiEndpoint + value: aiFoundryAiProjectEndpoint } { name: 'AZURE_OPENAI_MODEL_NAME' @@ -1485,7 +1502,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_AI_PROJECT_NAME' - value: aiFoundryAiServicesProject.outputs.name + value: aiFoundryAiProjectName } { name: 'FRONTEND_SITE_NAME' @@ -1493,7 +1510,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_AI_AGENT_ENDPOINT' - value: aiFoundryAiServicesProject!.outputs.apiEndpoint + value: aiFoundryAiProjectEndpoint } { name: 'AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME' From 53107c9f9677f74a32d384609bf2442a83fd631b Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Tue, 26 Aug 2025 11:10:30 +0200 Subject: [PATCH 15/29] Update .gitignore: add patterns to ignore Bicep and ARM local parameter files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 0f8c238ca..a1fefd2ca 100644 --- a/.gitignore +++ b/.gitignore @@ -458,3 +458,7 @@ __pycache__/ *.whl .azure .github/copilot-instructions.md + +# Bicep local files +*.local*.bicepparam +*.local*.parameters.json \ No newline at end of file From c6d59475b76300c9e75938ae4d6305404f815060 Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Tue, 26 Aug 2025 11:34:29 +0200 Subject: [PATCH 16/29] Refactor AI Foundry AI Services module: remove commented-out code and clarify AI Project resource ID --- infra/main.bicep | 89 +----------------------------------------------- 1 file changed, 1 insertion(+), 88 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index 676fedd8a..ede7c9639 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -964,100 +964,13 @@ module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ // ========== AI Foundry: AI Services ========== // // WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai -// //TODO: update to AVM module when AI Projects and AI Projects RBAC are supported -// module aiFoundryAiServices 'modules/ai-services.bicep' = if (aiFoundryAIservicesEnabled) { -// name: take('avm.res.cognitive-services.account.${aiFoundryAiServicesResourceName}', 64) -// params: { -// name: aiFoundryAiServicesResourceName -// location: azureAiServiceLocation -// tags: tags -// existingFoundryProjectResourceId: existingFoundryProjectResourceId -// projectName: aiFoundryAiServicesAiProjectResourceName -// projectDescription: 'AI Foundry Project' -// sku: 'S0' -// kind: 'AIServices' -// disableLocalAuth: true -// customSubDomainName: aiFoundryAiServicesResourceName -// apiProperties: { -// //staticsEnabled: false -// } -// networkAcls: { -// defaultAction: 'Allow' -// virtualNetworkRules: [] -// ipRules: [] -// } -// managedIdentities: { userAssignedResourceIds: [userAssignedIdentity!.outputs.resourceId] } //To create accounts or projects, you must enable a managed identity on your resource -// roleAssignments: [ -// { -// roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User -// principalId: userAssignedIdentity.outputs.principalId -// principalType: 'ServicePrincipal' -// } -// { -// roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' // Azure AI Developer -// principalId: userAssignedIdentity.outputs.principalId -// principalType: 'ServicePrincipal' -// } -// { -// roleDefinitionIdOrName: '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd' // Cognitive Services OpenAI User -// principalId: userAssignedIdentity.outputs.principalId -// principalType: 'ServicePrincipal' -// } -// ] -// // WAF aligned configuration for Monitoring -// diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null -// publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' -// privateEndpoints: (enablePrivateNetworking && empty(existingFoundryProjectResourceId)) -// ? ([ -// { -// name: 'pep-${aiFoundryAiServicesResourceName}' -// customNetworkInterfaceName: 'nic-${aiFoundryAiServicesResourceName}' -// subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] -// privateDnsZoneGroup: { -// privateDnsZoneGroupConfigs: [ -// { -// name: 'ai-services-dns-zone-cognitiveservices' -// privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.cognitiveServices]!.outputs.resourceId -// } -// { -// name: 'ai-services-dns-zone-openai' -// privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.openAI]!.outputs.resourceId -// } -// { -// name: 'ai-services-dns-zone-aiservices' -// privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.aiServices]!.outputs.resourceId -// } -// ] -// } -// } -// ]) -// : [] -// deployments: [ -// { -// name: aiFoundryAiServicesModelDeployment.name -// model: { -// format: aiFoundryAiServicesModelDeployment.format -// name: aiFoundryAiServicesModelDeployment.name -// version: aiFoundryAiServicesModelDeployment.version -// } -// raiPolicyName: aiFoundryAiServicesModelDeployment.raiPolicyName -// sku: { -// name: aiFoundryAiServicesModelDeployment.sku.name -// capacity: aiFoundryAiServicesModelDeployment.sku.capacity -// } -// } -// ] -// } -// } - -// resource id: /subscriptions//resourceGroups//providers/Microsoft.CognitiveServices/accounts//projects/ var useExistingAiFoundryAiProject = !empty(existingAiFoundryAiProjectResourceId) var aiFoundryAiServicesResourceName = useExistingAiFoundryAiProject ? split(existingAiFoundryAiProjectResourceId, '/')[8] : 'aif-${solutionSuffix}' var aiFoundryAiProjectResourceName = useExistingAiFoundryAiProject ? split(existingAiFoundryAiProjectResourceId, '/')[10] - : 'proj-${solutionSuffix}' + : 'proj-${solutionSuffix}' // AI Project resource id: /subscriptions//resourceGroups//providers/Microsoft.CognitiveServices/accounts//projects/ var aiFoundryAiServicesModelDeployment = { format: 'OpenAI' name: gptModelName From e16ac5fa17499170a5613ce93d66b82d0b1fe3bb Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Tue, 26 Aug 2025 12:40:52 +0200 Subject: [PATCH 17/29] Refactor AI services module: update aiServicesName assignment to handle existing project condition --- infra/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/main.bicep b/infra/main.bicep index ede7c9639..2c273631b 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -1125,7 +1125,7 @@ module aiFoundryAiServicesProject 'modules/ai-project.bicep' = if (!useExistingA location: azureAiServiceLocation tags: tags desc: aiFoundryAiProjectDescription - aiServicesName: aiFoundryAiServicesResourceName + aiServicesName: useExistingAiFoundryAiProject ? existingAiFoundryAiServices.name : aiFoundryAiServices!.outputs.name } } From b9b8f24aa6ecc486c77b664bfc5f78cdb15fc30c Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Tue, 26 Aug 2025 12:41:40 +0200 Subject: [PATCH 18/29] Refactor AI Foundry AI Services module: add comment for implicit dependencies in aiServicesName assignment --- infra/main.bicep | 1 + 1 file changed, 1 insertion(+) diff --git a/infra/main.bicep b/infra/main.bicep index 2c273631b..3b32fa521 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -1125,6 +1125,7 @@ module aiFoundryAiServicesProject 'modules/ai-project.bicep' = if (!useExistingA location: azureAiServiceLocation tags: tags desc: aiFoundryAiProjectDescription + //Implicit dependencies below aiServicesName: useExistingAiFoundryAiProject ? existingAiFoundryAiServices.name : aiFoundryAiServices!.outputs.name } } From f3f30f75b513070c6d6a0ccb7bda16892c789ec8 Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Tue, 26 Aug 2025 12:42:22 +0200 Subject: [PATCH 19/29] Refactor AI Foundry AI Services module: simplify aiServicesName assignment by removing conditional check --- infra/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/main.bicep b/infra/main.bicep index 3b32fa521..4e3bd49b1 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -1126,7 +1126,7 @@ module aiFoundryAiServicesProject 'modules/ai-project.bicep' = if (!useExistingA tags: tags desc: aiFoundryAiProjectDescription //Implicit dependencies below - aiServicesName: useExistingAiFoundryAiProject ? existingAiFoundryAiServices.name : aiFoundryAiServices!.outputs.name + aiServicesName: aiFoundryAiServices!.outputs.name } } From 072d6111fb6d3002a70bdc91776ab272f78690af Mon Sep 17 00:00:00 2001 From: Alvaro Guadamillas Date: Tue, 26 Aug 2025 16:22:19 +0200 Subject: [PATCH 20/29] Refactor AI Foundry AI Services module: streamline resource group and subscription ID assignment for existing AI projects --- infra/main.bicep | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index 4e3bd49b1..237815174 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -965,6 +965,12 @@ module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [ // WAF best practices for Open AI: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-openai var useExistingAiFoundryAiProject = !empty(existingAiFoundryAiProjectResourceId) +var aiFoundryAiServicesResourceGroupName = useExistingAiFoundryAiProject + ? split(existingAiFoundryAiProjectResourceId, '/')[4] + : 'rg-${solutionSuffix}' +var aiFoundryAiServicesSubscriptionId = useExistingAiFoundryAiProject + ? split(existingAiFoundryAiProjectResourceId, '/')[2] + : subscription().id var aiFoundryAiServicesResourceName = useExistingAiFoundryAiProject ? split(existingAiFoundryAiProjectResourceId, '/')[8] : 'aif-${solutionSuffix}' @@ -985,14 +991,12 @@ var aiFoundryAiProjectDescription = 'AI Foundry Project' resource existingAiFoundryAiServices 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = if (useExistingAiFoundryAiProject) { name: aiFoundryAiServicesResourceName - scope: resourceGroup( - split(existingAiFoundryAiProjectResourceId, '/')[2], - split(existingAiFoundryAiProjectResourceId, '/')[4] - ) + scope: resourceGroup(aiFoundryAiServicesSubscriptionId, aiFoundryAiServicesResourceGroupName) } module existingAiFoundryAiServicesDeployments 'modules/ai-services-deployments.bicep' = if (useExistingAiFoundryAiProject) { name: take('module.ai-services-model-deployments.${existingAiFoundryAiServices.name}', 64) + scope: resourceGroup(aiFoundryAiServicesSubscriptionId, aiFoundryAiServicesResourceGroupName) params: { name: existingAiFoundryAiServices.name deployments: [ From 70cc0e769ab4c2039086cb2ed7f8dd695234262b Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Tue, 26 Aug 2025 22:12:48 +0530 Subject: [PATCH 21/29] Refactor parameter files: rename existingFoundryProjectResourceId to existingAiFoundryAiProjectResourceId --- infra/main.parameters.json | 2 +- infra/main.waf.parameters.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/infra/main.parameters.json b/infra/main.parameters.json index 9c41f245d..51a67a7cf 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -35,7 +35,7 @@ "existingLogAnalyticsWorkspaceId": { "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" }, - "existingFoundryProjectResourceId": { + "existingAiFoundryAiProjectResourceId": { "value": "${AZURE_ENV_FOUNDRY_PROJECT_ID}" } } diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json index 0048a3224..1da6bfd32 100644 --- a/infra/main.waf.parameters.json +++ b/infra/main.waf.parameters.json @@ -50,7 +50,7 @@ "existingLogAnalyticsWorkspaceId": { "value": "${AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID}" }, - "existingFoundryProjectResourceId": { + "existingAiFoundryAiProjectResourceId": { "value": "${AZURE_ENV_FOUNDRY_PROJECT_ID}" } } From 5532fb1ac1268182e2cdc336f2664e0f198b4ba8 Mon Sep 17 00:00:00 2001 From: Roopan P M Date: Mon, 1 Sep 2025 12:09:34 +0530 Subject: [PATCH 22/29] bicep udpated post downmerge --- infra/main.bicep | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/infra/main.bicep b/infra/main.bicep index 994a02627..2cd2afb0a 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -52,6 +52,9 @@ param gptModelName string = 'gpt-4o' @description('Optional. Version of the GPT model to deploy. Defaults to 2024-08-06.') param gptModelVersion string = '2024-08-06' +@description('Optional. Version of the Azure OpenAI service to deploy. Defaults to 2025-01-01-preview.') +param azureopenaiVersion string = '2025-01-01-preview' + @minLength(1) @allowed([ 'Standard' @@ -1548,5 +1551,5 @@ output AZURE_AI_PROJECT_NAME string = aiFoundryAiProjectName output AZURE_AI_MODEL_DEPLOYMENT_NAME string = aiFoundryAiServicesModelDeployment.name // output APPLICATIONINSIGHTS_CONNECTION_STRING string = applicationInsights.outputs.connectionString output AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME string = aiFoundryAiServicesModelDeployment.name -output AZURE_AI_AGENT_ENDPOINT string = aiFoundryAiServices.outputs.aiProjectInfo.apiEndpoint +output AZURE_AI_AGENT_ENDPOINT string = aiFoundryAiProjectEndpoint output APP_ENV string = 'Prod' From 16a3ea8f2cc93697ec9471c87caad0561fdfbc99 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Mon, 1 Sep 2025 12:24:59 +0530 Subject: [PATCH 23/29] always enable public network access for Container App Environment and Web App --- infra/main.bicep | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index 2cd2afb0a..c792d7896 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -1247,7 +1247,7 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2 tags: tags enableTelemetry: enableTelemetry // WAF aligned configuration for Private Networking - publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' + publicNetworkAccess: 'Enabled' // Always enabling the public network access for Container App Environment internal: enablePrivateNetworking ? true : false infrastructureSubnetResourceId: enablePrivateNetworking ? virtualNetwork.?outputs.?subnetResourceIds[3] : null // WAF aligned configuration for Monitoring @@ -1508,7 +1508,7 @@ module webSite 'modules/web-sites.bicep' = { vnetRouteAllEnabled: enablePrivateNetworking ? true : false vnetImagePullEnabled: enablePrivateNetworking ? true : false virtualNetworkSubnetId: enablePrivateNetworking ? virtualNetwork!.outputs.subnetResourceIds[4] : null - publicNetworkAccess: enablePrivateNetworking ? 'Disabled' : 'Enabled' + publicNetworkAccess: 'Enabled' // Always enabling the public network access for Web App privateEndpoints: enablePrivateNetworking ? [ { From 8b7b2b8c1b2f97c3caa336729b3080286b33f2a2 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Mon, 1 Sep 2025 16:09:06 +0530 Subject: [PATCH 24/29] Remove unused private endpoint configurations and ensure public network access is enabled for Container App Environment and Web App. --- infra/main.bicep | 54 ++---------------------------------------------- 1 file changed, 2 insertions(+), 52 deletions(-) diff --git a/infra/main.bicep b/infra/main.bicep index c792d7896..695d480bb 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -917,8 +917,6 @@ var privateDnsZones = [ 'privatelink.openai.azure.com' 'privatelink.services.ai.azure.com' 'privatelink.documents.azure.com' - 'privatelink.${toLower(replace(location,' ',''))}.azurecontainerapps.io' - 'privatelink.azurewebsites.net' ] // DNS Zone Index Constants @@ -927,8 +925,6 @@ var dnsZoneIndex = { openAI: 1 aiServices: 2 cosmosDb: 3 - containerAppEnvironment: 4 - appService: 5 } // List of DNS zone indices that correspond to AI-related services. @@ -1247,8 +1243,8 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2 tags: tags enableTelemetry: enableTelemetry // WAF aligned configuration for Private Networking - publicNetworkAccess: 'Enabled' // Always enabling the public network access for Container App Environment - internal: enablePrivateNetworking ? true : false + publicNetworkAccess: 'Enabled' // Always enabling the publicNetworkAccess for Container App Environment + internal: false // Must be false when publicNetworkAccess is'Enabled' infrastructureSubnetResourceId: enablePrivateNetworking ? virtualNetwork.?outputs.?subnetResourceIds[3] : null // WAF aligned configuration for Monitoring appLogsConfiguration: enableMonitoring @@ -1282,43 +1278,12 @@ module containerAppEnvironment 'br/public:avm/res/app/managed-environment:0.11.2 } } -// Private Endpoint for Container App Environment -var privateEndpointContainerAppEnvironmentService = 'managedEnvironments' -module privateEndpointContainerAppEnvironment 'br:mcr.microsoft.com/bicep/avm/res/network/private-endpoint:0.11.0' = if (enablePrivateNetworking) { - name: take('avm.res.network.private-endpoint.app-environment.${solutionSuffix}', 64) - params: { - name: 'pep-${containerAppEnvironmentResourceName}' - location: location - tags: tags - enableTelemetry: enableTelemetry - subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] - customNetworkInterfaceName: 'nic-${containerAppEnvironmentResourceName}' - privateLinkServiceConnections: [ - { - name: '${last(split(containerAppEnvironment.outputs.resourceId, '/'))}-${privateEndpointContainerAppEnvironmentService}-0' - properties: { - groupIds: [privateEndpointContainerAppEnvironmentService] - privateLinkServiceId: containerAppEnvironment.outputs.resourceId - } - } - ] - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [ - { privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.containerAppEnvironment]!.outputs.resourceId } - ] - } - } -} - // ========== Backend Container App Service ========== // // WAF best practices for container apps: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/azure-container-apps // PSRule for Container App: https://azure.github.io/PSRule.Rules.Azure/en/rules/resource/#container-app var containerAppResourceName = 'ca-${solutionSuffix}' module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { name: take('avm.res.app.container-app.${containerAppResourceName}', 64) - dependsOn: [ - privateEndpointContainerAppEnvironment - ] params: { name: containerAppResourceName tags: tags @@ -1509,21 +1474,6 @@ module webSite 'modules/web-sites.bicep' = { vnetImagePullEnabled: enablePrivateNetworking ? true : false virtualNetworkSubnetId: enablePrivateNetworking ? virtualNetwork!.outputs.subnetResourceIds[4] : null publicNetworkAccess: 'Enabled' // Always enabling the public network access for Web App - privateEndpoints: enablePrivateNetworking - ? [ - { - name: 'pep-${webSiteResourceName}' - customNetworkInterfaceName: 'nic-${webSiteResourceName}' - privateDnsZoneGroup: { - privateDnsZoneGroupConfigs: [ - { privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.appService]!.outputs.resourceId } - ] - } - service: 'sites' - subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0] - } - ] - : null } } From 557f57d87925713a294ba2308d42a28ff5c92fac Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Mon, 1 Sep 2025 19:15:15 +0530 Subject: [PATCH 25/29] Update AZURE_OPENAI_ENDPOINT --- infra/main.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/main.bicep b/infra/main.bicep index 695d480bb..77b791f19 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -1356,7 +1356,7 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = { } { name: 'AZURE_OPENAI_ENDPOINT' - value: aiFoundryAiProjectEndpoint + value: 'https://${aiFoundryAiServicesResourceName}.openai.azure.com/' } { name: 'AZURE_OPENAI_MODEL_NAME' From a2f76b0213aabd72ea9a0e9b45cecce0e4cf923a Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Tue, 2 Sep 2025 09:28:59 +0530 Subject: [PATCH 26/29] fixed the unit test case issue in test_cosmos_memory.py --- src/backend/tests/context/test_cosmos_memory.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backend/tests/context/test_cosmos_memory.py b/src/backend/tests/context/test_cosmos_memory.py index 0467d9907..55cf263ce 100644 --- a/src/backend/tests/context/test_cosmos_memory.py +++ b/src/backend/tests/context/test_cosmos_memory.py @@ -25,6 +25,7 @@ def _fake_get_azure_credential(*_a, **_k): COSMOSDB_CONTAINER="mock-container", COSMOSDB_ENDPOINT="https://mock-endpoint", COSMOSDB_DATABASE="mock-database", + AZURE_CLIENT_ID="mock-client-id", ) sys.modules.setdefault("app_config", app_config_mod) From bdbf32504ca40fc705a2b88b6af7e1568a4a6a00 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Tue, 2 Sep 2025 15:36:04 +0530 Subject: [PATCH 27/29] Enhance documentation and configuration for Azure deployment parameters, including VM credentials and Azure Developer CLI requirements. --- docs/CustomizingAzdParameters.md | 2 ++ docs/DeploymentGuide.md | 56 +++++++++++++++++++++++--------- infra/main.bicep | 5 ++- infra/main.parameters.json | 4 +-- infra/main.waf.parameters.json | 4 +-- 5 files changed, 51 insertions(+), 20 deletions(-) diff --git a/docs/CustomizingAzdParameters.md b/docs/CustomizingAzdParameters.md index bc28fc345..79830249a 100644 --- a/docs/CustomizingAzdParameters.md +++ b/docs/CustomizingAzdParameters.md @@ -19,6 +19,8 @@ By default this template will use the environment name as the prefix to prevent | `AZURE_ENV_IMAGETAG` | string | `latest` | Docker image tag used for container deployments. | | `AZURE_ENV_ENABLE_TELEMETRY` | bool | `true` | Enables telemetry for monitoring and diagnostics. | | `AZURE_ENV_LOG_ANALYTICS_WORKSPACE_ID` | string | Guide to get your [Existing Workspace ID](/docs/re-use-log-analytics.md) | Set this if you want to reuse an existing Log Analytics Workspace instead of creating a new one. | +| `AZURE_ENV_VM_ADMIN_USERNAME` | string | `take(newGuid(), 20)` | The administrator username for the virtual machine. | +| `AZURE_ENV_VM_ADMIN_PASSWORD` | string | `newGuid()` | The administrator password for the virtual machine. | --- ## How to Set a Parameter diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index fb4fca41a..83c109e59 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -26,17 +26,41 @@ Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass This will allow the scripts to run for the current session without permanently changing your system's policy. +### **Azure Developer CLI (azd) Requirement** + +Ensure that you are using the latest version of the [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview). +The `azd` version must be **1.18.0 or higher**. + +Upgrade commands by OS: + +* **Windows (using winget):** + + ```bash + winget install microsoft.azd + ``` + +* **Linux (using apt):** + + ```bash + curl -fsSL https://aka.ms/install-azd.sh | bash + ``` + +* **macOS (using Homebrew):** + + ```bash + brew update && brew tap azure/azd && brew install azd + ``` + ## Deployment Options & Steps ### Sandbox or WAF Aligned Deployment Options The [`infra`](../infra) folder of the Multi Agent Solution Accelerator contains the [`main.bicep`](../infra/main.bicep) Bicep script, which defines all Azure infrastructure components for this solution. -When running `azd up`, you’ll now be prompted to choose between a **WAF-aligned configuration** and a **sandbox configuration** using a simple selection: +By default, the `azd up` command uses the `main.parameters.json` file to deploy the solution. This file is pre-configured for a **sandbox environment** — ideal for development and proof-of-concept scenarios, with minimal security and cost controls for rapid iteration. -- A **sandbox environment** — ideal for development and proof-of-concept scenarios, with minimal security and cost controls for rapid iteration. +For **production deployments**, the repository also provides [`main.waf.parameters.json`](../infra/main.waf.parameters.json), which applies a [Well-Architected Framework (WAF) aligned](https://learn.microsoft.com/en-us/azure/well-architected/) configuration. This option enables additional Azure best practices for reliability, security, cost optimization, operational excellence, and performance efficiency, such as: -- A **production deployments environment**, which applies a [Well-Architected Framework (WAF) aligned](https://learn.microsoft.com/en-us/azure/well-architected/) configuration. This option enables additional Azure best practices for reliability, security, cost optimization, operational excellence, and performance efficiency, such as: - Enhanced network security (e.g., Network protection with private endpoints) - Stricter access controls and managed identities - Logging, monitoring, and diagnostics enabled by default @@ -44,24 +68,26 @@ When running `azd up`, you’ll now be prompted to choose between a **WAF-aligne **How to choose your deployment configuration:** -When prompted during `azd up`: +* Use the default `main.parameters.json` file for a **sandbox/dev environment** +* For a **WAF-aligned, production-ready deployment**, copy the contents of `main.waf.parameters.json` into `main.parameters.json` before running `azd up` + +--- -![useWAFAlignedArchitecture](images/macae_waf_prompt.png) +### VM Credentials Configuration -- Select **`true`** to deploy a **WAF-aligned, production-ready environment** -- Select **`false`** to deploy a **lightweight sandbox/dev environment** +By default, the solution sets the VM administrator username and password from environment variables. +If you do not configure these values, a randomly generated GUID will be used for both the username and password. + +To set your own VM credentials before deployment, use: + +```sh +azd env set AZURE_ENV_VM_ADMIN_USERNAME +azd env set AZURE_ENV_VM_ADMIN_PASSWORD +``` > [!TIP] > Always review and adjust parameter values (such as region, capacity, security settings and log analytics workspace configuration) to match your organization’s requirements before deploying. For production, ensure you have sufficient quota and follow the principle of least privilege for all identities and role assignments. -> To reuse an existing Log Analytics workspace, update the existingWorkspaceResourceId field under the logAnalyticsWorkspaceConfiguration parameter in the .bicep file with the resource ID of your existing workspace. -For example: -``` -param logAnalyticsWorkspaceConfiguration = { - dataRetentionInDays: 30 - existingWorkspaceResourceId: '/subscriptions//resourceGroups//providers/Microsoft.OperationalInsights/workspaces/' -} -``` > [!IMPORTANT] > The WAF-aligned configuration is under active development. More Azure Well-Architected recommendations will be added in future updates. diff --git a/infra/main.bicep b/infra/main.bicep index 77b791f19..1fc9582c4 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -709,13 +709,16 @@ module maintenanceConfiguration 'br/public:avm/res/maintenance/maintenance-confi } var dataCollectionRulesResourceName = 'dcr-${solutionSuffix}' +var dataCollectionRulesLocation = useExistingLogAnalytics + ? existingLogAnalyticsWorkspace!.location + : logAnalyticsWorkspace!.outputs.location module windowsVmDataCollectionRules 'br/public:avm/res/insights/data-collection-rule:0.6.1' = if (enablePrivateNetworking && enableMonitoring) { name: take('avm.res.insights.data-collection-rule.${dataCollectionRulesResourceName}', 64) params: { name: dataCollectionRulesResourceName tags: tags enableTelemetry: enableTelemetry - location: location + location: dataCollectionRulesLocation dataCollectionRuleProperties: { kind: 'Windows' dataSources: { diff --git a/infra/main.parameters.json b/infra/main.parameters.json index 51a67a7cf..14965085a 100644 --- a/infra/main.parameters.json +++ b/infra/main.parameters.json @@ -24,10 +24,10 @@ "value": "${AZURE_ENV_MODEL_CAPACITY}" }, "backendContainerImageTag": { - "value": "${AZURE_ENV_IMAGE_TAG}" + "value": "${AZURE_ENV_IMAGE_TAG=latest}" }, "frontendContainerImageTag": { - "value": "${AZURE_ENV_IMAGE_TAG}" + "value": "${AZURE_ENV_IMAGE_TAG=latest}" }, "enableTelemetry": { "value": "${AZURE_ENV_ENABLE_TELEMETRY}" diff --git a/infra/main.waf.parameters.json b/infra/main.waf.parameters.json index 1da6bfd32..c6fd16c49 100644 --- a/infra/main.waf.parameters.json +++ b/infra/main.waf.parameters.json @@ -24,10 +24,10 @@ "value": "${AZURE_ENV_MODEL_CAPACITY}" }, "backendContainerImageTag": { - "value": "${AZURE_ENV_IMAGE_TAG}" + "value": "${AZURE_ENV_IMAGE_TAG=latest}" }, "frontendContainerImageTag": { - "value": "${AZURE_ENV_IMAGE_TAG}" + "value": "${AZURE_ENV_IMAGE_TAG=latest}" }, "enableTelemetry": { "value": "${AZURE_ENV_ENABLE_TELEMETRY}" From b339965bc1d4bfe4ca8f3fd0971638bba1dc04db Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Tue, 2 Sep 2025 15:39:34 +0530 Subject: [PATCH 28/29] Fix link formatting for main.parameters.json in Deployment Guide --- docs/DeploymentGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index 83c109e59..e41c4422c 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -57,7 +57,7 @@ Upgrade commands by OS: The [`infra`](../infra) folder of the Multi Agent Solution Accelerator contains the [`main.bicep`](../infra/main.bicep) Bicep script, which defines all Azure infrastructure components for this solution. -By default, the `azd up` command uses the `main.parameters.json` file to deploy the solution. This file is pre-configured for a **sandbox environment** — ideal for development and proof-of-concept scenarios, with minimal security and cost controls for rapid iteration. +By default, the `azd up` command uses the [`main.parameters.json`](../infra/main.parameters.json)` file to deploy the solution. This file is pre-configured for a **sandbox environment** — ideal for development and proof-of-concept scenarios, with minimal security and cost controls for rapid iteration. For **production deployments**, the repository also provides [`main.waf.parameters.json`](../infra/main.waf.parameters.json), which applies a [Well-Architected Framework (WAF) aligned](https://learn.microsoft.com/en-us/azure/well-architected/) configuration. This option enables additional Azure best practices for reliability, security, cost optimization, operational excellence, and performance efficiency, such as: From b3c771f77bd2ee7dc2d4815508ffffc4e9556e76 Mon Sep 17 00:00:00 2001 From: Abdul-Microsoft Date: Tue, 2 Sep 2025 15:41:14 +0530 Subject: [PATCH 29/29] Fix formatting issue in Deployment Guide for main.parameters.json reference --- docs/DeploymentGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeploymentGuide.md b/docs/DeploymentGuide.md index e41c4422c..7cc4aced2 100644 --- a/docs/DeploymentGuide.md +++ b/docs/DeploymentGuide.md @@ -57,7 +57,7 @@ Upgrade commands by OS: The [`infra`](../infra) folder of the Multi Agent Solution Accelerator contains the [`main.bicep`](../infra/main.bicep) Bicep script, which defines all Azure infrastructure components for this solution. -By default, the `azd up` command uses the [`main.parameters.json`](../infra/main.parameters.json)` file to deploy the solution. This file is pre-configured for a **sandbox environment** — ideal for development and proof-of-concept scenarios, with minimal security and cost controls for rapid iteration. +By default, the `azd up` command uses the [`main.parameters.json`](../infra/main.parameters.json) file to deploy the solution. This file is pre-configured for a **sandbox environment** — ideal for development and proof-of-concept scenarios, with minimal security and cost controls for rapid iteration. For **production deployments**, the repository also provides [`main.waf.parameters.json`](../infra/main.waf.parameters.json), which applies a [Well-Architected Framework (WAF) aligned](https://learn.microsoft.com/en-us/azure/well-architected/) configuration. This option enables additional Azure best practices for reliability, security, cost optimization, operational excellence, and performance efficiency, such as: