chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
param uniqueId string
|
||||
param prefix string
|
||||
param userAssignedIdentityResourceId string
|
||||
param userAssignedIdentityClientId string
|
||||
param openAiEndpoint string
|
||||
param openAiApiKey string
|
||||
param openAiApiVersion string = '2024-08-01-preview'
|
||||
param openAiModel string = 'gpt-4o'
|
||||
param applicationInsightsConnectionString string
|
||||
param containerRegistry string = '${prefix}acr${uniqueId}'
|
||||
param location string = resourceGroup().location
|
||||
param logAnalyticsWorkspaceName string
|
||||
param apiAppExists bool
|
||||
param emptyContainerImage string = 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
|
||||
param botAppId string
|
||||
@secure()
|
||||
param botPassword string
|
||||
param botTenantId string
|
||||
|
||||
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' existing = {
|
||||
name: logAnalyticsWorkspaceName
|
||||
}
|
||||
|
||||
// see https://azureossd.github.io/2023/01/03/Using-Managed-Identity-and-Bicep-to-pull-images-with-Azure-Container-Apps/
|
||||
resource containerAppEnv 'Microsoft.App/managedEnvironments@2023-11-02-preview' = {
|
||||
name: '${prefix}-containerAppEnv-${uniqueId}'
|
||||
location: location
|
||||
identity: {
|
||||
type: 'UserAssigned'
|
||||
userAssignedIdentities: {
|
||||
'${userAssignedIdentityResourceId}': {}
|
||||
}
|
||||
}
|
||||
properties: {
|
||||
appLogsConfiguration: {
|
||||
destination: 'log-analytics'
|
||||
logAnalyticsConfiguration: {
|
||||
customerId: logAnalyticsWorkspace.properties.customerId
|
||||
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When azd passes parameters, it will tell if apps were already created
|
||||
// In this case, we don't overwrite the existing image
|
||||
// See https://johnnyreilly.com/using-azd-for-faster-incremental-azure-container-app-deployments-in-azure-devops#the-does-your-service-exist-parameter
|
||||
module fetchLatestImageApi './fetch-container-image.bicep' = {
|
||||
name: 'api-app-image'
|
||||
params: {
|
||||
exists: apiAppExists
|
||||
name: '${prefix}-api-${uniqueId}'
|
||||
}
|
||||
}
|
||||
|
||||
resource apiContainerApp 'Microsoft.App/containerApps@2023-11-02-preview' = {
|
||||
name: '${prefix}-api-${uniqueId}'
|
||||
location: location
|
||||
tags: { 'azd-service-name': 'api' }
|
||||
identity: {
|
||||
type: 'UserAssigned'
|
||||
userAssignedIdentities: {
|
||||
'${userAssignedIdentityResourceId}': {}
|
||||
}
|
||||
}
|
||||
properties: {
|
||||
managedEnvironmentId: containerAppEnv.id
|
||||
configuration: {
|
||||
activeRevisionsMode: 'Single'
|
||||
ingress: {
|
||||
external: true
|
||||
targetPort: 80
|
||||
transport: 'auto'
|
||||
}
|
||||
registries: [
|
||||
{
|
||||
server: '${containerRegistry}.azurecr.io'
|
||||
identity: userAssignedIdentityResourceId
|
||||
}
|
||||
]
|
||||
}
|
||||
template: {
|
||||
scale: {
|
||||
minReplicas: 1
|
||||
maxReplicas: 1
|
||||
}
|
||||
containers: [
|
||||
{
|
||||
name: 'api'
|
||||
image: apiAppExists ? fetchLatestImageApi.outputs.containers[0].image : emptyContainerImage
|
||||
resources: {
|
||||
cpu: 1
|
||||
memory: '2Gi'
|
||||
}
|
||||
env: [
|
||||
{ name: 'AZURE_CLIENT_ID', value: userAssignedIdentityClientId }
|
||||
{ name: 'BOT_APP_ID', value: botAppId }
|
||||
{ name: 'BOT_PASSWORD', value: botPassword }
|
||||
{ name: 'BOT_TENANT_ID', value: botTenantId }
|
||||
{ name: 'APPLICATIONINSIGHTS_CONNECTIONSTRING', value: applicationInsightsConnectionString }
|
||||
{ name: 'APPLICATIONINSIGHTS_SERVICE_NAME', value: 'api' }
|
||||
{ name: 'AZURE_OPENAI_ENDPOINT', value: openAiEndpoint }
|
||||
{ name: 'AZURE_OPENAI_CHAT_DEPLOYMENT_NAME', value: openAiModel }
|
||||
{ name: 'AZURE_OPENAI_API_KEY', value: '' }
|
||||
{ name: 'AZURE_OPENAI_API_VERSION', value: openAiApiVersion }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output messagesEndpoint string = 'https://${apiContainerApp.properties.configuration.ingress.fqdn}/api/messages'
|
||||
output manifestUrl string = 'https://${apiContainerApp.properties.configuration.ingress.fqdn}/manifest'
|
||||
output homeUrl string = 'https://${apiContainerApp.properties.configuration.ingress.fqdn}'
|
||||
@@ -0,0 +1,29 @@
|
||||
param uniqueId string
|
||||
param prefix string
|
||||
param userAssignedIdentityPrincipalId string
|
||||
param acrName string = '${prefix}acr${uniqueId}'
|
||||
param location string = resourceGroup().location
|
||||
|
||||
resource acr 'Microsoft.ContainerRegistry/registries@2021-06-01-preview' = {
|
||||
name: acrName
|
||||
location: location
|
||||
sku: {
|
||||
name: 'Standard' // Choose between Basic, Standard, and Premium based on your needs
|
||||
}
|
||||
properties: {
|
||||
adminUserEnabled: false
|
||||
}
|
||||
}
|
||||
|
||||
resource acrPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
|
||||
name: guid(acr.id, userAssignedIdentityPrincipalId, 'acrpull')
|
||||
scope: acr
|
||||
properties: {
|
||||
roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') // Role definition ID for AcrPull
|
||||
principalId: userAssignedIdentityPrincipalId
|
||||
principalType: 'ServicePrincipal'
|
||||
}
|
||||
}
|
||||
|
||||
output acrName string = acrName
|
||||
output acrEndpoint string = acr.properties.loginServer
|
||||
@@ -0,0 +1,46 @@
|
||||
param uniqueId string
|
||||
param prefix string
|
||||
@secure()
|
||||
param userAssignedIdentityPrincipalId string
|
||||
param location string = resourceGroup().location
|
||||
param appInsightsName string = '${prefix}-appin-${uniqueId}'
|
||||
param logAnalyticsWorkspaceName string = '${prefix}-law-${uniqueId}'
|
||||
|
||||
// Create or reference an existing Log Analytics Workspace
|
||||
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2020-08-01' = {
|
||||
name: logAnalyticsWorkspaceName
|
||||
location: location
|
||||
properties: {
|
||||
sku: {
|
||||
name: 'PerGB2018'
|
||||
}
|
||||
retentionInDays: 30
|
||||
}
|
||||
}
|
||||
|
||||
// Create Application Insights resource linked to the Log Analytics Workspace
|
||||
resource applicationInsights 'Microsoft.Insights/components@2020-02-02-preview' = {
|
||||
name: appInsightsName
|
||||
location: location
|
||||
kind: 'web'
|
||||
properties: {
|
||||
Application_Type: 'web'
|
||||
WorkspaceResourceId: logAnalyticsWorkspace.id
|
||||
}
|
||||
}
|
||||
|
||||
// Assign "Monitoring Metrics Publisher" role to the Application Insights resource
|
||||
resource acrPullRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
|
||||
name: guid(applicationInsights.id, userAssignedIdentityPrincipalId, 'appinsightsPublisher')
|
||||
scope: applicationInsights
|
||||
properties: {
|
||||
roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') // Role definition ID for Monitoring Metrics Publisher
|
||||
principalId: userAssignedIdentityPrincipalId
|
||||
principalType: 'ServicePrincipal'
|
||||
}
|
||||
}
|
||||
|
||||
output logAnalyticsWorkspaceId string = logAnalyticsWorkspace.id
|
||||
output logAnalyticsWorkspaceName string = logAnalyticsWorkspaceName
|
||||
output applicationInsightsInstrumentationKey string = applicationInsights.properties.InstrumentationKey
|
||||
output applicationInsightsConnectionString string = applicationInsights.properties.ConnectionString
|
||||
@@ -0,0 +1,37 @@
|
||||
param uniqueId string
|
||||
param prefix string
|
||||
param messagesEndpoint string
|
||||
param botAppId string
|
||||
param botTenantId string
|
||||
|
||||
resource bot 'Microsoft.BotService/botServices@2023-09-15-preview' = {
|
||||
name: '${prefix}bot${uniqueId}'
|
||||
location: 'global'
|
||||
sku: {
|
||||
name: 'F0'
|
||||
}
|
||||
kind: 'azurebot'
|
||||
properties: {
|
||||
iconUrl: 'https://docs.botframework.com/static/devportal/client/images/bot-framework-default.png'
|
||||
displayName: '${prefix}bot${uniqueId}'
|
||||
endpoint: messagesEndpoint
|
||||
description: 'Bot created by Bicep'
|
||||
publicNetworkAccess: 'Enabled'
|
||||
msaAppId: botAppId
|
||||
msaAppTenantId: botTenantId
|
||||
msaAppType: 'SingleTenant'
|
||||
msaAppMSIResourceId: null
|
||||
schemaTransformationVersion: '1.3'
|
||||
isStreamingSupported: false
|
||||
}
|
||||
}
|
||||
|
||||
// Connect the bot service to Microsoft Teams
|
||||
resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
|
||||
parent: bot
|
||||
location: 'global'
|
||||
name: 'MsTeamsChannel'
|
||||
properties: {
|
||||
channelName: 'MsTeamsChannel'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
param exists bool
|
||||
param name string
|
||||
|
||||
resource existingApp 'Microsoft.App/containerApps@2023-05-01' existing = if (exists) {
|
||||
name: name
|
||||
}
|
||||
|
||||
output containers array = exists ? existingApp.properties.template.containers : []
|
||||
@@ -0,0 +1,141 @@
|
||||
targetScope = 'subscription'
|
||||
|
||||
@minLength(1)
|
||||
@maxLength(64)
|
||||
@description('Name of the environment that can be used as part of naming resource convention')
|
||||
param environmentName string
|
||||
|
||||
@description('The current user ID, to assign RBAC permissions to')
|
||||
param currentUserId string
|
||||
|
||||
// Main deployment parameters
|
||||
param prefix string = 'copstsk'
|
||||
@minLength(1)
|
||||
@description('Primary location for all resources')
|
||||
param location string
|
||||
|
||||
@minLength(1)
|
||||
@description('Name of the Azure OpenAI resource')
|
||||
param openAIName string
|
||||
|
||||
@minLength(1)
|
||||
@description('Name of the Azure Resource Group where the OpenAI resource is located')
|
||||
param openAIResourceGroupName string
|
||||
|
||||
@description('Azure Bot app ID')
|
||||
param botAppId string
|
||||
@description('Azure Bot app password')
|
||||
@secure()
|
||||
param botPassword string
|
||||
@description('Azure Bot tenant ID')
|
||||
param botTenantId string
|
||||
|
||||
param openAIModel string
|
||||
param openAIApiVersion string
|
||||
param apiAppExists bool = false
|
||||
param runningOnGh string = ''
|
||||
|
||||
var tags = {
|
||||
'azd-env-name': environmentName
|
||||
}
|
||||
|
||||
resource rg 'Microsoft.Resources/resourceGroups@2022-09-01' = {
|
||||
name: 'rg-${environmentName}'
|
||||
location: location
|
||||
tags: tags
|
||||
}
|
||||
|
||||
var uniqueId = uniqueString(rg.id)
|
||||
var principalType = empty(runningOnGh) ? 'User' : 'ServicePrincipal'
|
||||
|
||||
module uami './uami.bicep' = {
|
||||
name: 'uami'
|
||||
scope: rg
|
||||
params: {
|
||||
uniqueId: uniqueId
|
||||
prefix: prefix
|
||||
location: location
|
||||
}
|
||||
}
|
||||
|
||||
module appin './appin.bicep' = {
|
||||
name: 'appin'
|
||||
scope: rg
|
||||
params: {
|
||||
uniqueId: uniqueId
|
||||
prefix: prefix
|
||||
location: location
|
||||
userAssignedIdentityPrincipalId: uami.outputs.principalId
|
||||
}
|
||||
}
|
||||
|
||||
module acrModule './acr.bicep' = {
|
||||
name: 'acr'
|
||||
scope: rg
|
||||
params: {
|
||||
uniqueId: uniqueId
|
||||
prefix: prefix
|
||||
userAssignedIdentityPrincipalId: uami.outputs.principalId
|
||||
location: location
|
||||
}
|
||||
}
|
||||
|
||||
module openAI './openAI.bicep' = {
|
||||
name: 'openAI'
|
||||
scope: resourceGroup(openAIResourceGroupName)
|
||||
params: {
|
||||
openAIName: openAIName
|
||||
userAssignedIdentityPrincipalId: uami.outputs.principalId
|
||||
}
|
||||
}
|
||||
|
||||
module aca './aca.bicep' = {
|
||||
name: 'aca'
|
||||
scope: rg
|
||||
params: {
|
||||
uniqueId: uniqueId
|
||||
prefix: prefix
|
||||
userAssignedIdentityResourceId: uami.outputs.identityId
|
||||
containerRegistry: acrModule.outputs.acrName
|
||||
location: location
|
||||
logAnalyticsWorkspaceName: appin.outputs.logAnalyticsWorkspaceName
|
||||
applicationInsightsConnectionString: appin.outputs.applicationInsightsConnectionString
|
||||
openAiApiKey: '' // Force ManId, otherwise set openAI.listKeys().key1
|
||||
openAiEndpoint: openAI.outputs.openAIEndpoint
|
||||
openAiModel: openAIModel
|
||||
openAiApiVersion: openAIApiVersion
|
||||
userAssignedIdentityClientId: uami.outputs.clientId
|
||||
apiAppExists: apiAppExists
|
||||
botAppId: botAppId
|
||||
botPassword: botPassword
|
||||
botTenantId: botTenantId
|
||||
}
|
||||
}
|
||||
|
||||
module bot 'bot.bicep' = {
|
||||
name: 'bot'
|
||||
scope: rg
|
||||
params: {
|
||||
uniqueId: uniqueId
|
||||
prefix: prefix
|
||||
botAppId: botAppId
|
||||
botTenantId: botTenantId
|
||||
messagesEndpoint: aca.outputs.messagesEndpoint
|
||||
}
|
||||
}
|
||||
|
||||
// These outputs are copied by azd to .azure/<env name>/.env file
|
||||
// post provision script will use these values, too
|
||||
output AZURE_RESOURCE_GROUP string = rg.name
|
||||
output APPLICATIONINSIGHTS_CONNECTIONSTRING string = appin.outputs.applicationInsightsConnectionString
|
||||
output AZURE_TENANT_ID string = subscription().tenantId
|
||||
output AZURE_USER_ASSIGNED_IDENTITY_ID string = uami.outputs.identityId
|
||||
output AZURE_CONTAINER_REGISTRY_ENDPOINT string = acrModule.outputs.acrEndpoint
|
||||
output AZURE_OPENAI_MODEL string = openAIModel
|
||||
output AZURE_OPENAI_ENDPOINT string = openAI.outputs.openAIEndpoint
|
||||
output AZURE_OPENAI_API_VERSION string = openAIApiVersion
|
||||
output ENDPOINT_URL string = aca.outputs.messagesEndpoint
|
||||
output MANIFEST_URL string = aca.outputs.manifestUrl
|
||||
output HOME_URL string = aca.outputs.homeUrl
|
||||
output BOT_APP_ID string = botAppId
|
||||
output BOT_TENANT_ID string = botTenantId
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"environmentName": {
|
||||
"value": "${AZURE_ENV_NAME}"
|
||||
},
|
||||
"currentUserId": {
|
||||
"value": "${AZURE_PRINCIPAL_ID}"
|
||||
},
|
||||
"runningOnGh": {
|
||||
"value": "${GITHUB_ACTIONS}"
|
||||
},
|
||||
"location": {
|
||||
"value": "${AZURE_LOCATION}"
|
||||
},
|
||||
"openAiName": {
|
||||
"value": "${AZURE_OPENAI_NAME}"
|
||||
},
|
||||
"openAiResourceGroupName": {
|
||||
"value": "${AZURE_OPENAI_RG}"
|
||||
},
|
||||
"openAIModel": {
|
||||
"value": "${AZURE_OPENAI_MODEL=gpt-4o}"
|
||||
},
|
||||
"openAIApiVersion": {
|
||||
"value": "${AZURE_OPENAI_API_VERSION=2024-08-01-preview}"
|
||||
},
|
||||
"apiAppExists": {
|
||||
"value": "${SERVICE_API_RESOURCE_EXISTS=false}"
|
||||
},
|
||||
"botAppId": {
|
||||
"value": "${BOT_APPID}"
|
||||
},
|
||||
"botPassword": {
|
||||
"value": "${BOT_PASSWORD}"
|
||||
},
|
||||
"botTenantId": {
|
||||
"value": "${BOT_TENANT_ID}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
targetScope = 'resourceGroup'
|
||||
|
||||
param openAIName string
|
||||
param userAssignedIdentityPrincipalId string
|
||||
|
||||
resource openAI 'Microsoft.CognitiveServices/accounts@2022-03-01' existing = {
|
||||
name: openAIName
|
||||
}
|
||||
|
||||
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
|
||||
name: guid(openAI.id, userAssignedIdentityPrincipalId, 'Cognitive Services OpenAI User')
|
||||
scope: openAI
|
||||
properties: {
|
||||
roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd') // Role definition ID for Cognitive Services OpenAI User
|
||||
principalId: userAssignedIdentityPrincipalId
|
||||
principalType: 'ServicePrincipal'
|
||||
}
|
||||
}
|
||||
|
||||
output openAIEndpoint string = openAI.properties.endpoint
|
||||
@@ -0,0 +1,13 @@
|
||||
param uniqueId string
|
||||
param prefix string
|
||||
param location string = resourceGroup().location
|
||||
param identityName string = '${prefix}uami${uniqueId}'
|
||||
|
||||
resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
|
||||
name: identityName
|
||||
location: location
|
||||
}
|
||||
|
||||
output identityId string = userAssignedIdentity.id
|
||||
output clientId string = userAssignedIdentity.properties.clientId
|
||||
output principalId string = userAssignedIdentity.properties.principalId
|
||||
Reference in New Issue
Block a user