Skip to content

Merge main into preview #564

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions build/install-dotnet.ps1
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Installs .NET 6 and .NET 7 for CI/CD environment
# Installs .NET 6, .NET 7, and .NET 8 for CI/CD environment
# see: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#examples

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;

&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 6.0

&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 7.0
&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 7.0

&([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 8.0
2 changes: 1 addition & 1 deletion examples/ConfigStoreDemo/ConfigStoreDemo.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<IsPackable>false</IsPackable>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
Expand Down
8 changes: 4 additions & 4 deletions examples/ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.10.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
<PackageReference Include="Azure.Identity" Version="1.12.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions examples/ConsoleApplication/ConsoleApplication.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<PropertyGroup>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Import Project="..\..\build\NugetProperties.props" />

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<Description>Microsoft.Azure.AppConfiguration.AspNetCore allows developers to use Microsoft Azure App Configuration service as a configuration source in their applications. This package adds additional features for ASP.NET Core applications to the existing package Microsoft.Extensions.Configuration.AzureAppConfiguration.</Description>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
Expand Down Expand Up @@ -34,7 +34,8 @@

<PropertyGroup>
<CodeAnalysisRuleSet>..\..\AzureAppConfigurationRules.ruleset</CodeAnalysisRuleSet>
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Import Project="..\..\build\NugetProperties.props" />

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<Description>Microsoft.Azure.AppConfiguration.Functions.Worker allows developers to use the Microsoft Azure App Configuration service as a configuration source in their applications. This package adds additional features to the existing package Microsoft.Extensions.Configuration.AzureAppConfiguration for .NET Azure Functions running in an isolated process.</Description>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
Expand Down Expand Up @@ -37,7 +37,8 @@

<PropertyGroup>
<CodeAnalysisRuleSet>..\..\AzureAppConfigurationRules.ruleset</CodeAnalysisRuleSet>
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,12 @@ public async Task<bool> TryRefreshAsync(CancellationToken cancellationToken)

return false;
}
catch (FormatException fe)
{
_logger.LogWarning(LogHelper.BuildRefreshFailedDueToFormattingErrorMessage(fe.Message));

return false;
}

return true;
}
Expand Down Expand Up @@ -635,6 +641,7 @@ exception is KeyVaultReferenceException ||
exception is TimeoutException ||
exception is OperationCanceledException ||
exception is InvalidOperationException ||
exception is FormatException ||
((exception as AggregateException)?.InnerExceptions?.Any(e =>
e is RequestFailedException ||
e is OperationCanceledException) ?? false)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,12 @@ public AzureKeyVaultKeyValueAdapter(AzureKeyVaultSecretProvider secretProvider)
/// returns the keyname and actual value
public async Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(ConfigurationSetting setting, Uri endpoint, Logger logger, CancellationToken cancellationToken)
{
KeyVaultSecretReference secretRef;

// Content validation
try
{
secretRef = JsonSerializer.Deserialize<KeyVaultSecretReference>(setting.Value);
}
catch (JsonException e)
{
throw CreateKeyVaultReferenceException("Invalid Key Vault reference.", setting, e, null);
}
string secretRefUri = ParseSecretReferenceUri(setting);

// Uri validation
if (string.IsNullOrEmpty(secretRef.Uri) || !Uri.TryCreate(secretRef.Uri, UriKind.Absolute, out Uri secretUri) || !KeyVaultSecretIdentifier.TryCreate(secretUri, out KeyVaultSecretIdentifier secretIdentifier))
if (string.IsNullOrEmpty(secretRefUri) || !Uri.TryCreate(secretRefUri, UriKind.Absolute, out Uri secretUri) || !KeyVaultSecretIdentifier.TryCreate(secretUri, out KeyVaultSecretIdentifier secretIdentifier))
{
throw CreateKeyVaultReferenceException("Invalid Key vault secret identifier.", setting, null, secretRef);
throw CreateKeyVaultReferenceException("Invalid Key vault secret identifier.", setting, null, secretRefUri);
}

string secret;
Expand All @@ -55,11 +45,11 @@ public async Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(Con
}
catch (Exception e) when (e is UnauthorizedAccessException || (e.Source?.Equals(AzureIdentityAssemblyName, StringComparison.OrdinalIgnoreCase) ?? false))
{
throw CreateKeyVaultReferenceException(e.Message, setting, e, secretRef);
throw CreateKeyVaultReferenceException(e.Message, setting, e, secretRefUri);
}
catch (Exception e) when (e is RequestFailedException || ((e as AggregateException)?.InnerExceptions?.All(e => e is RequestFailedException) ?? false))
{
throw CreateKeyVaultReferenceException("Key vault error.", setting, e, secretRef);
throw CreateKeyVaultReferenceException("Key vault error.", setting, e, secretRefUri);
}

return new KeyValuePair<string, string>[]
Expand All @@ -68,15 +58,15 @@ public async Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(Con
};
}

