Skip to content

Merge main to release/stable/v7 for 7.2.0 stable release #553

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 6 commits into from
May 1, 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
4 changes: 2 additions & 2 deletions examples/ConsoleAppWithFailOver/ConsoleAppWithFailOver.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

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

<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.10.2" />
<PackageReference Include="Azure.Identity" Version="1.11.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion examples/ConsoleApplication/ConsoleApplication.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<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 All @@ -21,7 +21,7 @@
<!-- Nuget Package Version Settings -->

<PropertyGroup>
<OfficialVersion>7.1.0</OfficialVersion>
<OfficialVersion>7.2.0</OfficialVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">
Expand All @@ -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 All @@ -24,7 +24,7 @@
<!-- Nuget Package Version Settings -->

<PropertyGroup>
<OfficialVersion>7.1.0</OfficialVersion>
<OfficialVersion>7.2.0</OfficialVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(CDP_PATCH_NUMBER)'!='' AND '$(CDP_BUILD_TYPE)'=='Official'">
Expand All @@ -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 @@ -29,22 +29,12 @@ public AzureKeyVaultKeyValueAdapter(AzureKeyVaultSecretProvider secretProvider)
/// returns the keyname and actual value
public async Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(ConfigurationSetting setting, 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 All @@ -102,5 +92,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 @@ -7,5 +7,8 @@ internal class ErrorMessages
{
public const string CacheExpirationTimeTooShort = "The cache expiration time cannot be less than {0} milliseconds.";
public const string SecretRefreshIntervalTooShort = "The secret refresh interval cannot be less than {0} milliseconds.";
public const string FeatureFlagInvalidJsonProperty = "Invalid property '{0}' for feature flag. Key: '{1}'. Found type: '{2}'. Expected type: '{3}'.";
public const string FeatureFlagInvalidFormat = "Invalid json format for feature flag. Key: '{0}'";
public const string InvalidKeyVaultReference = "Invalid Key Vault reference.";
}
}
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 @@ -2,16 +2,13 @@
// Licensed under the MIT license.
//
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.FeatureManagement
{
internal class ClientFilter
{
[JsonPropertyName("name")]
public string Name { get; set; }

[JsonPropertyName("parameters")]
public JsonElement Parameters { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
// Licensed under the MIT license.
//
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.FeatureManagement
{
internal class FeatureConditions
{
[JsonPropertyName("client_filters")]
public List<ClientFilter> ClientFilters { get; set; } = new List<ClientFilter>();

[JsonPropertyName("requirement_type")]
public string RequirementType { get; set; }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
//
using System.Text.Json.Serialization;

namespace Microsoft.Extensions.Configuration.AzureAppConfiguration.FeatureManagement
{
internal class FeatureFlag
{
[JsonPropertyName("id")]
public string Id { get; set; }

[JsonPropertyName("enabled")]
public bool Enabled { get; set; }

[JsonPropertyName("conditions")]
public FeatureConditions Conditions { get; set; }
}
}
}
Loading