From d4571f723bdd86114ca2a893258e4023d40eec80 Mon Sep 17 00:00:00 2001 From: rujche Date: Mon, 4 Nov 2024 22:38:03 +0800 Subject: [PATCH] Use to AVM to support MySql: Auth by managed identity and username & password. --- .../scaffold/templates/db-mysql.bicept | 88 ---- .../scaffold/templates/db-postgres.bicept | 81 ---- .../templates/host-containerapp.bicept | 415 ------------------ .../scaffold/templates/resources.bicept | 154 ++++++- 4 files changed, 148 insertions(+), 590 deletions(-) delete mode 100644 cli/azd/resources/scaffold/templates/db-mysql.bicept delete mode 100644 cli/azd/resources/scaffold/templates/db-postgres.bicept delete mode 100644 cli/azd/resources/scaffold/templates/host-containerapp.bicept diff --git a/cli/azd/resources/scaffold/templates/db-mysql.bicept b/cli/azd/resources/scaffold/templates/db-mysql.bicept deleted file mode 100644 index dcd9dad0618..00000000000 --- a/cli/azd/resources/scaffold/templates/db-mysql.bicept +++ /dev/null @@ -1,88 +0,0 @@ -{{define "db-mysql.bicep" -}} -param serverName string -param location string = resourceGroup().location -param tags object = {} - -param keyVaultName string -param identityName string - -param databaseUser string = 'mysqladmin' -param databaseName string = '{{.DatabaseName}}' -@secure() -param databasePassword string - -param allowAllIPsFirewall bool = false - -resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: identityName - location: location -} - -resource mysqlServer 'Microsoft.DBforMySQL/flexibleServers@2023-06-30' = { - location: location - tags: tags - name: serverName - sku: { - name: 'Standard_B1ms' - tier: 'Burstable' - } - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${userAssignedIdentity.id}': {} - } - } - properties: { - version: '8.0.21' - administratorLogin: databaseUser - administratorLoginPassword: databasePassword - storage: { - storageSizeGB: 128 - } - backup: { - backupRetentionDays: 7 - geoRedundantBackup: 'Disabled' - } - highAvailability: { - mode: 'Disabled' - } - } - - resource firewall_all 'firewallRules' = if (allowAllIPsFirewall) { - name: 'allow-all-IPs' - properties: { - startIpAddress: '0.0.0.0' - endIpAddress: '255.255.255.255' - } - } -} - -resource database 'Microsoft.DBforMySQL/flexibleServers/databases@2023-06-30' = { - parent: mysqlServer - name: databaseName - properties: { - // Azure defaults to UTF-8 encoding, override if required. - // charset: 'string' - // collation: 'string' - } -} - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { - name: keyVaultName -} - -resource dbPasswordKey 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { - parent: keyVault - name: 'databasePassword' - properties: { - value: databasePassword - } -} - -output databaseId string = database.id -output identityName string = userAssignedIdentity.name -output databaseHost string = mysqlServer.properties.fullyQualifiedDomainName -output databaseName string = databaseName -output databaseUser string = databaseUser -output databaseConnectionKey string = 'databasePassword' -{{ end}} diff --git a/cli/azd/resources/scaffold/templates/db-postgres.bicept b/cli/azd/resources/scaffold/templates/db-postgres.bicept deleted file mode 100644 index b6ebb5a87b8..00000000000 --- a/cli/azd/resources/scaffold/templates/db-postgres.bicept +++ /dev/null @@ -1,81 +0,0 @@ -{{define "db-postgres.bicep" -}} -param serverName string -param location string = resourceGroup().location -param tags object = {} - -param keyVaultName string - -param databaseUser string = 'psqladmin' -param databaseName string = '{{.DatabaseName}}' -@secure() -param databasePassword string - -param allowAllIPsFirewall bool = false - -resource postgreServer'Microsoft.DBforPostgreSQL/flexibleServers@2022-01-20-preview' = { - location: location - tags: tags - name: serverName - sku: { - name: 'Standard_B1ms' - tier: 'Burstable' - } - properties: { - version: '13' - administratorLogin: databaseUser - administratorLoginPassword: databasePassword - storage: { - storageSizeGB: 128 - } - backup: { - backupRetentionDays: 7 - geoRedundantBackup: 'Disabled' - } - highAvailability: { - mode: 'Disabled' - } - maintenanceWindow: { - customWindow: 'Disabled' - dayOfWeek: 0 - startHour: 0 - startMinute: 0 - } - } - - resource firewall_all 'firewallRules' = if (allowAllIPsFirewall) { - name: 'allow-all-IPs' - properties: { - startIpAddress: '0.0.0.0' - endIpAddress: '255.255.255.255' - } - } -} - -resource database 'Microsoft.DBforPostgreSQL/flexibleServers/databases@2022-01-20-preview' = { - parent: postgreServer - name: databaseName - properties: { - // Azure defaults to UTF-8 encoding, override if required. - // charset: 'string' - // collation: 'string' - } -} - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { - name: keyVaultName -} - -resource dbPasswordKey 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { - parent: keyVault - name: 'databasePassword' - properties: { - value: databasePassword - } -} - -output databaseId string = database.id -output databaseHost string = postgreServer.properties.fullyQualifiedDomainName -output databaseName string = databaseName -output databaseUser string = databaseUser -output databaseConnectionKey string = 'databasePassword' -{{ end}} diff --git a/cli/azd/resources/scaffold/templates/host-containerapp.bicept b/cli/azd/resources/scaffold/templates/host-containerapp.bicept deleted file mode 100644 index 9991fdea940..00000000000 --- a/cli/azd/resources/scaffold/templates/host-containerapp.bicept +++ /dev/null @@ -1,415 +0,0 @@ -{{define "host-containerapp.bicep" -}} -param name string -param location string = resourceGroup().location -param tags object = {} - -param identityName string -param containerRegistryName string -param containerAppsEnvironmentName string -param applicationInsightsName string -{{- if .DbCosmosMongo}} -@secure() -param cosmosDbConnectionString string -{{- end}} -{{- if (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity)}} -param postgresDatabaseId string -{{- end}} -{{- if (and .DbPostgres .DbPostgres.AuthUsingUsernamePassword)}} -param postgresDatabaseHost string -param postgresDatabaseName string -param postgresDatabaseUser string -@secure() -param postgresDatabasePassword string -{{- end}} -{{- if (and .DbMySql .DbMySql.AuthUsingManagedIdentity)}} -param mysqlDatabaseId string -param mysqlIdentityName string -{{- end}} -{{- if (and .DbMySql .DbMySql.AuthUsingUsernamePassword)}} -param mysqlDatabaseHost string -param mysqlDatabaseName string -param mysqlDatabaseUser string -@secure() -param mysqlDatabasePassword string -{{- end}} -{{- if (and .AzureServiceBus .AzureServiceBus.AuthUsingConnectionString)}} -@secure() -param azureServiceBusConnectionString string -{{- end}} -{{- if (and .AzureServiceBus .AzureServiceBus.AuthUsingManagedIdentity)}} -@secure() -param azureServiceBusNamespace string -{{- end}} -{{- if .DbRedis}} -param redisName string -{{- end}} -{{- if (and .Frontend .Frontend.Backends)}} -param apiUrls array -{{- end}} -{{- if (and .Backend .Backend.Frontends)}} -param allowedOrigins array -{{- end}} -param exists bool -@secure() -param appDefinition object -param currentTime string = utcNow() - -var appSettingsArray = filter(array(appDefinition.settings), i => i.name != '') -var secrets = map(filter(appSettingsArray, i => i.?secret != null), i => { - name: i.name - value: i.value - secretRef: i.?secretRef ?? take(replace(replace(toLower(i.name), '_', '-'), '.', '-'), 32) -}) -var env = map(filter(appSettingsArray, i => i.?secret == null), i => { - name: i.name - value: i.value -}) - -resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: identityName - location: location -} - -resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' existing = { - name: containerRegistryName -} - -resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' existing = { - name: containerAppsEnvironmentName -} - -resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = { - name: applicationInsightsName -} - -resource acrPullRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: containerRegistry - name: guid(subscription().id, resourceGroup().id, identity.id, 'acrPullRole') - properties: { - roleDefinitionId: subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d') - principalType: 'ServicePrincipal' - principalId: identity.properties.principalId - } -} - -module fetchLatestImage '../modules/fetch-container-image.bicep' = { - name: '${name}-fetch-image' - params: { - exists: exists - name: name - } -} -{{- if .DbRedis}} - -resource redis 'Microsoft.App/containerApps@2023-05-02-preview' = { - name: redisName - location: location - properties: { - environmentId: containerAppsEnvironment.id - configuration: { - service: { - type: 'redis' - } - } - template: { - containers: [ - { - image: 'redis' - name: 'redis' - } - ] - } - } -} -{{- end}} - -resource app 'Microsoft.App/containerApps@2023-05-02-preview' = { - name: name - location: location - tags: union(tags, {'azd-service-name': '{{.Name}}' }) - dependsOn: [ acrPullRole ] - identity: { - type: 'UserAssigned' - userAssignedIdentities: { '${identity.id}': {} } - } - properties: { - managedEnvironmentId: containerAppsEnvironment.id - configuration: { - {{- if ne .Port 0}} - ingress: { - external: true - targetPort: {{.Port}} - transport: 'auto' - {{- if (and .Backend .Backend.Frontends)}} - corsPolicy: { - allowedOrigins: union(allowedOrigins, [ - // define additional allowed origins here - ]) - allowedMethods: ['GET', 'PUT', 'POST', 'DELETE'] - } - {{- end}} - } - {{- end}} - registries: [ - { - server: '${containerRegistryName}.azurecr.io' - identity: identity.id - } - ] - secrets: union([ - {{- if .DbCosmosMongo}} - { - name: 'azure-cosmos-connection-string' - value: cosmosDbConnectionString - } - {{- end}} - {{- if (and .DbPostgres .DbPostgres.AuthUsingUsernamePassword)}} - { - name: 'postgres-db-pass' - value: postgresDatabasePassword - } - {{- end}} - {{- if (and .DbMySql .DbMySql.AuthUsingUsernamePassword)}} - { - name: 'mysql-db-pass' - value: mysqlDatabasePassword - } - {{- end}} - {{- if (and .AzureServiceBus .AzureServiceBus.AuthUsingConnectionString)}} - { - name: 'spring-cloud-azure-servicebus-connection-string' - value: azureServiceBusConnectionString - } - {{- end}} - ], - map(secrets, secret => { - name: secret.secretRef - value: secret.value - })) - } - template: { - containers: [ - { - image: fetchLatestImage.outputs.?containers[?0].?image ?? 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest' - name: 'main' - env: union([ - { - name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' - value: applicationInsights.properties.ConnectionString - } - {{- if .DbCosmosMongo}} - { - name: 'AZURE_COSMOS_MONGODB_CONNECTION_STRING' - secretRef: 'azure-cosmos-connection-string' - } - {{- end}} - {{- if (and .DbPostgres .DbPostgres.AuthUsingUsernamePassword)}} - { - name: 'POSTGRES_HOST' - value: postgresDatabaseHost - } - { - name: 'POSTGRES_PORT' - value: '5432' - } - { - name: 'POSTGRES_DATABASE' - value: postgresDatabaseName - } - { - name: 'POSTGRES_USERNAME' - value: postgresDatabaseUser - } - { - name: 'POSTGRES_PASSWORD' - secretRef: 'postgres-db-pass' - } - {{- end}} - {{- if (and .DbMySql .DbMySql.AuthUsingUsernamePassword)}} - { - name: 'MYSQL_HOST' - value: mysqlDatabaseHost - } - { - name: 'MYSQL_PORT' - value: '3306' - } - { - name: 'MYSQL_DATABASE' - value: mysqlDatabaseName - } - { - name: 'MYSQL_USERNAME' - value: mysqlDatabaseUser - } - { - name: 'MYSQL_PASSWORD' - secretRef: 'mysql-db-pass' - } - {{- end}} - {{- if (and .AzureServiceBus .AzureServiceBus.AuthUsingConnectionString)}} - { - name: 'SPRING_CLOUD_AZURE_SERVICEBUS_CONNECTION_STRING' - secretRef: 'spring-cloud-azure-servicebus-connection-string' - } - {{- end}} - {{- if (and .AzureServiceBus .AzureServiceBus.AuthUsingManagedIdentity)}} - { - name: 'SPRING_CLOUD_AZURE_SERVICEBUS_CONNECTION_STRING' - value: '' - } - { - name: 'SPRING_CLOUD_AZURE_SERVICEBUS_NAMESPACE' - value: azureServiceBusNamespace - } - { - name: 'SPRING_CLOUD_AZURE_SERVICEBUS_CREDENTIAL_MANAGEDIDENTITYENABLED' - value: 'true' - } - { - name: 'SPRING_CLOUD_AZURE_SERVICEBUS_CREDENTIAL_CLIENTID' - value: identity.properties.clientId - } - {{- end}} - {{- if .Frontend}} - {{- range $i, $e := .Frontend.Backends}} - { - name: '{{upper .Name}}_BASE_URL' - value: apiUrls[{{$i}}] - } - {{- end}} - {{- end}} - {{- if ne .Port 0}} - { - name: 'PORT' - value: '{{ .Port }}' - } - { - name: 'SERVER_PORT' - value: '{{ .Port }}' - } - {{- end}} - ], - env, - map(secrets, secret => { - name: secret.name - secretRef: secret.secretRef - })) - resources: { - cpu: json('1.0') - memory: '2.0Gi' - } - } - ] - {{- if .DbRedis}} - serviceBinds: [ - { - serviceId: redis.id - name: 'redis' - } - ] - {{- end}} - scale: { - minReplicas: 1 - maxReplicas: 10 - } - } - } -} -{{- if (or (and .DbMySql .DbMySql.AuthUsingManagedIdentity) (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity))}} - -resource linkerCreatorIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: '${name}-linker-creator-identity' - location: location -} - -resource linkerCreatorRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - scope: resourceGroup() - name: guid(subscription().id, resourceGroup().id, linkerCreatorIdentity.id, 'linkerCreatorRole') - properties: { - roleDefinitionId: subscriptionResourceId( - 'Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - principalType: 'ServicePrincipal' - principalId: linkerCreatorIdentity.properties.principalId - } -} -{{- end}} -{{- if (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity)}} - -resource appLinkToPostgres 'Microsoft.Resources/deploymentScripts@2023-08-01' = { - dependsOn: [ linkerCreatorRole ] - name: '${name}-link-to-postgres' - location: location - kind: 'AzureCLI' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${linkerCreatorIdentity.id}': {} - } - } - properties: { - azCliVersion: '2.63.0' - timeout: 'PT10M' - forceUpdateTag: currentTime - scriptContent: 'apk update; apk add g++; apk add unixodbc-dev; az extension add --name containerapp; az extension add --name serviceconnector-passwordless --upgrade; az containerapp connection create postgres-flexible --connection appLinkToPostgres --source-id ${app.id} --target-id ${postgresDatabaseId} --client-type springBoot --user-identity client-id=${identity.properties.clientId} subs-id=${subscription().subscriptionId} user-object-id=${linkerCreatorIdentity.properties.principalId} -c main --yes;' - cleanupPreference: 'OnSuccess' - retentionInterval: 'P1D' - } -} -{{- end}} -{{- if (and .DbMySql .DbMySql.AuthUsingManagedIdentity)}} - -resource appLinkToMySql 'Microsoft.Resources/deploymentScripts@2023-08-01' = { - dependsOn: [ linkerCreatorRole ] - name: '${name}-link-to-mysql' - location: location - kind: 'AzureCLI' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${linkerCreatorIdentity.id}': {} - } - } - properties: { - azCliVersion: '2.63.0' - timeout: 'PT10M' - forceUpdateTag: currentTime - scriptContent: 'apk update; apk add g++; apk add unixodbc-dev; az extension add --name containerapp; az extension add --name serviceconnector-passwordless --upgrade; az containerapp connection create mysql-flexible --connection appLinkToMySql --source-id ${app.id} --target-id ${mysqlDatabaseId} --client-type springBoot --user-identity client-id=${identity.properties.clientId} subs-id=${subscription().subscriptionId} user-object-id=${linkerCreatorIdentity.properties.principalId} mysql-identity-id=${mysqlIdentityName} -c main --yes;' - cleanupPreference: 'OnSuccess' - retentionInterval: 'P1D' - } -} -{{- end}} -{{- if (and .AzureServiceBus .AzureServiceBus.AuthUsingManagedIdentity) }} - -resource servicebus 'Microsoft.ServiceBus/namespaces@2022-01-01-preview' existing = { - name: azureServiceBusNamespace -} - -resource serviceBusReceiverRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { - name: guid(servicebus.id, '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0', identity.name) - scope: servicebus - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0') // Azure Service Bus Data Receiver - principalId: identity.properties.principalId - principalType: 'ServicePrincipal' - } -} - -resource serviceBusSenderRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { - name: guid(servicebus.id, '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39', identity.name) - scope: servicebus - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39') // Azure Service Bus Data Sender - principalId: identity.properties.principalId - principalType: 'ServicePrincipal' - } -} -{{end}} - -output defaultDomain string = containerAppsEnvironment.properties.defaultDomain -output name string = app.name -output uri string = 'https://${app.properties.configuration.ingress.fqdn}' -output id string = app.id -{{ end}} diff --git a/cli/azd/resources/scaffold/templates/resources.bicept b/cli/azd/resources/scaffold/templates/resources.bicept index 8ab889d9c23..b87f8c4d4bd 100644 --- a/cli/azd/resources/scaffold/templates/resources.bicept +++ b/cli/azd/resources/scaffold/templates/resources.bicept @@ -61,7 +61,7 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.4.5 name: '${abbrs.appManagedEnvironments}${resourceToken}' location: location zoneRedundant: false - {{- if (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity) }} + {{- if (or (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity) (and .DbMySql .DbMySql.AuthUsingManagedIdentity))}} roleAssignments: [ { principalId: connectionCreatorIdentity.outputs.principalId @@ -103,8 +103,8 @@ module cosmos 'br/public:avm/res/document-db/database-account:0.4.0' = { } } {{- end}} - {{- if .DbPostgres}} + var postgreSqlDatabaseName = '{{ .DbPostgres.DatabaseName }}' var postgreSqlDatabaseUser = 'psqladmin' module postgreServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:0.1.4' = { @@ -144,7 +144,69 @@ module postgreServer 'br/public:avm/res/db-for-postgre-sql/flexible-server:0.1.4 } } {{- end}} -{{- if (or (and .DbMySql .DbMySql.AuthUsingManagedIdentity) (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity))}} +{{- if .DbMySql}} + +var mysqlDatabaseName = '{{ .DbMySql.DatabaseName }}' +var mysqlDatabaseUser = 'mysqladmin' +{{- if (and .DbMySql .DbMySql.AuthUsingManagedIdentity) }} +module mysqlIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { + name: 'mysqlIdentity' + params: { + name: '${abbrs.managedIdentityUserAssignedIdentities}mysql-${resourceToken}' + location: location + roleAssignments: [ + { + principalId: connectionCreatorIdentity.outputs.principalId + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + ] + } +} +{{- end}} +module mysqlServer 'br/public:avm/res/db-for-my-sql/flexible-server:0.4.1' = { + name: 'mysqlServer' + params: { + // Required parameters + name: '${abbrs.dBforMySQLServers}${resourceToken}' + skuName: 'Standard_B1ms' + tier: 'Burstable' + // Non-required parameters + administratorLogin: mysqlDatabaseUser + administratorLoginPassword: mysqlDatabasePassword + geoRedundantBackup: 'Disabled' + firewallRules: [ + { + name: 'AllowAllIps' + startIpAddress: '0.0.0.0' + endIpAddress: '255.255.255.255' + } + ] + databases: [ + { + name: mysqlDatabaseName + } + ] + location: location + highAvailability: 'Disabled' + {{- if (and .DbMySql .DbMySql.AuthUsingManagedIdentity) }} + managedIdentities: { + userAssignedResourceIds: [ + mysqlIdentity.outputs.resourceId + ] + } + roleAssignments: [ + { + principalId: connectionCreatorIdentity.outputs.principalId + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + ] + {{- end}} + } +} +{{- end}} +{{- if (or (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity) (and .DbMySql .DbMySql.AuthUsingManagedIdentity))}} module connectionCreatorIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.2.1' = { name: 'connectionCreatorIdentity' @@ -170,7 +232,28 @@ module {{bicepName .Name}}CreateConnectionToPostgreSql 'br/public:avm/res/resour } runOnce: false retentionInterval: 'P1D' - scriptContent: 'apk update; apk add g++; apk add unixodbc-dev; az extension add --name containerapp; az extension add --name serviceconnector-passwordless --upgrade; az containerapp connection create postgres-flexible --connection appLinkToPostgres --source-id ${ {{bicepName .Name}}.outputs.resourceId} --target-id ${postgreServer.outputs.resourceId}/databases/${postgreSqlDatabaseName} --client-type springBoot --user-identity client-id=${ {{bicepName .Name}}Identity.outputs.clientId} subs-id=${subscription().subscriptionId} user-object-id=${connectionCreatorIdentity.outputs.principalId} -c main --yes;' + scriptContent: 'apk update; apk add g++; apk add unixodbc-dev; az extension add --name containerapp; az extension add --name serviceconnector-passwordless --upgrade; az containerapp connection create postgres-flexible --connection appConnectToPostgres --source-id ${ {{bicepName .Name}}.outputs.resourceId} --target-id ${postgreServer.outputs.resourceId}/databases/${postgreSqlDatabaseName} --client-type springBoot --user-identity client-id=${ {{bicepName .Name}}Identity.outputs.clientId} subs-id=${subscription().subscriptionId} user-object-id=${connectionCreatorIdentity.outputs.principalId} -c main --yes;' + } +} +{{- end}} +{{- end}} +{{- if (and .DbMySql .DbMySql.AuthUsingManagedIdentity) }} +{{- range .Services}} +module {{bicepName .Name}}CreateConnectionToMysql 'br/public:avm/res/resources/deployment-script:0.4.0' = { + name: '{{bicepName .Name}}CreateConnectionToMysql' + params: { + kind: 'AzureCLI' + name: '${abbrs.deploymentScript}{{bicepName .Name}}-connection-to-mysql-${resourceToken}' + azCliVersion: '2.63.0' + location: location + managedIdentities: { + userAssignedResourcesIds: [ + connectionCreatorIdentity.outputs.resourceId + ] + } + runOnce: false + retentionInterval: 'P1D' + scriptContent: 'apk update; apk add g++; apk add unixodbc-dev; az extension add --name containerapp; az extension add --name serviceconnector-passwordless --upgrade; az containerapp connection create mysql-flexible --connection appConnectToMysql --source-id ${ {{bicepName .Name}}.outputs.resourceId} --target-id ${mysqlServer.outputs.resourceId}/databases/${mysqlDatabaseName} --client-type springBoot --user-identity client-id=${ {{bicepName .Name}}Identity.outputs.clientId} subs-id=${subscription().subscriptionId} user-object-id=${connectionCreatorIdentity.outputs.principalId} mysql-identity-id=${mysqlIdentity.outputs.resourceId} -c main --yes;' } } {{- end}} @@ -315,7 +398,7 @@ module {{bicepName .Name}}Identity 'br/public:avm/res/managed-identity/user-assi params: { name: '${abbrs.managedIdentityUserAssignedIdentities}{{bicepName .Name}}-${resourceToken}' location: location - {{- if (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity) }} + {{- if (or (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity) (and .DbMySql .DbMySql.AuthUsingManagedIdentity))}} roleAssignments: [ { principalId: connectionCreatorIdentity.outputs.principalId @@ -383,6 +466,16 @@ module {{bicepName .Name}} 'br/public:avm/res/app/container-app:0.8.0' = { value: 'postgresql://${postgreSqlDatabaseUser}:${postgreSqlDatabasePassword}@${postgreServer.outputs.fqdn}:5432/${postgreSqlDatabaseName}' } {{- end}} + {{- if (and .DbMySql .DbMySql.AuthUsingUsernamePassword) }} + { + name: 'mysql-password' + value: mysqlDatabasePassword + } + { + name: 'mysql-db-url' + value: 'mysql://${mysqlDatabaseUser}:${mysqlDatabasePassword}@${mysqlServer.outputs.fqdn}:3306/${mysqlDatabaseName}' + } + {{- end}} {{- if .DbRedis}} { name: 'redis-pass' @@ -485,6 +578,46 @@ module {{bicepName .Name}} 'br/public:avm/res/app/container-app:0.8.0' = { secretRef: 'postgresql-password' } {{- end}} + {{- if .DbMySql}} + { + name: 'MYSQL_HOST' + value: mysqlServer.outputs.fqdn + } + { + name: 'MYSQL_DATABASE' + value: mysqlDatabaseName + } + { + name: 'MYSQL_PORT' + value: '3306' + } + { + name: 'SPRING_DATASOURCE_URL' + value: 'jdbc:mysql://${mysqlServer.outputs.fqdn}:3306/${mysqlDatabaseName}' + } + {{- end}} + {{- if (and .DbMySql .DbMySql.AuthUsingUsernamePassword) }} + { + name: 'MYSQL_URL' + secretRef: 'mysql-db-url' + } + { + name: 'MYSQL_USERNAME' + value: mysqlDatabaseUser + } + { + name: 'MYSQL_PASSWORD' + secretRef: 'mysql-password' + } + { + name: 'SPRING_DATASOURCE_USERNAME' + value: mysqlDatabaseUser + } + { + name: 'SPRING_DATASOURCE_PASSWORD' + secretRef: 'mysql-password' + } + {{- end}} {{- if .DbRedis}} { name: 'REDIS_HOST' @@ -646,7 +779,7 @@ module {{bicepName .Name}} 'br/public:avm/res/app/container-app:0.8.0' = { environmentResourceId: containerAppsEnvironment.outputs.resourceId location: location tags: union(tags, { 'azd-service-name': '{{.Name}}' }) - {{- if (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity) }} + {{- if (or (and .DbPostgres .DbPostgres.AuthUsingManagedIdentity) (and .DbMySql .DbMySql.AuthUsingManagedIdentity))}} roleAssignments: [ { principalId: connectionCreatorIdentity.outputs.principalId @@ -714,6 +847,12 @@ module keyVault 'br/public:avm/res/key-vault/vault:0.6.1' = { value: postgreSqlDatabasePassword } {{- end}} + {{- if (and .DbMySql .DbMySql.AuthUsingUsernamePassword) }} + { + name: 'mysql-password' + value: mysqlDatabasePassword + } + {{- end}} ] } } @@ -730,6 +869,9 @@ output AZURE_CACHE_REDIS_ID string = redis.outputs.resourceId {{- if .DbPostgres}} output AZURE_POSTGRES_FLEXIBLE_SERVER_ID string = postgreServer.outputs.resourceId {{- end}} +{{- if .DbMySql}} +output AZURE_MYSQL_FLEXIBLE_SERVER_ID string = mysqlServer.outputs.resourceId +{{- end}} {{- if .AzureEventHubs }} output AZURE_EVENT_HUBS_ID string = eventHubNamespace.outputs.resourceId {{- end}}