diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs index 8025246ec88321..59cbbcb574e32a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs @@ -12,10 +12,20 @@ namespace Microsoft.Extensions.Configuration.EnvironmentVariables /// public class EnvironmentVariablesConfigurationProvider : ConfigurationProvider { + // Connection string prefixes for various services. These prefixes are used to identify connection strings in environment variables. + // az webapp config connection-string set: https://learn.microsoft.com/en-us/cli/azure/webapp/config/connection-string?view=azure-cli-latest#az-webapp-config-connection-string-set + // Environment variables and app settings in Azure App Service: https://learn.microsoft.com/en-us/azure/app-service/reference-app-settings?tabs=kudu%2Cdotnet#variable-prefixes private const string MySqlServerPrefix = "MYSQLCONNSTR_"; private const string SqlAzureServerPrefix = "SQLAZURECONNSTR_"; private const string SqlServerPrefix = "SQLCONNSTR_"; private const string CustomConnectionStringPrefix = "CUSTOMCONNSTR_"; + private const string PostgreSqlServerPrefix = "POSTGRESQLCONNSTR_"; + private const string ApiHubPrefix = "APIHUBCONNSTR_"; + private const string DocDbPrefix = "DOCDBCONNSTR_"; + private const string EventHubPrefix = "EVENTHUBCONNSTR_"; + private const string NotificationHubPrefix = "NOTIFICATIONHUBCONNSTR_"; + private const string RedisCachePrefix = "REDISCACHECONNSTR_"; + private const string ServiceBusPrefix = "SERVICEBUSCONNSTR_"; private readonly string _prefix; private readonly string _normalizedPrefix; @@ -83,6 +93,34 @@ internal void Load(IDictionary envVariables) { HandleMatchedConnectionStringPrefix(data, SqlServerPrefix, "System.Data.SqlClient", key, value); } + else if (key.StartsWith(PostgreSqlServerPrefix, StringComparison.OrdinalIgnoreCase)) + { + HandleMatchedConnectionStringPrefix(data, PostgreSqlServerPrefix, "Npgsql", key, value); + } + else if (key.StartsWith(ApiHubPrefix, StringComparison.OrdinalIgnoreCase)) + { + HandleMatchedConnectionStringPrefix(data, ApiHubPrefix, null, key, value); + } + else if (key.StartsWith(DocDbPrefix, StringComparison.OrdinalIgnoreCase)) + { + HandleMatchedConnectionStringPrefix(data, DocDbPrefix, null, key, value); + } + else if (key.StartsWith(EventHubPrefix, StringComparison.OrdinalIgnoreCase)) + { + HandleMatchedConnectionStringPrefix(data, EventHubPrefix, null, key, value); + } + else if (key.StartsWith(NotificationHubPrefix, StringComparison.OrdinalIgnoreCase)) + { + HandleMatchedConnectionStringPrefix(data, NotificationHubPrefix, null, key, value); + } + else if (key.StartsWith(RedisCachePrefix, StringComparison.OrdinalIgnoreCase)) + { + HandleMatchedConnectionStringPrefix(data, RedisCachePrefix, null, key, value); + } + else if (key.StartsWith(ServiceBusPrefix, StringComparison.OrdinalIgnoreCase)) + { + HandleMatchedConnectionStringPrefix(data, ServiceBusPrefix, null, key, value); + } else if (key.StartsWith(CustomConnectionStringPrefix, StringComparison.OrdinalIgnoreCase)) { HandleMatchedConnectionStringPrefix(data, CustomConnectionStringPrefix, null, key, value); diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs index bf74d11775dcfe..6f0c600c1f5fd4 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs @@ -325,5 +325,61 @@ private sealed class MyOptions public int Number { get; set; } public string Text { get; set; } } + + [Fact] + public void LoadsPostgreSqlConnectionStrings() + { + var dic = new Hashtable() + { + {"POSTGRESQLCONNSTR_db1", "Host=server1;Database=db1;Username=root;Password=password;"}, + }; + var envConfigSrc = new EnvironmentVariablesConfigurationProvider(null); + + envConfigSrc.Load(dic); + + Assert.Equal("Host=server1;Database=db1;Username=root;Password=password;", envConfigSrc.Get("ConnectionStrings:db1")); + Assert.Equal("Npgsql", envConfigSrc.Get("ConnectionStrings:db1_ProviderName")); + } + + [Fact] + public void LoadsAzureServiceConnectionStrings() + { + var dic = new Hashtable() + { + {"APIHUBCONNSTR_api1", "Endpoint=https://api1.azure.com;ApiKey=key1;"}, + {"DOCDBCONNSTR_docdb1", "AccountEndpoint=https://docdb1.documents.azure.com;AccountKey=key1;"}, + {"EVENTHUBCONNSTR_eventhub1", "Endpoint=sb://eventhub1.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=key1;"}, + {"NOTIFICATIONHUBCONNSTR_notification1", "Endpoint=sb://notification1.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=key1;"}, + {"REDISCACHECONNSTR_redis1", "redis1.redis.cache.windows.net:6380,password=key1,ssl=True,abortConnect=False"}, + {"SERVICEBUSCONNSTR_servicebus1", "Endpoint=sb://servicebus1.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=key1;"}, + }; + var envConfigSrc = new EnvironmentVariablesConfigurationProvider(null); + + envConfigSrc.Load(dic); + + // API Hub + Assert.Equal("Endpoint=https://api1.azure.com;ApiKey=key1;", envConfigSrc.Get("ConnectionStrings:api1")); + Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:api1_ProviderName")); + + // DocDB (Cosmos DB) + Assert.Equal("AccountEndpoint=https://docdb1.documents.azure.com;AccountKey=key1;", envConfigSrc.Get("ConnectionStrings:docdb1")); + Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:docdb1_ProviderName")); + + // Event Hub + Assert.Equal("Endpoint=sb://eventhub1.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=key1;", envConfigSrc.Get("ConnectionStrings:eventhub1")); + Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:eventhub1_ProviderName")); + + // Notification Hub + Assert.Equal("Endpoint=sb://notification1.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=key1;", envConfigSrc.Get("ConnectionStrings:notification1")); + Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:notification1_ProviderName")); + + // Redis Cache + Assert.Equal("redis1.redis.cache.windows.net:6380,password=key1,ssl=True,abortConnect=False", envConfigSrc.Get("ConnectionStrings:redis1")); + Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:redis1_ProviderName")); + + // Service Bus + Assert.Equal("Endpoint=sb://servicebus1.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=key1;", envConfigSrc.Get("ConnectionStrings:servicebus1")); + Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:servicebus1_ProviderName")); + } } }