Skip to content

Commit 38109c3

Browse files
Obsolete connection strings for Azure services (#90)
* Obsolete connection strings for Azure services, instead using Azure.Identity exclusively. * Doc edits.
1 parent b5f96cc commit 38109c3

5 files changed

Lines changed: 46 additions & 50 deletions

File tree

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -176,19 +176,20 @@ and currently exposes the format of the file which, as mentioned above, should b
176176
```xml
177177
<add name="AzureAppConfig"
178178
[mode|@prefix|@stripPrefix|tokenPattern|@escapeExpandedValues|@optional=false]
179-
(@endpoint="https://your-appconfig-store.azconfig.io" | @connectionString="Endpoint=https://your-appconfig-store.azconfig.io;Id=XXXXXXXXXX;Secret=XXXXXXXXXX")
179+
@endpoint="https://your-appconfig-store.azconfig.io"
180180
[@keyFilter="string"]
181181
[@labelFilter="label"]
182182
[@acceptDateTime="DateTimeOffset"]
183183
[@useAzureKeyVault="bool"]
184184
type="Microsoft.Configuration.ConfigurationBuilders.AzureAppConfigurationBuilder, Microsoft.Configuration.ConfigurationBuilders.AzureAppConfig" />
185185
```
186186
[AppConfiguration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview) is a new offering from Azure, currently in preview. If you
187-
wish to use this new service for managing your configuration, then use this AzureAppConfigurationBuilder. Either `endpoint` or `connectionString` are
188-
required, but all other attributes are optional. If both `endpoint` and `connectionString` are used, then preference is given to the connection string.
189-
It is however, __strongly__ encouraged to use `endpoint` with a managed service identity in Azure.
187+
wish to use this new service for managing your configuration, then use this AzureAppConfigurationBuilder. `endpoint` is
188+
required, but all other attributes are optional.
189+
Previous iterations of this config builder allowed for a `connectionString` to connect to the
190+
App Configuration service. This method is no longer allowed, and this config builder now exclusively uses [DefaultAzureCredential](https://docs.microsoft.com/en-us/dotnet/api/azure.identity.defaultazurecredential)
191+
from the Azure.Identity package to handle credentials for connecting to the service.
190192
* `endpoint` - This specifies the AppConfiguration store to connect to.
191-
* `connectionString` - This specifies the AppConfiguration store to connect to, along with the Id and Secret necessary to access the service.
192193
* `keyFilter` - Use this to select a set of configuration values matching a certain key pattern.
193194
* `labelFilter` - Only retrieve configuration values that match a certain label.
194195
* `acceptDateTime` - Instead of versioning ala Azure Key Vault, AppConfiguration uses timestamps. Use this attribute to go back in time
@@ -202,21 +203,20 @@ It is however, __strongly__ encouraged to use `endpoint` with a managed service
202203
<add name="AzureKeyVault"
203204
[mode|@prefix|@stripPrefix|tokenPattern|@escapeExpandedValues|@optional=false]
204205
(@vaultName="MyVaultName" | @uri="https://MyVaultName.vault.azure.net")
205-
[@connectionString="connection string"]
206206
[@version="secrets version"]
207207
[@preloadSecretNames="true"]
208208
type="Microsoft.Configuration.ConfigurationBuilders.AzureKeyVaultConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Azure" />
209209
```
210-
If your secrets are kept in Azure Key Vault, then this config builder is for you. There are three additional attributes for this config builder. The `vaultName` is
211-
required. The other attributes allow you some manual control about which vault to connect to, but are only necessary if the application is not running in an
212-
environment that works magically with `Microsoft.Azure.Services.AppAuthentication`. The Azure Services Authentication library is used to automatically pick
213-
up connection information from the execution environment if possible, but you can override that feature by providing a connection string instead.
214-
* `vaultName` - This is a required attribute. It specifies the name of the vault in your Azure subscription from which to read key/value pairs.
215-
* `connectionString` - A connection string usable by [AzureServiceTokenProvider](https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication#connection-string-support)
216-
* `uri` - Connect to other Key Vault providers with this attribute. If not specified, Azure is the assumed Vault provider. If the uri _is_specified, then `vaultName` is no longer a required parameter.
210+
If your secrets are kept in Azure Key Vault, then this config builder is for you. There are three additional attributes for this config builder. The `vaultName`
211+
(or `uri`) is required. Previous iterations of this config builder allowed for a `connectionString` as a way to supply credential information for connecting to
212+
Azure Key Vault. This method is no longer allowed as it is not a supported scenario for the current `Azure.Identity` SDK which is used for connecting
213+
to Azure services. Instead, this iteration of the config builder exclusively uses [DefaultAzureCredential](https://docs.microsoft.com/en-us/dotnet/api/azure.identity.defaultazurecredential)
214+
from the `Azure.Identity` package to handle credentials for connecting to Azure Key Vault.
215+
* `vaultName` - This (or `uri`) is a required attribute. It specifies the name of the vault in your Azure subscription from which to read key/value pairs.
216+
* `uri` - Connect to non-Azure Key Vault providers with this attribute. If not specified, Azure is the assumed Vault provider. If the uri _is_ specified, then `vaultName` is no longer a required parameter.
217217
* `version` - Azure Key Vault provides a versioning feature for secrets. If this is specified, the builder will only retrieve secrets matching this version.
218-
* `preloadSecretNames` - By default, this builder will query __all__ the key names in the key vault when it is initialized. If this is a concern, set
219-
this attribute to 'false', and secrets will be retrieved one at a time. This could also be useful if the vault allows "Get" access but not
218+
* `preloadSecretNames` - By default, this builder will query __all__ the key names in the key vault when it is initialized to improve performance. If this is
219+
a concern, set this attribute to 'false', and secrets will be retrieved one at a time. This could also be useful if the vault allows "Get" access but not
220220
"List" access. (NOTE: Disabling preload is incompatible with Greedy mode.)
221221
Tip: Azure Key Vault uses random per-secret Guid assignments for versioning, which makes specifying a secret `version` tag on this builder rather
222222
limiting, as it will only ever update one config value. To make version handling more useful, V2 of this builder takes advantage of the new key-updating

src/Azure/AzureKeyVaultConfigBuilder.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@ public class AzureKeyVaultConfigBuilder : KeyValueConfigBuilder
2222
{
2323
#pragma warning disable CS1591 // No xml comments for tag literals.
2424
public const string vaultNameTag = "vaultName";
25-
public const string connectionStringTag = "connectionString";
25+
public const string connectionStringTag = "connectionString"; // obsolete
2626
public const string uriTag = "uri";
2727
public const string versionTag = "version";
2828
public const string preloadTag = "preloadSecretNames";
2929
#pragma warning restore CS1591 // No xml comments for tag literals.
3030

3131
private string _vaultName;
32-
private string _connectionString;
3332
private string _uri;
3433
private string _version;
3534
private bool _preload;
@@ -79,8 +78,14 @@ protected override void LazyInitialize(string name, NameValueCollection config)
7978
}
8079
_uri = _uri.TrimEnd(new char[] { '/' });
8180

82-
_connectionString = UpdateConfigSettingWithAppSettings(connectionStringTag);
83-
_connectionString = String.IsNullOrWhiteSpace(_connectionString) ? null : _connectionString;
81+
if (config[connectionStringTag] != null)
82+
{
83+
// A connection string was given. Connection strings are no longer supported. Azure.Identity is the preferred way to
84+
// authenticate, and that library has various mechanisms other than a plain text connection string in config to obtain
85+
// the necessary client credentials for connecting to Azure.
86+
// Be noisy about this even if optional, as it is a fundamental misconfiguration going forward.
87+
throw new ArgumentException("AzureKeyVaultConfigBuilder no longer supports connection strings as of version 2.", connectionStringTag);
88+
}
8489

8590
// Connect to KeyVault
8691
try

src/AzureAppConfig/AzureAppConfigurationBuilder.cs

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,14 @@ public class AzureAppConfigurationBuilder : KeyValueConfigBuilder
2828

2929
#pragma warning disable CS1591 // No xml comments for tag literals.
3030
public const string endpointTag = "endpoint";
31-
public const string connectionStringTag = "connectionString";
31+
public const string connectionStringTag = "connectionString"; // obsolete
3232
public const string keyFilterTag = "keyFilter";
3333
public const string labelFilterTag = "labelFilter";
3434
public const string dateTimeFilterTag = "acceptDateTime";
3535
public const string useKeyVaultTag = "useAzureKeyVault";
3636
#pragma warning restore CS1591 // No xml comments for tag literals.
3737

3838
private Uri _endpoint;
39-
private string _connectionString;
4039
private string _keyFilter;
4140
private string _labelFilter;
4241
private DateTimeOffset _dateTimeFilter;
@@ -83,40 +82,33 @@ protected override void LazyInitialize(string name, NameValueCollection config)
8382
if (_useKeyVault)
8483
_kvClientCache = new ConcurrentDictionary<Uri, SecretClient>(EqualityComparer<Uri>.Default);
8584

86-
// Always allow 'connectionString' to override black magic. But we expect this to be null most of the time.
87-
_connectionString = UpdateConfigSettingWithAppSettings(connectionStringTag);
88-
if (String.IsNullOrWhiteSpace(_connectionString))
85+
// Config Store Endpoint
86+
string uri = UpdateConfigSettingWithAppSettings(endpointTag);
87+
if (!String.IsNullOrWhiteSpace(uri))
8988
{
90-
_connectionString = null;
91-
92-
// Use MSI Connector instead.
93-
string uri = UpdateConfigSettingWithAppSettings(endpointTag);
94-
if (!String.IsNullOrWhiteSpace(uri))
89+
try
9590
{
96-
try
97-
{
98-
_endpoint = new Uri(uri);
99-
_client = new ConfigurationClient(_endpoint, new DefaultAzureCredential());
100-
}
101-
catch (Exception ex)
102-
{
103-
if (!Optional)
104-
throw new ArgumentException($"Exception encountered while creating connection to Azure App Configuration store.", ex);
105-
}
91+
_endpoint = new Uri(uri);
92+
_client = new ConfigurationClient(_endpoint, new DefaultAzureCredential());
10693
}
107-
else
94+
catch (Exception ex)
10895
{
109-
throw new ArgumentException($"An endpoint URI or connection string must be provided for connecting to Azure App Configuration service via the '{endpointTag}' or '{connectionStringTag}' attributes.");
96+
if (!Optional)
97+
throw new ArgumentException($"Exception encountered while creating connection to Azure App Configuration store.", ex);
11098
}
11199
}
112100
else
113101
{
114-
// If we get here, then we should try to connect with a connection string.
115-
try
116-
{
117-
_client = new ConfigurationClient(_connectionString);
118-
}
119-
catch (Exception e) when (Optional && ((e.InnerException is System.Net.Http.HttpRequestException) || (e.InnerException is UnauthorizedAccessException))) { }
102+
throw new ArgumentException($"An endpoint URI must be provided for connecting to Azure App Configuration service via the '{endpointTag}' attribute.");
103+
}
104+
105+
if (config[connectionStringTag] != null)
106+
{
107+
// A connection string was given. Connection strings are no longer supported. Azure.Identity is the preferred way to
108+
// authenticate, and that library has various mechanisms other than a plain text connection string in config to obtain
109+
// the necessary client credentials for connecting to Azure.
110+
// Be noisy about this even if optional, as it is a fundamental misconfiguration going forward.
111+
throw new ArgumentException("AzureAppConfigurationBuilder no longer supports connection strings.", connectionStringTag);
120112
}
121113

122114
// At this point we've got all our ducks in a row and are ready to go. And we know that

src/packages/ConfigurationBuilders.Azure.nupkg/tools/Net471/Install.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ $keyVaultConfigBuilder = [BuilderDescription]@{
1414
AllowedParameters=@( $keyValueCommonParameters +
1515
[ParameterDescription]@{ Name="vaultName"; IsRequired=$false; DefaultValue="[VaultName]" },
1616
[ParameterDescription]@{ Name="uri"; IsRequired=$false },
17-
[ParameterDescription]@{ Name="connectionString"; IsRequired=$false },
17+
[ParameterDescription]@{ Name="connectionString"; IsRequired=$false }, # Obsolete, but don't complain about it here. Still preserve it so people can revert back to the version that allows this.
1818
[ParameterDescription]@{ Name="version"; IsRequired=$false },
1919
[ParameterDescription]@{ Name="preloadSecretNames"; IsRequired=$false });
2020
}

src/packages/ConfigurationBuilders.AzureAppConfiguration.nupkg/tools/Net471/Install.ps1

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ $keyVaultConfigBuilder = [BuilderDescription]@{
1212
Version="$assemblyVersion$";
1313
DefaultName="AzureAppConfig";
1414
AllowedParameters=@( $keyValueCommonParameters +
15-
[ParameterDescription]@{ Name="endpoint"; IsRequired=$false; DefaultValue="[Config_Store_Endpoint_Url]" },
16-
[ParameterDescription]@{ Name="connectionString"; IsRequired=$false },
15+
[ParameterDescription]@{ Name="endpoint"; IsRequired=$true; DefaultValue="[Config_Store_Endpoint_Url]" },
1716
[ParameterDescription]@{ Name="keyFilter"; IsRequired=$false },
1817
[ParameterDescription]@{ Name="labelFilter"; IsRequired=$false },
1918
[ParameterDescription]@{ Name="acceptDateTime"; IsRequired=$false };

0 commit comments

Comments
 (0)