From 63c8d2654da228143e2fde7928c88ef151a81c96 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 19 Feb 2025 18:01:59 -0600 Subject: [PATCH] Fix Azure PostgreSQL AsExisting In bicep, it is not supported to set properties on "existing" resources. When using AsExisting on an Azure PostgreSQL resource, we are setting authConfig properties to enable/disable password and activeDirectory auth. This is causing errors when trying to deploy because the bicep is invalid. Fix this by not setting these properties on existing resources. Instead for activeDirectory/Entra ID auth, we will add the principle as an admin on the server. For password auth on an existing resource, we expect the user to pass the correct username/password parameters to connect to the database server. Fix #7694 --- .../AzurePostgresExtensions.cs | 28 ++++--- .../ExistingAzureResourceTests.cs | 84 +++++++++++++++++-- 2 files changed, 96 insertions(+), 16 deletions(-) diff --git a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs index 8e65138cd97..3e30ba121d1 100644 --- a/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs +++ b/src/Aspire.Hosting.Azure.PostgreSQL/AzurePostgresExtensions.cs @@ -394,14 +394,19 @@ private static void ConfigurePostgreSqlInfrastructure(AzureResourceInfrastructur keyVault.Name = kvNameParam; infrastructure.Add(keyVault); - postgres.AuthConfig = new PostgreSqlFlexibleServerAuthConfig() + // bicep doesn't allow for setting properties on existing resources. So we don't set auth properties here. + // The administratorLogin and administratorLoginPassword are expected to match what is already configured on the server + if (!postgres.IsExistingResource) { - ActiveDirectoryAuth = PostgreSqlFlexibleServerActiveDirectoryAuthEnum.Disabled, - PasswordAuth = PostgreSqlFlexibleServerPasswordAuthEnum.Enabled - }; + postgres.AuthConfig = new PostgreSqlFlexibleServerAuthConfig() + { + ActiveDirectoryAuth = PostgreSqlFlexibleServerActiveDirectoryAuthEnum.Disabled, + PasswordAuth = PostgreSqlFlexibleServerPasswordAuthEnum.Enabled + }; - postgres.AdministratorLogin = administratorLogin; - postgres.AdministratorLoginPassword = administratorLoginPassword; + postgres.AdministratorLogin = administratorLogin; + postgres.AdministratorLoginPassword = administratorLoginPassword; + } var secret = new KeyVaultSecret("connectionString") { @@ -430,11 +435,14 @@ private static void ConfigurePostgreSqlInfrastructure(AzureResourceInfrastructur } else { - postgres.AuthConfig = new PostgreSqlFlexibleServerAuthConfig() + if (!postgres.IsExistingResource) { - ActiveDirectoryAuth = PostgreSqlFlexibleServerActiveDirectoryAuthEnum.Enabled, - PasswordAuth = PostgreSqlFlexibleServerPasswordAuthEnum.Disabled - }; + postgres.AuthConfig = new PostgreSqlFlexibleServerAuthConfig() + { + ActiveDirectoryAuth = PostgreSqlFlexibleServerActiveDirectoryAuthEnum.Enabled, + PasswordAuth = PostgreSqlFlexibleServerPasswordAuthEnum.Disabled + }; + } var principalIdParameter = new ProvisioningParameter(AzureBicepResource.KnownParameters.PrincipalId, typeof(string)); infrastructure.Add(principalIdParameter); diff --git a/tests/Aspire.Hosting.Azure.Tests/ExistingAzureResourceTests.cs b/tests/Aspire.Hosting.Azure.Tests/ExistingAzureResourceTests.cs index 1ed5ce92dee..a999d72e907 100644 --- a/tests/Aspire.Hosting.Azure.Tests/ExistingAzureResourceTests.cs +++ b/tests/Aspire.Hosting.Azure.Tests/ExistingAzureResourceTests.cs @@ -778,12 +778,6 @@ param principalName string resource postgresSql 'Microsoft.DBforPostgreSQL/flexibleServers@2024-08-01' existing = { name: existingResourceName - properties: { - authConfig: { - activeDirectoryAuth: 'Enabled' - passwordAuth: 'Disabled' - } - } } resource postgreSqlFirewallRule_AllowAllAzureIps 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2024-08-01' = { @@ -815,6 +809,84 @@ param principalName string Assert.Equal(expectedBicep, BicepText); } + [Fact] + public async Task SupportsExistingPostgresSqlWithResourceGroupWithPasswordAuth() + { + using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish); + + var existingResourceName = builder.AddParameter("existingResourceName"); + var existingResourceGroupName = builder.AddParameter("existingResourceGroupName"); + var existingUserName = builder.AddParameter("existingUserName"); + var existingPassword = builder.AddParameter("existingPassword"); + + var postgresSql = builder.AddAzurePostgresFlexibleServer("postgresSql") + .PublishAsExisting(existingResourceName, existingResourceGroupName) + .WithPasswordAuthentication(existingUserName, existingPassword); + + var (ManifestNode, BicepText) = await ManifestUtils.GetManifestWithBicep(postgresSql.Resource); + + var expectedManifest = """ + { + "type": "azure.bicep.v1", + "connectionString": "{postgresSql.secretOutputs.connectionString}", + "path": "postgresSql.module.bicep", + "params": { + "administratorLogin": "{existingUserName.value}", + "administratorLoginPassword": "{existingPassword.value}", + "existingResourceName": "{existingResourceName.value}", + "keyVaultName": "" + }, + "scope": { + "resourceGroup": "{existingResourceGroupName.value}" + } + } + """; + + Assert.Equal(expectedManifest, ManifestNode.ToString()); + + var expectedBicep = """ + @description('The location for the resource(s) to be deployed.') + param location string = resourceGroup().location + + param existingResourceName string + + param administratorLogin string + + @secure() + param administratorLoginPassword string + + param keyVaultName string + + resource postgresSql 'Microsoft.DBforPostgreSQL/flexibleServers@2024-08-01' existing = { + name: existingResourceName + } + + resource postgreSqlFirewallRule_AllowAllAzureIps 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2024-08-01' = { + name: 'AllowAllAzureIps' + properties: { + endIpAddress: '0.0.0.0' + startIpAddress: '0.0.0.0' + } + parent: postgresSql + } + + resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = { + name: keyVaultName + } + + resource connectionString 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = { + name: 'connectionString' + properties: { + value: 'Host=${postgresSql.properties.fullyQualifiedDomainName};Username=${administratorLogin};Password=${administratorLoginPassword}' + } + parent: keyVault + } + """; + + output.WriteLine(BicepText); + Assert.Equal(expectedBicep, BicepText); + } + [Fact] public async Task SupportsExistingAzureSearchWithResourceGroup() {