KeyVaultReferenceException CreateKeyVaultReferenceException(string message, ConfigurationSetting setting, Exception inner, KeyVaultSecretReference secretRef = null)
KeyVaultReferenceException CreateKeyVaultReferenceException(string message, ConfigurationSetting setting, Exception inner, string secretRefUri = null)
{
return new KeyVaultReferenceException(message, inner)
{
Key = setting.Key,
Label = setting.Label,
Etag = setting.ETag.ToString(),
ErrorCode = (inner as RequestFailedException)?.ErrorCode,
SecretIdentifier = secretRef?.Uri
SecretIdentifier = secretRefUri
};
}

Expand Down Expand Up @@ -107,5 +97,50 @@ public bool NeedsRefresh()
{
return _secretProvider.ShouldRefreshKeyVaultSecrets();
}

private string ParseSecretReferenceUri(ConfigurationSetting setting)
{
string secretRefUri = null;

try
{
var reader = new Utf8JsonReader(System.Text.Encoding.UTF8.GetBytes(setting.Value));

if (reader.Read() && reader.TokenType != JsonTokenType.StartObject)
{
throw CreateKeyVaultReferenceException(ErrorMessages.InvalidKeyVaultReference, setting, null, null);
}

while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (reader.TokenType != JsonTokenType.PropertyName)
{
continue;
}

if (reader.GetString() == KeyVaultConstants.SecretReferenceUriJsonPropertyName)
{
if (reader.Read() && reader.TokenType == JsonTokenType.String)
{
secretRefUri = reader.GetString();
}
else
{
throw CreateKeyVaultReferenceException(ErrorMessages.InvalidKeyVaultReference, setting, null, null);
}
}
else
{
reader.Skip();
}
}
}
catch (JsonException e)
{
throw CreateKeyVaultReferenceException(ErrorMessages.InvalidKeyVaultReference, setting, e, null);
}

return secretRefUri;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.AzureKeyVault
internal class KeyVaultConstants
{
public const string ContentType = "application/vnd.microsoft.appconfig.keyvaultref+json";

public const string SecretReferenceUriJsonPropertyName = "uri";
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal class LoggingConstants
public const string RefreshFailedDueToKeyVaultError = "A refresh operation failed while resolving a Key Vault reference.";
public const string PushNotificationUnregisteredEndpoint = "Ignoring the push notification received for the unregistered endpoint";
public const string FallbackClientLookupError = "Failed to perform fallback client lookup.";
public const string RefreshFailedDueToFormattingError = "A refresh operation failed due to a formatting error.";

// Successful update, debug log level
public const string RefreshKeyValueRead = "Key-value read from App Configuration.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,59 @@ public static bool TryCreatePushNotification(this EventGridEvent eventGridEvent,

if (Uri.TryCreate(eventGridEvent.Subject, UriKind.Absolute, out Uri resourceUri))
{
JsonElement eventGridEventData;
string syncToken = null;

try
{
eventGridEventData = JsonDocument.Parse(eventGridEvent.Data.ToString()).RootElement;
var reader = new Utf8JsonReader(System.Text.Encoding.UTF8.GetBytes(eventGridEvent.Data.ToString()));

if (reader.Read() && reader.TokenType != JsonTokenType.StartObject)
{
return false;
}

while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (reader.TokenType != JsonTokenType.PropertyName)
{
continue;
}

if (reader.GetString() == SyncTokenPropertyName)
{
if (reader.Read() && reader.TokenType == JsonTokenType.String)
{
syncToken = reader.GetString();
}
else
{
return false;
}
}
else
{
reader.Skip();
}
}
}
catch (JsonException)
{
return false;
}

if (eventGridEventData.ValueKind == JsonValueKind.Object &&
eventGridEventData.TryGetProperty(SyncTokenPropertyName, out JsonElement syncTokenJson) &&
syncTokenJson.ValueKind == JsonValueKind.String)
if (syncToken == null)
{
pushNotification = new PushNotification()
{
SyncToken = syncTokenJson.GetString(),
EventType = eventGridEvent.EventType,
ResourceUri = resourceUri
};
return true;
return false;
}

pushNotification = new PushNotification()
{
SyncToken = syncToken,
EventType = eventGridEvent.EventType,
ResourceUri = resourceUri
};

return true;
}

return false;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ internal class ClientFilter

public JsonElement Parameters { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ internal class FeatureConditions

public string RequirementType { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ internal class FeatureFlag

public FeatureTelemetry Telemetry { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(Configura
{
ClientFilter clientFilter = featureFlag.Conditions.ClientFilters[i];

_featureFilterTracing.UpdateFeatureFilterTracing(clientFilter.Name);
_featureFilterTracing.UpdateFeatureFilterTracing(clientFilter.Name);

string clientFiltersPath = $"{featureFlagPath}:{FeatureManagementConstants.Conditions}:{FeatureManagementConstants.ClientFilters}:{i}";

Expand Down
Loading